Dasynq: merge changes from upstream.
authorDavin McCall <davmac@davmac.org>
Wed, 5 Jul 2017 20:04:36 +0000 (21:04 +0100)
committerDavin McCall <davmac@davmac.org>
Wed, 5 Jul 2017 20:04:36 +0000 (21:04 +0100)
src/dasynq/dasynq-itimer.h
src/dasynq/dasynq-timerfd.h

index d2599fbaf839fdaf1f3b04e83f3891e440fa1d1e..99f360f92e1c3de7b0486ca884f91f467411b9ed 100644 (file)
@@ -34,7 +34,7 @@ template <class Base> class ITimerEvents : public timer_base<Base>
     // if there are no active timers).
     void set_timer_from_queue()
     {
-        struct timespec newtime;
+        time_val newtime;
         struct itimerval newalarm;
         if (timer_queue.empty()) {
             newalarm.it_value = {0, 0};
@@ -47,14 +47,30 @@ template <class Base> class ITimerEvents : public timer_base<Base>
         
         struct timespec curtime;
         get_curtime(curtime);
-        newalarm.it_interval = {0, 0};
-        newalarm.it_value.tv_sec = newtime.tv_sec - curtime.tv_sec;
-        newalarm.it_value.tv_usec = (newtime.tv_nsec - curtime.tv_nsec) / 1000;
+        time_val curtimev = curtime;
 
-        if (newalarm.it_value.tv_usec < 0) {
-            newalarm.it_value.tv_usec += 1000000;
-            newalarm.it_value.tv_sec--;
+        newalarm.it_interval = {0, 0};
+        if (curtimev < newtime) {
+            newalarm.it_value.tv_sec = newtime.seconds() - curtime.tv_sec;
+            if (curtimev.nseconds() > newtime.nseconds()) {
+                newalarm.it_value.tv_usec = (1000000000 - curtimev.nseconds()
+                        + newtime.nseconds()) / 1000;
+                newalarm.it_value.tv_sec--;
+            }
+            else {
+                newalarm.it_value.tv_usec = (newtime.nseconds() - curtime.tv_nsec) / 1000;
+            }
         }
+        else {
+            // We passed the timeout: set alarm to expire immediately (we must use {0,1} as
+            // {0,0} disables the timer).
+            // TODO: it would be better if we just processed the appropriate timers here,
+            //       but that is complicated to get right especially if the event loop
+            //       is multi-threaded.
+            newalarm.it_value.tv_sec = 0;
+            newalarm.it_value.tv_usec = 1;
+        }
+
         setitimer(ITIMER_REAL, &newalarm, nullptr);
     }
     
@@ -73,7 +89,6 @@ template <class Base> class ITimerEvents : public timer_base<Base>
 
             // arm timerfd with timeout from head of queue
             set_timer_from_queue();
-            // loop_mech.rearmSignalWatch_nolock(SIGALRM);
             return false; // don't disable signal watch
         }
         else {
index d92ab0f090febf2db7949d1983a9f61cf7b9a6ef..032c5dae7f54eb161b3f3fe8bff56a1080860589 100644 (file)
@@ -155,10 +155,8 @@ template <class Base> class TimerFdEvents : public timer_base<Base>
     
     void removeTimer_nolock(timer_handle_t &timer_id, clock_type clock = clock_type::MONOTONIC) noexcept
     {
+        stop_timer_nolock(timer_id, clock);
         timer_queue_t & queue = get_queue(clock);
-        if (queue.is_queued(timer_id)) {
-            queue.remove(timer_id);
-        }
         queue.deallocate(timer_id);
     }
 
@@ -171,8 +169,13 @@ template <class Base> class TimerFdEvents : public timer_base<Base>
     void stop_timer_nolock(timer_handle_t &timer_id, clock_type clock = clock_type::MONOTONIC) noexcept
     {
         timer_queue_t & queue = get_queue(clock);
+        int fd = (clock == clock_type::MONOTONIC) ? timerfd_fd : systemtime_fd;
         if (queue.is_queued(timer_id)) {
+            bool was_first = (&timer_queue.get_root()) == &timer_id;
             queue.remove(timer_id);
+            if (was_first) {
+                set_timer_from_queue(fd, queue);
+            }
         }
     }