Utils/Console: Add short help to 'ls' output
[senf.git] / Scheduler / Scheduler.cc
index 74761da..a79307a 100644 (file)
@@ -41,6 +41,7 @@
 
 namespace {
     bool terminate_ (false);
+    bool running_ (false);
 }
 
 prefix_ void senf::scheduler::terminate()
@@ -48,20 +49,60 @@ prefix_ void senf::scheduler::terminate()
     terminate_ = true;
 }
 
+prefix_ void senf::scheduler::yield()
+{
+    senf::scheduler::detail::FIFORunner::instance().yield();
+}
+
+prefix_ bool senf::scheduler::running()
+{
+    return running_;
+}
+
+prefix_ senf::ClockService::clock_type senf::scheduler::now()
+{
+    return running() ? eventTime() : ClockService::now();
+}
+
+namespace {
+    
+    // We don't want try { } catch(...) { ... throw; } since that will make debugging more
+    // difficult: the stack backtrace for an unexpected exception would always end here.
+    struct SchedulerScopedInit
+    {
+        SchedulerScopedInit() 
+            {
+                senf::scheduler::detail::FIFORunner::instance().startWatchdog();
+                senf::scheduler::detail::SignalDispatcher::instance().unblockSignals();
+                senf::scheduler::detail::TimerDispatcher::instance().enable();
+                running_ = true;
+            }
+
+        ~SchedulerScopedInit()
+            {
+                senf::scheduler::detail::TimerDispatcher::instance().disable();
+                senf::scheduler::detail::SignalDispatcher::instance().blockSignals();
+                senf::scheduler::detail::FIFORunner::instance().stopWatchdog();
+                running_ = false;
+            }
+    };
+}
+
 prefix_ void senf::scheduler::process()
 {
+    SchedulerScopedInit initScheduler;
     terminate_ = false;
+    running_ = true;
+    detail::TimerDispatcher::instance().reschedule();
     while(! terminate_ && ! (detail::FdDispatcher::instance().empty() &&
                              detail::TimerDispatcher::instance().empty() &&
                              detail::FileDispatcher::instance().empty())) {
-        detail::SignalDispatcher::instance().unblockSignals();
-        detail::TimerDispatcher::instance().unblockSignals();
         detail::FdManager::instance().processOnce();
-        detail::TimerDispatcher::instance().blockSignals();
-        detail::SignalDispatcher::instance().blockSignals();
         detail::FileDispatcher::instance().prepareRun();
-        detail::EventEventDispatcher::instance().prepareRun();
+        detail::EventHookDispatcher::instance().prepareRun();
+        detail::TimerDispatcher::instance().prepareRun();
         detail::FIFORunner::instance().run();
+        detail::TimerDispatcher::instance().reschedule();
     }
 }
 
@@ -73,9 +114,9 @@ prefix_ void senf::scheduler::restart()
     detail::TimerDispatcher*      tdd (&detail::TimerDispatcher::instance());
     detail::SignalDispatcher*     sdd (&detail::SignalDispatcher::instance());
     detail::FileDispatcher*       fld (&detail::FileDispatcher::instance());
-    detail::EventEventDispatcher* eed (&detail::EventEventDispatcher::instance());
+    detail::EventHookDispatcher*  eed (&detail::EventHookDispatcher::instance());
 
-    eed->~EventEventDispatcher();
+    eed->~EventHookDispatcher();
     fld->~FileDispatcher();
     sdd->~SignalDispatcher();
     tdd->~TimerDispatcher();
@@ -89,7 +130,7 @@ prefix_ void senf::scheduler::restart()
     new (tdd) detail::TimerDispatcher();
     new (sdd) detail::SignalDispatcher();
     new (fld) detail::FileDispatcher();
-    new (eed) detail::EventEventDispatcher();
+    new (eed) detail::EventHookDispatcher();
 }
 
 prefix_ bool senf::scheduler::empty()
@@ -98,7 +139,19 @@ prefix_ bool senf::scheduler::empty()
         && detail::TimerDispatcher::instance().empty()
         && detail::FileDispatcher::instance().empty()
         && detail::SignalDispatcher::instance().empty()
-        && detail::EventEventDispatcher::instance().empty();
+        && detail::EventHookDispatcher::instance().empty();
+}
+
+prefix_ void senf::scheduler::hiresTimers()
+{
+#ifdef HAVE_TIMERFD
+    if (haveScalableHiresTimers())
+        detail::TimerDispatcher::instance().timerSource(
+            std::auto_ptr<detail::TimerSource>(new detail::TimerFDTimerSource()));
+    else
+#endif
+        detail::TimerDispatcher::instance().timerSource(
+            std::auto_ptr<detail::TimerSource>(new detail::POSIXTimerSource()));
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -110,6 +163,33 @@ prefix_ senf::log::time_type senf::scheduler::LogTimeSource::operator()()
     return eventTime();
 }
 
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::BlockSignals
+
+prefix_ senf::scheduler::BlockSignals::BlockSignals(bool initiallyBlocked)
+    : blocked_ (false)
+{
+    ::sigfillset(&allSigs_);
+    if (initiallyBlocked)
+        block();
+}
+
+prefix_ void senf::scheduler::BlockSignals::block()
+{
+    if (blocked_)
+        return;
+    ::sigprocmask(SIG_BLOCK, &allSigs_, &savedSigs_);
+    blocked_ = true;
+}
+
+prefix_ void senf::scheduler::BlockSignals::unblock()
+{
+    if (!blocked_)
+        return;
+    ::sigprocmask(SIG_SETMASK, &savedSigs_, 0);
+    blocked_ = false;
+}
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_