Author: lubosd
Date: Sun Apr 20 12:56:52 2014
New Revision: 37805

URL: http://svn.gna.org/viewcvs/gnustep?rev=37805&view=rev
Log:
    * Source/CFRunLoop.c,
      Tests/CFRunLoop/timers.m: CFRunLoop timer fixes and tests


Added:
    libs/corebase/trunk/Tests/CFRunLoop/timers.m
Modified:
    libs/corebase/trunk/ChangeLog
    libs/corebase/trunk/Source/CFRunLoop.c

Modified: libs/corebase/trunk/ChangeLog
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/corebase/trunk/ChangeLog?rev=37805&r1=37804&r2=37805&view=diff
==============================================================================
--- libs/corebase/trunk/ChangeLog       (original)
+++ libs/corebase/trunk/ChangeLog       Sun Apr 20 12:56:52 2014
@@ -1,3 +1,7 @@
+2014-04-20 Lubos Dolezel <[email protected]>
+       * Source/CFRunLoop.c,
+         Tests/CFRunLoop/timers.m: CFRunLoop timer fixes and tests
+
 2014-04-18 Lubos Dolezel <[email protected]>
        * Source/CFRunLoop.c,
          Tests/CFRunLoop/source.m: CFRunLoop impl that passes the test

Modified: libs/corebase/trunk/Source/CFRunLoop.c
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/corebase/trunk/Source/CFRunLoop.c?rev=37805&r1=37804&r2=37805&view=diff
==============================================================================
--- libs/corebase/trunk/Source/CFRunLoop.c      (original)
+++ libs/corebase/trunk/Source/CFRunLoop.c      Sun Apr 20 12:56:52 2014
@@ -37,6 +37,7 @@
 #      include <unistd.h>
 #      include <fcntl.h>
 #      include <poll.h>
+#      include <limits.h>
 #endif
 #ifdef HAVE_LIBDISPATCH
 #      include <dispatch/dispatch.h>
@@ -363,6 +364,8 @@
                                         0, &kCFTypeDictionaryKeyCallBacks,
                                         NULL);
 
+  CFSetAddValue(rl->_commonModes, kCFRunLoopDefaultMode);
+  
   pipe(rl->_wakeUpPipe);
   fcntl(rl->_wakeUpPipe[0], F_SETFL, O_NONBLOCK);
   fcntl(rl->_wakeUpPipe[1], F_SETFL, O_NONBLOCK);
@@ -415,7 +418,7 @@
   do
     {
       code = CFRunLoopRunInMode (kCFRunLoopDefaultMode, DISTANT_FUTURE, false);
-    } while (code != kCFRunLoopRunFinished || code != kCFRunLoopRunStopped);
+    } while (code != kCFRunLoopRunFinished && code != kCFRunLoopRunStopped);
 }
 
 static void
