Utils/Termlib: Extend the completion API
[senf.git] / Scheduler / FIFORunner.cc
index b39b5c2..b57c66b 100644 (file)
@@ -40,7 +40,7 @@
 
 prefix_ senf::scheduler::detail::FIFORunner::FIFORunner()
     : tasks_ (), next_ (tasks_.end()), watchdogRunning_ (false), watchdogMs_ (1000), 
-      watchdogCount_(0), hangCount_ (0)
+      watchdogAbort_ (false), watchdogCount_(0), hangCount_ (0), yield_ (false)
 {
     struct sigevent ev;
     ::memset(&ev, 0, sizeof(ev));
@@ -75,18 +75,22 @@ prefix_ senf::scheduler::detail::FIFORunner::~FIFORunner()
 
 prefix_ void senf::scheduler::detail::FIFORunner::startWatchdog()
 {
-    struct itimerspec timer;
-    ::memset(&timer, 0, sizeof(timer));
-
-    timer.it_interval.tv_sec = watchdogMs_ / 1000;
-    timer.it_interval.tv_nsec = (watchdogMs_ % 1000) * 1000000ul;
-    timer.it_value.tv_sec = timer.it_interval.tv_sec;
-    timer.it_value.tv_nsec = timer.it_interval.tv_nsec;
+    if (watchdogMs_ > 0) {
+        struct itimerspec timer;
+        ::memset(&timer, 0, sizeof(timer));
 
-    if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
-        SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
+        timer.it_interval.tv_sec = watchdogMs_ / 1000;
+        timer.it_interval.tv_nsec = (watchdogMs_ % 1000) * 1000000ul;
+        timer.it_value.tv_sec = timer.it_interval.tv_sec;
+        timer.it_value.tv_nsec = timer.it_interval.tv_nsec;
+        
+        if (timer_settime(watchdogId_, 0, &timer, 0) < 0)
+            SENF_THROW_SYSTEM_EXCEPTION("timer_settime()");
 
-    watchdogRunning_ = true;
+        watchdogRunning_ = true;
+    }
+    else
+        stopWatchdog();
 }
 
 prefix_ void senf::scheduler::detail::FIFORunner::stopWatchdog()
@@ -132,17 +136,32 @@ prefix_ void senf::scheduler::detail::FIFORunner::dequeue(TaskInfo * task)
 
 prefix_ void senf::scheduler::detail::FIFORunner::run()
 {
-    TaskList::iterator f (tasks_.begin());
-    TaskList::iterator l (TaskList::current(highPriorityEnd_));
-    run(f, l);
+    for(;;) {
+        TaskList::iterator f (tasks_.begin());
+        TaskList::iterator l (TaskList::current(highPriorityEnd_));
+        run(f, l);
+        if (yield_) {
+            yield_ = false;
+            continue;
+        }
 
-    f = l; ++f;
-    l = TaskList::current(normalPriorityEnd_);
-    run(f, l);
-        
-    f = l; ++f;
-    l = tasks_.end();
-    run(f, l);
+        f = l; ++f;
+        l = TaskList::current(normalPriorityEnd_);
+        run(f, l); 
+        if (yield_) {
+            yield_ = false;
+            continue;
+        }
+       
+        f = l; ++f;
+        l = tasks_.end();
+        run(f, l);
+        if (yield_) {
+            yield_ = false;
+            continue;
+        }
+        break;
+    }
 }
 
 prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, TaskList::iterator l)
@@ -170,7 +189,7 @@ prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, Task
     ScopeExit atExit ((
                           var(watchdogCount_) = 0, 
                           var(next_) = l
-                          ));
+                     ));
     
     while (next_ != end) {
         TaskInfo & task (*next_);
@@ -184,7 +203,10 @@ prefix_ void senf::scheduler::detail::FIFORunner::run(TaskList::iterator f, Task
             ++ next_;
             tasks_.splice(l, tasks_, i);
             watchdogCount_ = 1;
+            yield_ = false;
             task.run();
+            if (yield_)
+                return;
         }
         else
             ++ next_;
@@ -220,6 +242,8 @@ prefix_ void senf::scheduler::detail::FIFORunner::watchdog(int, siginfo_t * si,
             write(1, runner.runningBacktrace_.c_str(), runner.runningBacktrace_.size());
 #endif
             write(1, "\n", 1);
+            if (runner.watchdogAbort_)
+                assert(false);
         }
     }
 }