Scheduler: Implement new timer event API
g0dil [Wed, 17 Sep 2008 08:41:16 +0000 (08:41 +0000)]
Scheduler: Move task 'name' argument to constructor
Scheduler: Remove obsolete 'enabled_' members
Scheduler: Remove obsolete SchedulerTimer class

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@907 270642c3-0616-0410-b53a-bc976706d245

35 files changed:
Console/Server.cc
Console/Server.hh
PPI/IdleEvent.cc
PPI/IdleEvent.cci
PPI/IdleEvent.hh
PPI/IntervalTimer.cc
PPI/IntervalTimer.cci
PPI/IntervalTimer.hh
PPI/SocketSink.test.cc
PPI/SocketSource.test.cc
Scheduler/FIFORunner.cc
Scheduler/FIFORunner.cci
Scheduler/FIFORunner.hh
Scheduler/FdDispatcher.cc
Scheduler/FdDispatcher.hh
Scheduler/FdDispatcher.ih
Scheduler/FileDispatcher.cc
Scheduler/FileDispatcher.hh
Scheduler/Scheduler.cc
Scheduler/Scheduler.cci
Scheduler/Scheduler.hh
Scheduler/Scheduler.test.cc
Scheduler/SignalEvent.cci
Scheduler/SignalEvent.hh
Scheduler/Timer.cci [deleted file]
Scheduler/Timer.hh [deleted file]
Scheduler/TimerDispatcher.cci [deleted file]
Scheduler/TimerDispatcher.hh [deleted file]
Scheduler/TimerEvent.cc [moved from Scheduler/TimerDispatcher.cc with 56% similarity]
Scheduler/TimerEvent.cci [new file with mode: 0644]
Scheduler/TimerEvent.hh [new file with mode: 0644]
Scheduler/TimerEvent.ih [new file with mode: 0644]
Scheduler/TimerEvent.test.cc [moved from Scheduler/TimerDispatcher.test.cc with 53% similarity]
Utils/Daemon/Daemon.cc
Utils/Daemon/Daemon.ih

index 3ef80ba..3148e76 100644 (file)
@@ -224,8 +224,10 @@ prefix_ senf::console::Client::Client(Server & server, ClientHandle handle)
     : out_t(boost::ref(*this)), senf::log::IOStreamTarget(out_t::member), server_ (server),
       handle_ (handle), 
       binding_ (handle, boost::bind(&Client::setNoninteractive,this), Scheduler::EV_READ, false),
-      timer_ (Scheduler::instance().eventTime() + ClockService::milliseconds(INTERACTIVE_TIMEOUT),
-              boost::bind(&Client::setInteractive, this), false),
+      timer_ ("senf::console::Client interactive timeout", 
+              boost::bind(&Client::setInteractive, this),
+              Scheduler::instance().eventTime() + ClockService::milliseconds(INTERACTIVE_TIMEOUT),
+              false),
       name_ (server.name()), reader_ (), mode_ (server.mode())
 {
     handle_.facet<senf::TCPSocketProtocol>().nodelay();
index b7684d5..66426a0 100644 (file)
@@ -36,7 +36,6 @@
 #include "../Socket/ServerSocketHandle.hh"
 #include "../Scheduler/Scheduler.hh"
 #include "../Scheduler/Binding.hh"
-#include "../Scheduler/Timer.hh"
 #include "../Scheduler/ReadHelper.hh"
 #include "Parse.hh"
 #include "Executor.hh"
@@ -197,7 +196,7 @@ namespace console {
         Server & server_;
         ClientHandle handle_;
         SchedulerBinding binding_;
-        SchedulerTimer timer_;
+        scheduler::TimerEvent timer_;
         CommandParser parser_;
         Executor executor_;
         std::string name_;
index 37077bb..4c98ad5 100644 (file)
 
 prefix_ void senf::ppi::IdleEvent::v_enable()
 {
-    id_ = Scheduler::instance().timeout(manager().now(), boost::bind(&IdleEvent::cb,this));
+    timer_.timeout(manager().now());
 }
 
 prefix_ void senf::ppi::IdleEvent::v_disable()
 {
-    Scheduler::instance().cancelTimeout(id_);
-    id_ = 0;
+    timer_.disable();
 }
 
 prefix_ void senf::ppi::IdleEvent::cb()
index 41ccf87..898c14b 100644 (file)
@@ -32,7 +32,7 @@
 // senf::ppi::IdleEvent
 
 prefix_ senf::ppi::IdleEvent::IdleEvent()
-    : id_(0)
+    : timer_ ("PPI idle event", boost::bind(&IdleEvent::cb,this))
 {}
 
 ///////////////////////////////cci.e///////////////////////////////////////
index 6a70510..51656ea 100644 (file)
@@ -56,7 +56,7 @@ namespace ppi {
 
         void cb();
         
-        unsigned id_;
+        scheduler::TimerEvent timer_;
     };
 
 }}
index 507567e..f0dafd1 100644 (file)
@@ -49,14 +49,13 @@ prefix_ void senf::ppi::IntervalTimer::v_enable()
 
 prefix_ void senf::ppi::IntervalTimer::v_disable()
 {
-    Scheduler::instance().cancelTimeout(id_);
-    id_ = 0;
+    timer_.disable();
 }
 
 prefix_ void senf::ppi::IntervalTimer::schedule()
 {
     info_.expected = info_.intervalStart + ( interval_ * (info_.number+1) ) / eventsPerInterval_;
-    id_ = Scheduler::instance().timeout(info_.expected, boost::bind(&IntervalTimer::cb,this));
+    timer_.timeout(info_.expected);
 }
 
 prefix_ void senf::ppi::IntervalTimer::cb()
index f38316a..35c7ce2 100644 (file)
@@ -33,7 +33,8 @@
 
 prefix_ senf::ppi::IntervalTimer::IntervalTimer(ClockService::clock_type interval,
                                                 unsigned eventsPerInterval)
-    : interval_ (interval), eventsPerInterval_ (eventsPerInterval)
+    : interval_ (interval), eventsPerInterval_ (eventsPerInterval),
+      timer_("PPI interval timer",  boost::bind(&IntervalTimer::cb,this))
 {}
 
 ///////////////////////////////cci.e///////////////////////////////////////
index 0e55aa5..1763f35 100644 (file)
@@ -82,7 +82,7 @@ namespace ppi {
         ClockService::clock_type interval_;
         unsigned eventsPerInterval_;
         IntervalTimerEventInfo info_;
-        unsigned id_;
+        scheduler::TimerEvent timer_;
     };
 
 }}
index 0114565..d2b9435 100644 (file)
@@ -84,8 +84,9 @@ BOOST_AUTO_UNIT_TEST(activeSocketSink)
 
     senf::UDPv4ClientSocketHandle inputSocket;
     inputSocket.bind(senf::INet4SocketAddress("localhost:44344"));
-    senf::Scheduler::instance().timeout(
-        senf::ClockService::now() + senf::ClockService::milliseconds(100), &timeout);
+    senf::scheduler::TimerEvent timer (
+        "activeSocketSink test timer", &timeout,
+        senf::ClockService::now() + senf::ClockService::milliseconds(100));
     source.submit(p);
     senf::ppi::run();
 