@@ -477,15 +480,12 @@
   for (i = 0; i < count; i++)
     {
       CFRunLoopTimerRef timer = timers[i];
-
-      if (timer->_nextFireDate < now)
+      
+      if (timer->_isValid && (timer->_nextFireDate < now || fabs(now - 
timer->_nextFireDate) < 0.001))
         {
           hadTimer = true;
           timer->_callback(timer, timer->_context.info);
-        }
-
-      if (timer->_isValid)
-        {
+
           // Compute the next time
           if (timer->_interval <= 0)
             timer->_isValid = false;
@@ -697,6 +697,7 @@
           if (nextTimer < DISTANT_FUTURE)
             {
               int delay = (int) ( (nextTimer - timeNow)*1000 );
+              // printf("(%f-%f)*1000=%d\n", nextTimer, timeNow, delay);
               if (timeout == -1 || delay < timeout)
                 timeout = delay;
               if (timeout < 0)
@@ -719,6 +720,7 @@
       CFRunLoopNotifyObservers(rl, context, kCFRunLoopBeforeWaiting);
       rl->_isWaiting = true;
 
+      // printf("poll: %d ms\n", timeout);
       sourcesFired = poll(pfd, numSources, timeout);
 
       rl->_isWaiting = false;
@@ -736,6 +738,7 @@
           if (pfd[0].revents != 0)
             {
               int dummy;
+              // printf("loop woken up!\n");
 
               // Remove everything from the notification pipe that woke us up
               while (read(pfd[0].fd, &dummy, sizeof(dummy)) > 0);
@@ -749,9 +752,10 @@
             }
 #endif
 
-          hadSource |= CFRunLoopProcessTimers(rl, timeNow, context);
-          hadSource |= CFRunLoopProcessSourcesVersion0(rl, timeNow, context);
-        }
+        }
+        
+      hadSource |= CFRunLoopProcessTimers(rl, timeNow, context);
+      hadSource |= CFRunLoopProcessSourcesVersion0(rl, timeNow, context);
 
       if (returnAfterSourceHandled && hadSource)
         {
@@ -1421,11 +1425,13 @@
   GSRunLoopContextRef context = GSRunLoopContextGet(rl, mode);
   
   count = CFArrayGetCount(context->timers);
+  // printf("Current time: %f\n", CFAbsoluteTimeGetCurrent());
 
   for (i = 0; i < count; i++)
     {
       CFRunLoopTimerRef timer = (CFRunLoopTimerRef) 
CFArrayGetValueAtIndex(context->timers, i);
 
+      // printf("Timer %p valid:%d nextFireDate:%f\n", timer, timer->_isValid, 
timer->_nextFireDate);
       if (timer->_isValid)
         {
           if (timer->_nextFireDate < rv)

Added: libs/corebase/trunk/Tests/CFRunLoop/timers.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/corebase/trunk/Tests/CFRunLoop/timers.m?rev=37805&view=auto
==============================================================================
--- libs/corebase/trunk/Tests/CFRunLoop/timers.m        (added)
+++ libs/corebase/trunk/Tests/CFRunLoop/timers.m        Sun Apr 20 12:56:52 2014
@@ -0,0 +1,78 @@
+#include <CoreFoundation/CFRunLoop.h>
+
+#include "../CFTesting.h"
+#include <pthread.h>
+#include <unistd.h>
+
+int timesTimer1Fired = 0, timesTimer2Fired = 0;
+void timerCallback(CFRunLoopTimerRef timer, void *info);
+void timerCallback2(CFRunLoopTimerRef timer, void *info);
+void* createSecondTimerThread(void* p);
+
+int main()
+{
+       // Test plan:
+       // Create a repeated timer, check if it repeats and invalidate it after 
2 repeats.
+       // Asynchronously, while the runloop is waiting, plan another, 
singleshot timer
+       // to see, if the runloop reschedules correctly.
+       // After all timers are invalid, the runloop should exit.
+       
+       CFRunLoopRef rl;
+       CFRunLoopTimerRef timer1;
+       
+       rl = CFRunLoopGetMain ();
+       PASS_CF(rl != NULL, "Got main run loop.");
+       
+       timer1 = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + 1, 1,
+                                       0, 0, timerCallback, NULL);
+       
+       CFRunLoopAddTimer(rl, timer1, kCFRunLoopCommonModes);
+       CFRelease(timer1);
+       
+       CFRunLoopRun();
+       PASS_CF(timesTimer1Fired == 2, "Timer 1 fired twice and loop exited");
+       
+       return 0;
+}
+
+void timerCallback(CFRunLoopTimerRef timer, void *info)
+{
+       timesTimer1Fired++;
+       
+       printf("Timer 1 fired...\n");
+       
+       if (timesTimer1Fired == 1)
+       {
+               pthread_t thread;
+               pthread_create(&thread, NULL, createSecondTimerThread, NULL);
+               
+       }
+       else if (timesTimer1Fired >= 2)
+               CFRunLoopTimerInvalidate(timer);
+}
+
+void timerCallback2(CFRunLoopTimerRef timer, void *info)
+{
+       printf("Timer 2 fired\n");
+       PASS_CF(timesTimer1Fired == 1, "Timer 2 fired while timer 1 fired only 
once");
+       
+       timesTimer2Fired++;
+       
+       PASS_CF(timesTimer2Fired == 1, "Timer 2 fires only once");
+}
+
+void* createSecondTimerThread(void* p)
+{
+       CFRunLoopRef rl = CFRunLoopGetMain ();
+       CFRunLoopTimerRef timer2;
+       
+       while (!CFRunLoopIsWaiting(rl))
+               usleep(10*1000);
+       
+       timer2 = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + 0.25, 
0,
+                                       0, 0, timerCallback2, NULL);
+       CFRunLoopAddTimer(rl, timer2, kCFRunLoopCommonModes);
+       CFRelease(timer2);
+       
+       return NULL;
+}


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to