: 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();
#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"
Server & server_;
ClientHandle handle_;
SchedulerBinding binding_;
- SchedulerTimer timer_;
+ scheduler::TimerEvent timer_;
CommandParser parser_;
Executor executor_;
std::string name_;
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()
// senf::ppi::IdleEvent
prefix_ senf::ppi::IdleEvent::IdleEvent()
- : id_(0)
+ : timer_ ("PPI idle event", boost::bind(&IdleEvent::cb,this))
{}
///////////////////////////////cci.e///////////////////////////////////////
void cb();
- unsigned id_;
+ scheduler::TimerEvent timer_;
};
}}
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()
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///////////////////////////////////////
ClockService::clock_type interval_;
unsigned eventsPerInterval_;
IntervalTimerEventInfo info_;
- unsigned id_;
+ scheduler::TimerEvent timer_;
};
}}
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();
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() );
struct NullTask
: public senf::scheduler::FIFORunner::TaskInfo
{
+ NullTask() : senf::scheduler::FIFORunner::TaskInfo ("<null>") {}
void run() {};
};
}
#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()
struct TaskInfo
: public TaskListBase
{
- TaskInfo();
+ explicit TaskInfo(std::string const & name_);
virtual ~TaskInfo();
bool runnable; ///< Runnable flag
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));
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) {
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;
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();
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);
}
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;
};
{
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();
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_);
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);
}
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;
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())
{}
// 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"
/** \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
///@{
///\}
- ///\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
bool terminate_;
scheduler::FdDispatcher fdDispatcher_;
- scheduler::TimerDispatcher timerDispatcher_;
scheduler::FileDispatcher fileDispatcher_;
};
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,
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) );
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// 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;
}
///\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
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_;
+++ /dev/null
-// $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:
+++ /dev/null
-// $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:
+++ /dev/null
-// $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:
+++ /dev/null
-// $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:
/** \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));
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;
blocked_ = true;
}
-prefix_ void senf::scheduler::TimerDispatcher::unblockSignals()
+prefix_ void senf::scheduler::detail::TimerDispatcher::unblockSignals()
{
if (! blocked_)
return;
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;
siginfo, sizeof(*siginfo));
}
-prefix_ void senf::scheduler::TimerDispatcher::reschedule()
+prefix_ void senf::scheduler::detail::TimerDispatcher::reschedule()
{
struct itimerspec timer;
memset(&timer, 0, sizeof(timer));
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);
}
///////////////////////////////////////////////////////////////////////////
-// 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:
--- /dev/null
+// $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:
--- /dev/null
+// $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:
--- /dev/null
+// $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:
// 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>
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////////////////////////////////////////
: 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))
{
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));
}
}
bool sigChld_;
scheduler::SignalEvent cldSignal_;
+ scheduler::TimerEvent timer_;
Forwarder coutForwarder_;
Forwarder cerrForwarder_;
};