index d1f6263..bb1c59d 100644 (file)
@@ -64,8 +64,9 @@ BOOST_AUTO_UNIT_TEST(socketSource)
 
     senf::UDPv4ClientSocketHandle outputSocket;
     outputSocket.writeto(senf::INet4SocketAddress("localhost:44344"),data);
-    senf::Scheduler::instance().timeout(
-        senf::ClockService::now() + senf::ClockService::milliseconds(100), &timeout);
+    senf::scheduler::TimerEvent timer (
+        "socketSource test timer", &timeout,
+        senf::ClockService::now() + senf::ClockService::milliseconds(100));
     senf::ppi::run();
 
     BOOST_REQUIRE( ! sink.empty() );
index 7fbd9df..0e5d5be 100644 (file)
@@ -101,6 +101,7 @@ namespace {
     struct NullTask 
         : public senf::scheduler::FIFORunner::TaskInfo
     {
+        NullTask() : senf::scheduler::FIFORunner::TaskInfo ("<null>") {}
         void run() {};
     };
 }
index 6d2f52a..4bea7ba 100644 (file)
@@ -34,8 +34,8 @@
 #define prefix_ inline
 ///////////////////////////////cci.p///////////////////////////////////////
 
-prefix_ senf::scheduler::FIFORunner::TaskInfo::TaskInfo()
-    : runnable (false)
+prefix_ senf::scheduler::FIFORunner::TaskInfo::TaskInfo(std::string const & name_)
+    : runnable (false), name (name_)
 {}
 
 prefix_ senf::scheduler::FIFORunner::TaskInfo::~TaskInfo()
index 756f07f..2c04bc6 100644 (file)
@@ -73,7 +73,7 @@ namespace scheduler {
         struct TaskInfo 
             : public TaskListBase
         {
-            TaskInfo();
+            explicit TaskInfo(std::string const & name_);
             virtual ~TaskInfo();
 
             bool runnable;              ///< Runnable flag
index 4103b51..4d8007b 100644 (file)
@@ -54,25 +54,19 @@ prefix_ bool senf::scheduler::FdDispatcher::add(std::string const & name, int fd
     
     FdMap::iterator i (fds_.find(fd));
     if (i == fds_.end()) {
-        i = fds_.insert(std::make_pair(fd, FdEvent())).first;
+        i = fds_.insert(std::make_pair(fd, FdEvent(name))).first;
         runner_.enqueue(static_cast<FdEvent::ReadTask*>(&i->second));
         runner_.enqueue(static_cast<FdEvent::PrioTask*>(&i->second));
         runner_.enqueue(static_cast<FdEvent::WriteTask*>(&i->second));
     }
     FdEvent & event (i->second);
 
-    if (events & EV_READ) {
+    if (events & EV_READ) 
         event.FdEvent::ReadTask::cb = cb;
-        event.FdEvent::ReadTask::name = name;
-    }
-    if (events & EV_PRIO) {
+    if (events & EV_PRIO) 
         event.FdEvent::PrioTask::cb = cb;
-        event.FdEvent::PrioTask::name = name;
-    }
-    if (events & EV_WRITE) {
+    if (events & EV_WRITE) 
         event.FdEvent::WriteTask::cb = cb;
-        event.FdEvent::WriteTask::name = name;
-    }
 
     if (! manager_.set(fd, event.activeEvents(), &event)) {
         runner_.dequeue(static_cast<FdEvent::ReadTask*>(&i->second));
@@ -95,18 +89,12 @@ prefix_ void senf::scheduler::FdDispatcher::remove(int fd, int events)
         return;
     FdEvent & event (i->second);
 
-    if (events & EV_READ) {
+    if (events & EV_READ) 
         event.FdEvent::ReadTask::cb = 0;
-        event.FdEvent::ReadTask::name.clear();
-    }
-    if (events & EV_PRIO) {
+    if (events & EV_PRIO) 
         event.FdEvent::PrioTask::cb = 0;
-        event.FdEvent::PrioTask::name.clear();
-    }
-    if (events & EV_WRITE) {
+    if (events & EV_WRITE)
         event.FdEvent::WriteTask::cb = 0;
-        event.FdEvent::WriteTask::name.clear();
-    }
 
     int activeEvents (event.activeEvents());
     if (! activeEvents) {
index affc61d..bfca398 100644 (file)
@@ -97,6 +97,9 @@ namespace scheduler {
             typedef detail::FdTask<1, FdEvent> PrioTask;
             typedef detail::FdTask<2, FdEvent> WriteTask;
 
+            explicit FdEvent(std::string const & name)
+                : ReadTask (name), PrioTask (name), WriteTask (name) {}
+
             virtual void signal(int events);
             int activeEvents() const;
             int events;
index 42d3c85..b0c1c01 100644 (file)
@@ -43,6 +43,9 @@ namespace detail {
     struct FdTask
         : public FIFORunner::TaskInfo
     {
+        explicit FdTask(std::string const & name) 
+            : FIFORunner::TaskInfo (name) {}
+
         typedef boost::function<void (int)> Callback;
         virtual void run();
         Self & self();
index 780335c..6ada898 100644 (file)
@@ -55,20 +55,16 @@ prefix_ void senf::scheduler::FileDispatcher::add(std::string const & name, int
     
     FileMap::iterator i (files_.find(fd));
     if (i == files_.end()) {
-        i = files_.insert(std::make_pair(fd, FileEvent())).first;
+        i = files_.insert(std::make_pair(fd, FileEvent(name))).first;
         runner_.enqueue(static_cast<FileEvent::ReadTask*>(&i->second));
         runner_.enqueue(static_cast<FileEvent::WriteTask*>(&i->second));
     }
     FileEvent & event (i->second);
 
-    if (events & EV_READ) {
+    if (events & EV_READ)
         event.FileEvent::ReadTask::cb = cb;
-        event.FileEvent::ReadTask::name = name;
-    }
-    if (events & EV_WRITE) {
+    if (events & EV_WRITE)
         event.FileEvent::WriteTask::cb = cb;
-        event.FileEvent::WriteTask::name = name;
-    }
     
     manager_.timeout(0);
 }
index 4bff54d..f81e3df 100644 (file)
@@ -109,6 +109,9 @@ namespace scheduler {
             typedef detail::FdTask<0, FileEvent> ReadTask;
             typedef detail::FdTask<1, FileEvent> WriteTask;
 
+            explicit FileEvent(std::string const & name)
+                : ReadTask (name), WriteTask (name) {}
+
             int activeEvents() const;
             int events;
         };
index 1bfd963..1d0a107 100644 (file)
@@ -44,12 +44,12 @@ prefix_ void senf::Scheduler::process()
 {
     terminate_ = false;
     while(! terminate_ && ! (fdDispatcher_.empty() &&
-                             timerDispatcher_.empty() &&
+                             scheduler::detail::TimerDispatcher::instance().empty() &&
                              fileDispatcher_.empty())) {
         scheduler::detail::SignalDispatcher::instance().unblockSignals();
-        timerDispatcher_.unblockSignals();
+        scheduler::detail::TimerDispatcher::instance().unblockSignals();
         scheduler::FdManager::instance().processOnce();
-        timerDispatcher_.blockSignals();
+        scheduler::detail::TimerDispatcher::instance().blockSignals();
         scheduler::detail::SignalDispatcher::instance().blockSignals();
         fileDispatcher_.prepareRun();
         scheduler::FIFORunner::instance().run();
@@ -61,7 +61,7 @@ prefix_ void senf::Scheduler::restart()
     scheduler::FdManager* fdm (&scheduler::FdManager::instance());
     scheduler::FIFORunner* ffr (&scheduler::FIFORunner::instance());
     scheduler::FdDispatcher* fdd (&fdDispatcher_);
-    scheduler::TimerDispatcher* td (&timerDispatcher_);
+    scheduler::detail::TimerDispatcher* td (&scheduler::detail::TimerDispatcher::instance());
     scheduler::detail::SignalDispatcher* sd (&scheduler::detail::SignalDispatcher::instance());
     scheduler::FileDispatcher* fld (&fileDispatcher_);
     
@@ -75,7 +75,7 @@ prefix_ void senf::Scheduler::restart()
     new (fdm) scheduler::FdManager();
     new (ffr) scheduler::FIFORunner();
     new (fdd) scheduler::FdDispatcher(*fdm, *ffr);
-    new (td) scheduler::TimerDispatcher(*fdm, *ffr);
+    new (td) scheduler::detail::TimerDispatcher();
     new (sd) scheduler::detail::SignalDispatcher();
     new (fld) scheduler::FileDispatcher(*fdm, *ffr);
 }
index 94cd693..27f463e 100644 (file)
@@ -67,52 +67,6 @@ prefix_ int senf::retrieve_filehandle(int fd)
     return fd;
 }
 
-prefix_ senf::Scheduler::timer_id senf::Scheduler::timeout(ClockService::clock_type timeout,
-                                                           SimpleCallback const & cb)
-{
-    return timerDispatcher_.add("<anon timer>", timeout, cb);
-}
-
-prefix_ senf::Scheduler::timer_id senf::Scheduler::timeout(std::string const & name,
-                                                           ClockService::clock_type timeout,
-                                                           SimpleCallback const & cb)
-{
-    return timerDispatcher_.add(name, timeout, cb);
-}
-
-prefix_ void senf::Scheduler::cancelTimeout(timer_id id)
-{
-    timerDispatcher_.remove(id);
-}
-
-prefix_ senf::ClockService::clock_type senf::Scheduler::timeoutEarly()
-    const
-{
-    SENF_LOG( (senf::log::IMPORTANT) 
-              ("timeoutEarly() is deprecated and a no-op. It will be removed") );
-    return 0;
-}
-
-prefix_ void senf::Scheduler::timeoutEarly(ClockService::clock_type v)
-{
-    SENF_LOG( (senf::log::IMPORTANT) 
-              ("timeoutEarly() is deprecated and a no-op. It will be removed") );
-}
-
-prefix_ senf::ClockService::clock_type senf::Scheduler::timeoutAdjust()
-    const
-{
-    SENF_LOG( (senf::log::IMPORTANT) 
-              ("timeoutAdjust() is deprecated and a no-op. It will be removed") );
-    return 0;
-}
-
-prefix_ void senf::Scheduler::timeoutAdjust(ClockService::clock_type v)
-{
-    SENF_LOG( (senf::log::IMPORTANT) 
-              ("timeoutAdjust() is deprecated and a no-op. It will be removed") );
-}
-
 prefix_ void senf::Scheduler::terminate()
 {
     terminate_ = true;
@@ -144,7 +98,6 @@ prefix_ unsigned senf::Scheduler::hangCount()
 prefix_ senf::Scheduler::Scheduler()
     : terminate_ (false), 
       fdDispatcher_ (scheduler::FdManager::instance(), scheduler::FIFORunner::instance()),
-      timerDispatcher_ (scheduler::FdManager::instance(), scheduler::FIFORunner::instance()),
       fileDispatcher_ (scheduler::FdManager::instance(), scheduler::FIFORunner::instance())
 {}
 
index 7c4dbcb..c0c02bc 100644 (file)
@@ -30,7 +30,7 @@
 // Custom includes
 #include "../Utils/Logger/SenfLog.hh"
 #include "FdDispatcher.hh"
-#include "TimerDispatcher.hh"
+#include "TimerEvent.hh"
 #include "SignalEvent.hh"
 #include "FileDispatcher.hh"
 #include "../Utils/Logger/SenfLog.hh"
@@ -189,9 +189,6 @@ namespace senf {
         /** \brief Callback type for signal events */
         typedef boost::function<void (siginfo_t const &)> SignalCallback;
 
-        /** \brief Timer id type */
-        typedef scheduler::TimerDispatcher::timer_id timer_id;
-
         ///////////////////////////////////////////////////////////////////////////
         ///\name Structors and default members
         ///@{
@@ -253,35 +250,6 @@ namespace senf {
 
         ///\}
 
-        ///\name Timeouts
-        ///\{
-
-        timer_id timeout(std::string const & name, ClockService::clock_type timeout, 
-                         SimpleCallback const & cb); 
-                                        ///< Add timeout event
-                                        /**< \returns timer id
-                                             \param[in] name descriptive name to identify the
-                                                 callback.
-                                             \param[in] timeout timeout in nanoseconds
-                                             \param[in] cb callback to call after \a timeout
-                                                 milliseconds */
-
-        timer_id timeout(ClockService::clock_type timeout, SimpleCallback const & cb); 
-                                        ///< Add timeout event
-                                        /**< \see timeout() */
-
-        void cancelTimeout(timer_id id); ///< Cancel timeout \a id
-
-#ifndef DOXYGEN
-        ClockService::clock_type timeoutEarly() const;
-        void timeoutEarly(ClockService::clock_type v);
-
-        ClockService::clock_type timeoutAdjust() const;
-        void timeoutAdjust(ClockService::clock_type v);
-#endif
-
-        ///\}
-
         void process();                 ///< Event handler main loop
                                         /**< This member must be called at some time to enter the
                                              event handler main loop. Only while this function is
@@ -319,7 +287,6 @@ namespace senf {
         bool terminate_;
 
         scheduler::FdDispatcher fdDispatcher_;
-        scheduler::TimerDispatcher timerDispatcher_;
         scheduler::FileDispatcher fileDispatcher_;
     };
 
index 3bd241d..9efd343 100644 (file)
@@ -247,28 +247,34 @@ BOOST_AUTO_UNIT_TEST(testScheduler)
     BOOST_REQUIRE_EQUAL( size, 4 );
     buffer[size]=0;
     BOOST_CHECK_EQUAL( buffer, "READ" );
-
-    event = Scheduler::EV_NONE;
-    BOOST_CHECK_NO_THROW( Scheduler::instance().timeout(
-                              ClockService::now()+ClockService::milliseconds(200),&timeout) );
-    BOOST_CHECK_NO_THROW( Scheduler::instance().timeout(
-                              ClockService::now()+ClockService::milliseconds(400),&timeout) );
-    ClockService::clock_type t (ClockService::now());
-    BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
-    BOOST_CHECK_PREDICATE( is_close, (ClockService::now()-t) (ClockService::milliseconds(200)) );
-    BOOST_CHECK( timeoutCalled );
-    BOOST_CHECK_EQUAL( event, Scheduler::EV_NONE );
-    BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (Scheduler::instance().eventTime()) );
-    timeoutCalled = false;
-    BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
-    BOOST_CHECK_PREDICATE( is_close, (ClockService::now()-t) (ClockService::milliseconds(400)) );
-    BOOST_CHECK( timeoutCalled );
-    BOOST_CHECK_EQUAL( event, Scheduler::EV_NONE );
-
-    BOOST_WARN_MESSAGE( false, "A 'Scheduler task hanging' error is expected to be signaled here." );
-    BOOST_CHECK_NO_THROW( Scheduler::instance().timeout(ClockService::now(), &blockingHandler) );
-    BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
-    BOOST_CHECK_EQUAL( Scheduler::instance().hangCount(), 1u );
+    
+    {
+        senf::scheduler::TimerEvent timer1 ("testTimer1", &timeout, 
+                                            ClockService::now()+ClockService::milliseconds(200));
+        senf::scheduler::TimerEvent timer2 ("testTimer2", &timeout,
+                                            ClockService::now()+ClockService::milliseconds(400));
+                                            
+        event = Scheduler::EV_NONE;
+        ClockService::clock_type t (ClockService::now());
+        BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
+        BOOST_CHECK_PREDICATE( is_close, (ClockService::now()-t) (ClockService::milliseconds(200)) );
+        BOOST_CHECK( timeoutCalled );
+        BOOST_CHECK( ! timer1.enabled() );
+        BOOST_CHECK_EQUAL( event, Scheduler::EV_NONE );
+        BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (Scheduler::instance().eventTime()) );
+        timeoutCalled = false;
+        BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
+        BOOST_CHECK_PREDICATE( is_close, (ClockService::now()-t) (ClockService::milliseconds(400)) );
+        BOOST_CHECK( timeoutCalled );
+        BOOST_CHECK_EQUAL( event, Scheduler::EV_NONE );
+        BOOST_CHECK( ! timer2.enabled() );
+
+        BOOST_WARN_MESSAGE( false, "A 'Scheduler task hanging' error is expected to be signaled here." );
+        BOOST_CHECK_NO_THROW( timer1.action(&blockingHandler) );
+        BOOST_CHECK_NO_THROW( timer1.timeout(ClockService::now()) );
+        BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
+        BOOST_CHECK_EQUAL( Scheduler::instance().hangCount(), 1u );
+    }
 
     HandleWrapper handle(sock,"TheTag");
     BOOST_CHECK_NO_THROW( Scheduler::instance().add(handle,
@@ -290,20 +296,19 @@ BOOST_AUTO_UNIT_TEST(testScheduler)
     BOOST_CHECK_EQUAL( buffer, "OK" );
     BOOST_CHECK_NO_THROW( Scheduler::instance().remove(handle) );
 
-    unsigned tid (Scheduler::instance().timeout(
-                      ClockService::now()+ClockService::milliseconds(400),&timeout));
     {
+        senf::scheduler::TimerEvent timer ("testWatchdog", &timeout,
+                                           ClockService::now()+ClockService::milliseconds(400));
         senf::scheduler::SignalEvent sig (SIGUSR1, &sigusr);
 
-        t = ClockService::now();
+        ClockService::clock_type t = ClockService::now();
         ::kill(::getpid(), SIGUSR1);
         delay(100);
         BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); 
         BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (t+ClockService::milliseconds(200)) );
         BOOST_CHECK_PREDICATE( is_close, (sigtime) (t+ClockService::milliseconds(200)) );
+        BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); 
     } 
-    BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); 
-    BOOST_CHECK_NO_THROW( Scheduler::instance().cancelTimeout(tid) );
 
     ///////////////////////////////////////////////////////////////////////////
 
index 3a0407e..df29dd7 100644 (file)
@@ -56,44 +56,39 @@ prefix_ bool senf::scheduler::detail::SignalDispatcher::empty()
 ///////////////////////////////////////////////////////////////////////////
 // senf::scheduler::SignalEvent
 
-prefix_ senf::scheduler::SignalEvent::SignalEvent(int signal, Callback cb,
+prefix_ senf::scheduler::SignalEvent::SignalEvent(int signal, Callback const & cb,
                                                   bool initiallyEnabled)
-    : signal_ (signal), enabled_ (initiallyEnabled), cb_ (cb)
+    : FIFORunner::TaskInfo(signalName(signal)), signal_ (signal), cb_ (cb)
 {
-    name = signalName(signal);
-    if (enabled_)
-        senf::scheduler::detail::SignalDispatcher::instance().add(*this);
+    if (initiallyEnabled)
+        enable();
 }
 
 prefix_ senf::scheduler::SignalEvent::~SignalEvent()
 {
     if (senf::scheduler::detail::SignalDispatcher::alive())
-        senf::scheduler::detail::SignalDispatcher::instance().remove(*this);
+        disable();
 }
 
 prefix_ void senf::scheduler::SignalEvent::disable()
 {
-    if (enabled_) {
+    if (detail::SignalSetBase::linked())
         senf::scheduler::detail::SignalDispatcher::instance().remove(*this);
-        enabled_ = false;
-    }
 }
 
 prefix_ void senf::scheduler::SignalEvent::enable()
 {
-    if (! enabled_) {
+    if (! detail::SignalSetBase::linked())
         senf::scheduler::detail::SignalDispatcher::instance().add(*this);
-        enabled_ = true;
-    }
 }
 
 prefix_ bool senf::scheduler::SignalEvent::enabled()
     const
 {
-    return enabled_;
+    return detail::SignalSetBase::linked();
 }
 
-prefix_ void senf::scheduler::SignalEvent::action(Callback cb)
+prefix_ void senf::scheduler::SignalEvent::action(Callback const & cb)
 {
     cb_ = cb;
 }
index a21c460..e5f2add 100644 (file)
@@ -74,7 +74,7 @@ namespace scheduler {
         ///\name Structors and default members
         ///@{
 
-        SignalEvent(int signal, Callback cb, bool initiallyEnabled=true);
+        SignalEvent(int signal, Callback const & cb, bool initiallyEnabled=true);
                                         ///< Register a signal event
                                         /**< Registers \a cb as callback for the UNIX signal \a
                                              signal. If \a initiallyEnabled is set \c false, the
@@ -92,13 +92,12 @@ namespace scheduler {
         void disable();                 ///< Enable signal event registration
         void enable();                  ///< Disable the signal event registration
         bool enabled() const;           ///< \c true, if event enabled, \c false otherwise
-        void action(Callback cb);       ///< Change signal event callback
+        void action(Callback const & cb); ///< Change signal event callback
 
     private:
         virtual void run();
         
         int signal_;
-        bool enabled_;
         Callback cb_;
         siginfo_t siginfo_;
 
diff --git a/Scheduler/Timer.cci b/Scheduler/Timer.cci
deleted file mode 100644 (file)
index dad761c..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-/** \file
-    \brief Timer inline non-template implementation */
-
-//#include "Timer.ih"
-
-// Custom includes
-
-#define prefix_ inline
-///////////////////////////////cci.p///////////////////////////////////////
-
-prefix_ senf::SchedulerTimer::SchedulerTimer(ClockService::clock_type timeout,
-                                             Scheduler::SimpleCallback const & cb,
-                                             bool enabled)
-    : timeout_ (timeout), cb_ (cb), 
-      id_ (enabled ? Scheduler::instance().timeout(timeout_, cb_) : 0), 
-      enabled_ (enabled)
-{}
-
-prefix_ void senf::SchedulerTimer::enable()
-{
-    if (!enabled_) {
-        id_ = Scheduler::instance().timeout(timeout_, cb_);
-        enabled_ = true;
-    }
-}
-
-prefix_ void senf::SchedulerTimer::disable()
-{
-    if (enabled_) {
-        Scheduler::instance().cancelTimeout(id_);
-        enabled_ = false;
-    }
-}
-
-prefix_ bool senf::SchedulerTimer::enabled()
-{
-    return enabled_;
-}
-
-prefix_ void senf::SchedulerTimer::update(ClockService::clock_type timeout)
-{
-    if (enabled_)
-        Scheduler::instance().cancelTimeout(id_);
-    timeout_ = timeout;
-    if (enabled_)
-        Scheduler::instance().timeout(timeout_, cb_);
-}
-
-prefix_ senf::SchedulerTimer::~SchedulerTimer()
-{
-    disable();
-}
-
-///////////////////////////////cci.e///////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/Timer.hh b/Scheduler/Timer.hh
deleted file mode 100644 (file)
index 93dbf43..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-/** \file
-    \brief Timer public header */
-
-#ifndef HH_Timer_
-#define HH_Timer_ 1
-
-// Custom includes
-#include "Scheduler.hh"
-
-//#include "Timer.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
-
-namespace senf {
-
-    /** \brief Manage scheduler timer
-
-        This class will manage a single timer: The timer can be enabled, disabled and updated and
-        will automatically be removed, when this instance is destroyed.
-
-        \code
-        class Foo
-        {
-        public:
-            Foo() : timer_ ( ClockServer::now() + ClockService::milliseconds(500),
-                             senf::membind(&Foo::timer, this) ) {}
-
-            void blarf() { timer_.disable(); }
-        
-        private:
-            void timer(); 
-        
-            senf::SchedulerTimer timer_;
-        };
-        \endcode
-      */
-    class SchedulerTimer
-        : boost::noncopyable
-    {
-    public:
-        ///////////////////////////////////////////////////////////////////////////
-        ///\name Structors and default members
-        ///@{
-
-        SchedulerTimer(ClockService::clock_type timeout, Scheduler::SimpleCallback const & cb,
-                       bool enabled=true);
-        ~SchedulerTimer();
-
-        ///@}
-        ///////////////////////////////////////////////////////////////////////////
-
-        void enable();                  ///< Enable timer
-        void disable();                 ///< Disable timer
-        bool enabled();                 ///< \c true, if timer is currently enabled
-                                        /**< An expired timer can still be in enabled state. */
-
-        void update(ClockService::clock_type timeout); ///< Change timeout time and enable timer
-                                        /**< If the timer is not enabled, you need to call enable()
-                                             for the timer to become effective. */
-
-    protected:
-
-    private:
-        ClockService::clock_type timeout_;
-        Scheduler::SimpleCallback cb_;
-        unsigned id_;
-        bool enabled_;
-    };
-
-}
-
-///////////////////////////////hh.e////////////////////////////////////////
-#include "Timer.cci"
-//#include "Timer.ct"
-//#include "Timer.cti"
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/TimerDispatcher.cci b/Scheduler/TimerDispatcher.cci
deleted file mode 100644 (file)
index 6e8e9e6..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-/** \file
-    \brief TimerDispatcher inline non-template implementation */
-
-//#include "TimerDispatcher.ih"
-
-// Custom includes
-#include <unistd.h>
-
-#define prefix_ inline
-///////////////////////////////cci.p///////////////////////////////////////
-
-prefix_ senf::scheduler::TimerDispatcher::TimerEvent::TimerEvent(timer_id id_,
-                                                                 Callback const & cb_,
-                                                                 TimerDispatcher & dispatcher_,
-                                                                 std::string const & n)
-    : id (id_), cb (cb_), dispatcher (dispatcher_)
-{
-    name = n;    
-}
-
-prefix_ bool senf::scheduler::TimerDispatcher::empty()
-    const
-{
-    return timers_.empty();
-}
-
-///////////////////////////////cci.e///////////////////////////////////////
-#undef prefix_
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
diff --git a/Scheduler/TimerDispatcher.hh b/Scheduler/TimerDispatcher.hh
deleted file mode 100644 (file)
index 7b6f92a..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-// $Id$
-//
-// Copyright (C) 2008 
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
-//     Stefan Bund <g0dil@berlios.de>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the
-// Free Software Foundation, Inc.,
-// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-/** \file
-    \brief TimerDispatcher public header */
-
-#ifndef HH_TimerDispatcher_
-#define HH_TimerDispatcher_ 1
-
-// Custom includes
-#include <signal.h>
-#include <set>
-#include <map>
-#include "ClockService.hh"
-#include "FdManager.hh"
-#include "FIFORunner.hh"
-#include "../Utils/Logger/SenfLog.hh"
-
-//#include "TimerDispatcher.mpp"
-///////////////////////////////hh.p////////////////////////////////////////
-
-namespace senf {
-namespace scheduler {
-
-    /** \brief Scheduler dispatcher managing timers
-
-        Timers are implemented using high-precision POSIX real-time timers. As such, the timer
-        granularity is given by clock_getres(CLOCK_MONOTONIC) which is 1ns on current linux kernels.
-
-        \implementation TimerDispatcher manages a single POSIX timer which is always programmed to
-            expire when the next scheduled timer needs to fire. The timer sends a signal (SIGALRM is
-            used). The handler writes data into a pipe which is has been added to the FdManager.
-      */
-    class TimerDispatcher
-        : public FdManager::Event
-    {
-        SENF_LOG_CLASS_AREA();
-
-    public:
-        ///////////////////////////////////////////////////////////////////////////
-        // Types
-
-        typedef boost::function<void ()> Callback;
-        typedef unsigned timer_id;
-
-        ///////////////////////////////////////////////////////////////////////////
-        ///\name Structors and default members
-        ///@{
-
-        TimerDispatcher(FdManager & manager, FIFORunner & runner);
-        ~TimerDispatcher();
-
-        ///@}
-        ///////////////////////////////////////////////////////////////////////////
-
-        timer_id add(std::string const & name, ClockService::clock_type timeout, 
-                     Callback const & cb);
-                                        ///< Add timer event
-                                        /**< This call adds a new timer expiring at the given point
-                                             in time.
-                                             \param[in] name descriptive name
-                                             \param[in] timeout point in time when the timer is to
-                                                 expire 
-                                             \param[in] cb callback 
-                                             \returns a \c timer_id which can be used to remove the
-                                                 timer. */
-        void remove(timer_id id);       ///< Remove timer
-
-        void unblockSignals();          ///< Unblock internal signals
-                                        /**< Must be called before waiting for an event */
-        void blockSignals();            ///< Block internal signals
-                                        /**< Must be called directly after the FdManager returns */
-        
-        bool empty() const;             ///< \c true, if no timer is registered.
-
-    protected:
-
-    private:
-        /// Internal: Timer event
-        struct TimerEvent
-            : public FIFORunner::TaskInfo
-        {
-            TimerEvent(timer_id id_, Callback const & cb_, TimerDispatcher & dispatcher_,
-                       std::string const & name);
-            virtual void run();
-
-            timer_id id;
-            Callback cb;
-            TimerDispatcher & dispatcher;
-        };
-
-        virtual void signal(int events);
-        static void sigHandler(int signal, ::siginfo_t * siginfo, void *);
-        void reschedule();
-
-        FdManager & manager_;
-        FIFORunner & runner_;
-
-        typedef std::multimap<ClockService::clock_type, TimerEvent> TimerMap;
-        typedef std::map<int, TimerMap::iterator> TimerIdMap;
-
-        TimerMap timers_;
-        TimerIdMap timerIdIndex_;
-        timer_id lastId_;
-
-        int timerPipe_[2];
-        sigset_t sigSet_;
-        bool blocked_;
-        timer_t timerId_;
-
-        static unsigned useCount_;
-    };
-
-}}
-
-///////////////////////////////hh.e////////////////////////////////////////
-#include "TimerDispatcher.cci"
-//#include "TimerDispatcher.ct"
-//#include "TimerDispatcher.cti"
-#endif
-
-\f
-// Local Variables:
-// mode: c++
-// fill-column: 100
-// comment-column: 40
-// c-file-style: "senf"
-// indent-tabs-mode: nil
-// ispell-local-dictionary: "american"
-// compile-command: "scons -u test"
-// End:
similarity index 56%
rename from Scheduler/TimerDispatcher.cc
rename to Scheduler/TimerEvent.cc
index 520500d..1a49800 100644 (file)
 /** \file
     \brief TimerDispatcher non-inline non-template implementation */
 
-#include "TimerDispatcher.hh"
-//#include "TimerDispatcher.ih"
+#include "TimerEvent.hh"
+#include "TimerEvent.ih"
 
 // Custom includes
 
-//#include "TimerDispatcher.mpp"
+//#include "TimerEvent.mpp"
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
-unsigned senf::scheduler::TimerDispatcher::useCount_ (0);
-
-prefix_ senf::scheduler::TimerDispatcher::TimerDispatcher(FdManager & manager,
-                                                          FIFORunner & runner)
-    : manager_ (manager), runner_ (runner), lastId_ (0), blocked_ (true)
+prefix_ senf::scheduler::detail::TimerDispatcher::TimerDispatcher()
+    : blocked_ (true)
 {
     if (pipe(timerPipe_) < 0)
         SENF_THROW_SYSTEM_EXCEPTION("pipe()");
-    manager_.set(timerPipe_[0], FdManager::EV_READ, this);
+    senf::scheduler::FdManager::instance().set(timerPipe_[0], FdManager::EV_READ, this);
 
     sigemptyset(&sigSet_);
     sigaddset(&sigSet_, SIGALRM);
     sigprocmask(SIG_BLOCK, &sigSet_, 0);
 
-    if (useCount_ == 0) {
-        struct sigaction act;
-        act.sa_sigaction = &sigHandler;
-        act.sa_mask = sigSet_;
-        act.sa_flags = SA_SIGINFO | SA_RESTART;
-        if (sigaction(SIGALRM, &act, 0) < 0)
-            SENF_THROW_SYSTEM_EXCEPTION("sigaction()");
-    }
+    struct sigaction act;
+    act.sa_sigaction = &sigHandler;
+    act.sa_mask = sigSet_;
+    act.sa_flags = SA_SIGINFO | SA_RESTART;
+    if (sigaction(SIGALRM, &act, 0) < 0)
+        SENF_THROW_SYSTEM_EXCEPTION("sigaction()");
 
     struct sigevent ev;
     ::memset(&ev, 0, sizeof(ev));
@@ -62,55 +57,43 @@ prefix_ senf::scheduler::TimerDispatcher::TimerDispatcher(FdManager & manager,
     ev.sigev_value.sival_ptr = this;
     if (timer_create(CLOCK_MONOTONIC, &ev, &timerId_) < 0)
         SENF_THROW_SYSTEM_EXCEPTION("timer_create()");
-    
-    ++ useCount_;
 }
 
-prefix_ senf::scheduler::TimerDispatcher::~TimerDispatcher()
+prefix_ senf::scheduler::detail::TimerDispatcher::~TimerDispatcher()
 {
-    -- useCount_;
-
-    TimerMap::iterator i (timers_.begin());
-    TimerMap::iterator const i_end (timers_.end());
+    TimerSet::iterator i (timers_.begin());
+    TimerSet::iterator const i_end (timers_.end());
     for (; i != i_end; ++i)
-        runner_.dequeue(&(i->second));
+        senf::scheduler::FIFORunner::instance().dequeue(&(*i));
 
     timer_delete(timerId_);
-    if (useCount_ == 0)
-        ::signal(SIGALRM, SIG_IGN);
+    ::signal(SIGALRM, SIG_IGN);
     sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
-    manager_.remove(timerPipe_[0]);
+    senf::scheduler::FdManager::instance().remove(timerPipe_[0]);
     close(timerPipe_[0]);
     close(timerPipe_[1]);
 }
 
-prefix_ senf::scheduler::TimerDispatcher::timer_id
-senf::scheduler::TimerDispatcher::add(std::string const & name,
-                                      ClockService::clock_type timeout, Callback const & cb)
+void senf::scheduler::detail::TimerDispatcher::add(TimerEvent & event)
 {
-    while (timerIdIndex_.find(++lastId_) != timerIdIndex_.end()) ;
-    TimerMap::iterator i (
-        timers_.insert(std::make_pair(timeout, TimerEvent(lastId_, cb, *this, name))));
-    timerIdIndex_.insert(std::make_pair(lastId_, i));
-    runner_.enqueue(&(i->second));
+    TimerSet::iterator i (timers_.insert(event));
+    senf::scheduler::FIFORunner::instance().enqueue(&(*i));
     if (! blocked_)
         reschedule();
-    return lastId_;
 }
 
-prefix_ void senf::scheduler::TimerDispatcher::remove(timer_id id)
+prefix_ void senf::scheduler::detail::TimerDispatcher::remove(TimerEvent & event)
 {
-    TimerIdMap::iterator i (timerIdIndex_.find(id));
-    if (i == timerIdIndex_.end())
+    TimerSet::iterator i (TimerSet::current(event));
+    if (i == timers_.end())
         return;
-    runner_.dequeue(&(i->second->second));
-    timers_.erase(i->second);
-    timerIdIndex_.erase(i);
+    senf::scheduler::FIFORunner::instance().dequeue(&(*i));
+    timers_.erase(i);
     if (! blocked_)
         reschedule();
 }
 
-prefix_ void senf::scheduler::TimerDispatcher::blockSignals()
+prefix_ void senf::scheduler::detail::TimerDispatcher::blockSignals()
 {
     if (blocked_) 
         return;
@@ -118,7 +101,7 @@ prefix_ void senf::scheduler::TimerDispatcher::blockSignals()
     blocked_ = true;
 }
 
-prefix_ void senf::scheduler::TimerDispatcher::unblockSignals()
+prefix_ void senf::scheduler::detail::TimerDispatcher::unblockSignals()
 {
     if (! blocked_)
         return;
@@ -127,21 +110,21 @@ prefix_ void senf::scheduler::TimerDispatcher::unblockSignals()
     blocked_ = false;
 }
 
-prefix_ void senf::scheduler::TimerDispatcher::signal(int events)
+prefix_ void senf::scheduler::detail::TimerDispatcher::signal(int events)
 {
     siginfo_t info;
     if (read(timerPipe_[0], &info, sizeof(info)) < int(sizeof(info)))
         return;
-
-    TimerMap::iterator i (timers_.begin());
-    TimerMap::iterator const i_end (timers_.end());
-    ClockService::clock_type now (manager_.eventTime());
-    for (; i != i_end && i->first <= now ; ++i)
-        i->second.runnable = true;
+    TimerSet::iterator i (timers_.begin());
+    TimerSet::iterator const i_end (timers_.end());
+    ClockService::clock_type now (senf::scheduler::FdManager::instance().eventTime());
+    for (; i != i_end && i->timeout_ <= now ; ++i)
+        i->runnable = true;
 }
 
-prefix_ void senf::scheduler::TimerDispatcher::sigHandler(int signal, ::siginfo_t * siginfo,
-                                                          void *)
+prefix_ void senf::scheduler::detail::TimerDispatcher::sigHandler(int signal, 
+                                                                  ::siginfo_t * siginfo,
+                                                                  void *)
 {
     // The manpage says, si_signo is unused in linux so we set it here
     siginfo->si_signo = signal; 
@@ -152,7 +135,7 @@ prefix_ void senf::scheduler::TimerDispatcher::sigHandler(int signal, ::siginfo_
           siginfo, sizeof(*siginfo));
 }
 
-prefix_ void senf::scheduler::TimerDispatcher::reschedule()
+prefix_ void senf::scheduler::detail::TimerDispatcher::reschedule()
 {
     struct itimerspec timer;
     memset(&timer, 0, sizeof(timer));
@@ -164,7 +147,7 @@ prefix_ void senf::scheduler::TimerDispatcher::reschedule()
         timer.it_value.tv_nsec = 0;
     }
     else {
-        ClockService::clock_type next (timers_.begin()->first);
+        ClockService::clock_type next (timers_.begin()->timeout_);
         if (next <= 0)
             next = 1;
         timer.it_value.tv_sec = ClockService::in_seconds(next);
@@ -178,21 +161,17 @@ prefix_ void senf::scheduler::TimerDispatcher::reschedule()
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::TimerDispatcher::TimerEvent
+// senf::scheduler::detail::TimerDispatcher::TimerEvent
 
-prefix_ void senf::scheduler::TimerDispatcher::TimerEvent::run()
+prefix_ void senf::scheduler::TimerEvent::run()
 {
-    Callback savedCb (cb);
-    dispatcher.remove(id);
-    // The member is now running WITHOUT AN OBJECT ... that has been destroyed above !!!!!!  On the
-    // other hand, if we do things the other way round, we have no idea, whether the callback might
-    // explicitly remove us and we have the same problem then ...
-    savedCb();
+    disable();
+    cb_();
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
-//#include "TimerDispatcher.mpp"
+//#include "TimerEvent.mpp"
 
 \f
 // Local Variables:
diff --git a/Scheduler/TimerEvent.cci b/Scheduler/TimerEvent.cci
new file mode 100644 (file)
index 0000000..0dffcd9
--- /dev/null
@@ -0,0 +1,108 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief TimerDispatcher inline non-template implementation */
+
+#include "TimerEvent.ih"
+
+// Custom includes
+#include <unistd.h>
+
+#define prefix_ inline
+///////////////////////////////cci.p///////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::TimerEvent
+
+prefix_ senf::scheduler::TimerEvent::TimerEvent(std::string const & name, Callback const & cb,
+                                                ClockService::clock_type timeout,
+                                                bool initiallyEnabled)
+    : FIFORunner::TaskInfo (name), cb_ (cb), timeout_ (timeout)
+{
+    if (initiallyEnabled)
+        enable();
+}
+
+prefix_ senf::scheduler::TimerEvent::TimerEvent(std::string const & name, Callback const & cb)
+    : FIFORunner::TaskInfo (name), cb_ (cb), timeout_ (0)
+{}
+
+prefix_ senf::scheduler::TimerEvent::~TimerEvent()
+{
+    if (senf::scheduler::detail::TimerDispatcher::alive())
+        disable();
+}
+
+prefix_ void senf::scheduler::TimerEvent::enable()
+{
+    if (! detail::TimerSetBase::linked())
+        senf::scheduler::detail::TimerDispatcher::instance().add(*this);
+}
+
+prefix_ void senf::scheduler::TimerEvent::disable()
+{
+    if (detail::TimerSetBase::linked())
+        senf::scheduler::detail::TimerDispatcher::instance().remove(*this);
+}
+
+prefix_ bool senf::scheduler::TimerEvent::enabled()
+{
+    return detail::TimerSetBase::linked();
+}
+
+prefix_ void senf::scheduler::TimerEvent::action(Callback const & cb)
+{
+    cb_ = cb;
+}
+
+prefix_ void senf::scheduler::TimerEvent::timeout(ClockService::clock_type timeout, 
+                                                  bool initiallyEnabled)
+{
+    disable();
+    timeout_ = timeout;
+    if (initiallyEnabled)
+        enable();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::scheduler::detail::TimerDispatcher
+
+prefix_ bool senf::scheduler::detail::TimerDispatcher::empty()
+    const
+{
+    return timers_.empty();
+}
+
+///////////////////////////////cci.e///////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Scheduler/TimerEvent.hh b/Scheduler/TimerEvent.hh
new file mode 100644 (file)
index 0000000..b0a4ae5
--- /dev/null
@@ -0,0 +1,106 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief TimerDispatcher public header */
+
+#ifndef HH_TimerDispatcher_
+#define HH_TimerDispatcher_ 1
+
+// Custom includes
+#include <signal.h>
+#include "../boost/intrusive/iset_hook.hpp"
+#include "ClockService.hh"
+#include "FdManager.hh"
+#include "FIFORunner.hh"
+#include "../Utils/Logger/SenfLog.hh"
+
+//#include "TimerEvent.mpp"
+///////////////////////////////hh.p////////////////////////////////////////
+
+namespace senf {
+namespace scheduler {
+
+    namespace detail {
+        struct TimerSetTag;
+        typedef boost::intrusive::iset_base_hook<TimerSetTag> TimerSetBase;
+        struct TimerSetCompare;
+        class TimerDispatcher;
+    }
+
+    class TimerEvent
+        : public FIFORunner::TaskInfo,
+          public detail::TimerSetBase
+    {
+    public:
+        ///////////////////////////////////////////////////////////////////////////
+        // Types
+
+        typedef boost::function<void ()> Callback;
+
+        ///////////////////////////////////////////////////////////////////////////
+        ///\name Structors and default members
+        ///@{
+
+        TimerEvent(std::string const & name, Callback const & cb, ClockService::clock_type timeout,
+                   bool initiallyEnabled = true);
+        TimerEvent(std::string const & name, Callback const & cb);
+        ~TimerEvent();
+
+        ///@}
+        ///////////////////////////////////////////////////////////////////////////
+
+        void enable();
+        void disable();
+        bool enabled();
+
+        void action(Callback const & cb);
+        void timeout(ClockService::clock_type timeout, bool enable=true);
+
+    private:
+        virtual void run();
+
+        Callback cb_;
+        ClockService::clock_type timeout_;
+
+        friend class detail::TimerDispatcher;
+        friend class detail::TimerSetCompare;
+    };
+
+}}
+
+///////////////////////////////hh.e////////////////////////////////////////
+#include "TimerEvent.cci"
+//#include "TimerEvent.ct"
+//#include "TimerEvent.cti"
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
diff --git a/Scheduler/TimerEvent.ih b/Scheduler/TimerEvent.ih
new file mode 100644 (file)
index 0000000..8bae8d1
--- /dev/null
@@ -0,0 +1,103 @@
+// $Id$
+//
+// Copyright (C) 2008 
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+//     Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+/** \file
+    \brief TimerDispatcher internal header */
+
+#ifndef IH_TimerDispatcher_
+#define IH_TimerDispatcher_ 1
+
+// Custom includes
+#include "../boost/intrusive/iset.hpp"
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+
+    class Scheduler;
+
+namespace scheduler {
+namespace detail {
+
+    struct TimerSetCompare {
+        bool operator()(TimerEvent const & a, TimerEvent const & b) const
+            { return a.timeout_ < b.timeout_; }
+    };
+
+    class TimerDispatcher
+        : public FdManager::Event,
+          public singleton<TimerDispatcher>
+    {
+        SENF_LOG_CLASS_AREA();
+        
+        typedef boost::intrusive::imultiset< TimerSetBase::value_traits<TimerEvent>,
+                                             TimerSetCompare,
+                                             false > TimerSet;
+
+    public:
+        using singleton<TimerDispatcher>::instance;
+        using singleton<TimerDispatcher>::alive;
+
+        void add(TimerEvent & event);
+        void remove(TimerEvent & event);
+
+        void unblockSignals();
+        void blockSignals();
+        
+        bool empty() const;
+
+    protected:
+
+    private:
+        TimerDispatcher();
+        ~TimerDispatcher();
+
+        virtual void signal(int events);
+        static void sigHandler(int signal, ::siginfo_t * siginfo, void *);
+        void reschedule();
+
+        TimerSet timers_;
+
+        int timerPipe_[2];
+        sigset_t sigSet_;
+        bool blocked_;
+        timer_t timerId_;
+
+        friend class senf::Scheduler;
+        friend class singleton<TimerDispatcher>;
+    };
+
+}}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
similarity index 53%
rename from Scheduler/TimerDispatcher.test.cc
rename to Scheduler/TimerEvent.test.cc
index 2795a8a..e7f777e 100644 (file)
 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 /** \file
-    \brief TimerDispatcher.test unit tests */
+    \brief TimerEvent.test unit tests */
 
-//#include "TimerDispatcher.test.hh"
-//#include "TimerDispatcher.test.ih"
+//#include "TimerEvent.test.hh"
+//#include "TimerEvent.test.ih"
 
 // Custom includes
-#include "TimerDispatcher.hh"
+#include "TimerEvent.hh"
 
 #include "../Utils//auto_unit_test.hh"
 #include <boost/test/test_tools.hpp>
@@ -52,32 +52,35 @@ namespace {
 
 BOOST_AUTO_UNIT_TEST(timerDispatcher)
 {
-    senf::scheduler::TimerDispatcher dispatcher (senf::scheduler::FdManager::instance(), senf::scheduler::FIFORunner::instance());
     senf::scheduler::FdManager::instance().timeout(1000);
 
     senf::ClockService::clock_type t (senf::ClockService::now());
-    senf::scheduler::TimerDispatcher::timer_id id;
-    SENF_CHECK_NO_THROW(
-        id = dispatcher.add( "testTimer", t + senf::ClockService::milliseconds(500), &handler ) );
-    SENF_CHECK_NO_THROW( dispatcher.unblockSignals() );
-    SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
-    SENF_CHECK_NO_THROW( dispatcher.blockSignals() );
-    SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
-    senf::ClockService::clock_type t2 (senf::ClockService::now());
-    BOOST_CHECK( called );
-    BOOST_CHECK_PREDICATE( is_close, (t2-t)(senf::ClockService::milliseconds(500)) );
-
-    SENF_CHECK_NO_THROW( dispatcher.remove(id) );
+    {
+        senf::scheduler::TimerEvent timer ("testTimer", &handler, 
+                                           t + senf::ClockService::milliseconds(500));
+        SENF_CHECK_NO_THROW( timer.disable() );
+        SENF_CHECK_NO_THROW( timer.enable() );
+        BOOST_CHECK( timer.enabled() );
+        SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().unblockSignals() );
+        SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+        SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().blockSignals() );
+        SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+        senf::ClockService::clock_type t2 (senf::ClockService::now());
+        BOOST_CHECK( called );
+        BOOST_CHECK( ! timer.enabled() );
+        BOOST_CHECK_PREDICATE( is_close, (t2-t)(senf::ClockService::milliseconds(500)) );
 
-    called=false;
-    t = senf::ClockService::now();
-    SENF_CHECK_NO_THROW( dispatcher.add( "testTimer", t, &handler ) );
-    SENF_CHECK_NO_THROW( dispatcher.unblockSignals() );
-    SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
-    SENF_CHECK_NO_THROW( dispatcher.blockSignals() );
-    SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
-    BOOST_CHECK_PREDICATE( is_close, (t) (senf::ClockService::now()) );
-    BOOST_CHECK( called );
+        called=false;
+        t = senf::ClockService::now();
+        SENF_CHECK_NO_THROW( timer.timeout(t) );
+        BOOST_CHECK( timer.enabled() );
+        SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().unblockSignals() );
+        SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+        SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().blockSignals() );
+        SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+        BOOST_CHECK_PREDICATE( is_close, (t) (senf::ClockService::now()) );
+        BOOST_CHECK( called );
+    }
 }
 
 ///////////////////////////////cc.e////////////////////////////////////////
index 19673af..89dbcec 100644 (file)
@@ -563,6 +563,7 @@ prefix_ senf::detail::DaemonWatcher::DaemonWatcher(int pid, int coutpipe, int ce
     : childPid_(pid), coutpipe_(coutpipe), cerrpipe_(cerrpipe), stdout_(stdout),
       stderr_(stderr), sigChld_(false),
       cldSignal_ (SIGCHLD, senf::membind(&DaemonWatcher::sigChld, this)),
+      timer_ ("DaemanWatcher watchdog", senf::membind(&DaemonWatcher::childOk, this)),
       coutForwarder_(coutpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 1)), 
       cerrForwarder_(cerrpipe_, boost::bind(&DaemonWatcher::pipeClosed, this, 2)) 
 {
@@ -594,9 +595,7 @@ prefix_ void senf::detail::DaemonWatcher::pipeClosed(int id)
             childDied(); // does not return
         if (::kill(childPid_, SIGUSR1) < 0 && errno != ESRCH)
             SENF_THROW_SYSTEM_EXCEPTION("::kill()");
-        Scheduler::instance().timeout(
-            Scheduler::instance().eventTime() + ClockService::seconds(1),
-            senf::membind(&DaemonWatcher::childOk, this));
+        timer_.timeout(Scheduler::instance().eventTime() + ClockService::seconds(1));
     }
 }
 
index 3dec5e2..795008a 100644 (file)
@@ -95,6 +95,7 @@ namespace detail {
         bool sigChld_;
 
         scheduler::SignalEvent cldSignal_;
+        scheduler::TimerEvent timer_;
         Forwarder coutForwarder_;
         Forwarder cerrForwarder_;
     };