From b90ee4bbe71a4b432a5c0c5fb92fa42bfdac3417 Mon Sep 17 00:00:00 2001 From: g0dil <g0dil@wiback.org> Date: Wed, 28 Jan 2009 17:31:46 +0000 Subject: [PATCH] Scheduler: Factor out TimerSource from TimerDispatcher and implement POSIXTimerSource --- Packets/80211Bundle/RadiotapPacket.hh | 2 +- Scheduler/Scheduler.cc | 7 +- Scheduler/TimerEvent.cc | 98 ++-------------- Scheduler/TimerEvent.cci | 10 ++ Scheduler/TimerEvent.ih | 23 ++-- Scheduler/TimerEvent.test.cc | 12 +- Scheduler/TimerSource.cc | 162 ++++++++++++++++++++++++++ Scheduler/TimerSource.cci | 51 ++++++++ Scheduler/TimerSource.hh | 117 +++++++++++++++++++ 9 files changed, 371 insertions(+), 111 deletions(-) create mode 100644 Scheduler/TimerSource.cc create mode 100644 Scheduler/TimerSource.cci create mode 100644 Scheduler/TimerSource.hh diff --git a/Packets/80211Bundle/RadiotapPacket.hh b/Packets/80211Bundle/RadiotapPacket.hh index 5ddec01c..178556b2 100644 --- a/Packets/80211Bundle/RadiotapPacket.hh +++ b/Packets/80211Bundle/RadiotapPacket.hh @@ -155,7 +155,7 @@ namespace senf OPTIONAL_FIELD ( flags, RadiotapPacketParser_Flags ); //<pkgdraw: size=8 OPTIONAL_FIELD ( rate, UInt8Parser ); SKIP_OPTIONAL_PADDING ( channelOptionsPresent(), rate, 2 ); - OPTIONAL_FIELD ( channelOptions, RadiotapPacketParser_ChannelOptions ); //<pkgdraw: size=16 + OPTIONAL_FIELD ( channelOptions, RadiotapPacketParser_ChannelOptions ); //<pkgdraw: size=32 SKIP_OPTIONAL_PADDING ( fhssPresent(), channelOptions, 2 ); OPTIONAL_FIELD ( fhss, UInt16LSBParser ); OPTIONAL_FIELD ( dbmAntennaSignal, Int8Parser ); diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index 24674593..3203d205 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -58,12 +58,12 @@ namespace { { senf::scheduler::detail::FIFORunner::instance().startWatchdog(); senf::scheduler::detail::SignalDispatcher::instance().unblockSignals(); - senf::scheduler::detail::TimerDispatcher::instance().unblockSignals(); + senf::scheduler::detail::TimerDispatcher::instance().enable(); } ~SchedulerScopedInit() { - senf::scheduler::detail::TimerDispatcher::instance().blockSignals(); + senf::scheduler::detail::TimerDispatcher::instance().disable(); senf::scheduler::detail::SignalDispatcher::instance().blockSignals(); senf::scheduler::detail::FIFORunner::instance().stopWatchdog(); } @@ -74,13 +74,16 @@ prefix_ void senf::scheduler::process() { SchedulerScopedInit initScheduler; terminate_ = false; + detail::TimerDispatcher::instance().reschedule(); while(! terminate_ && ! (detail::FdDispatcher::instance().empty() && detail::TimerDispatcher::instance().empty() && detail::FileDispatcher::instance().empty())) { detail::FdManager::instance().processOnce(); detail::FileDispatcher::instance().prepareRun(); detail::EventHookDispatcher::instance().prepareRun(); + detail::TimerDispatcher::instance().prepareRun(); detail::FIFORunner::instance().run(); + detail::TimerDispatcher::instance().reschedule(); } } diff --git a/Scheduler/TimerEvent.cc b/Scheduler/TimerEvent.cc index f3113e4e..38ad03ab 100644 --- a/Scheduler/TimerEvent.cc +++ b/Scheduler/TimerEvent.cc @@ -34,31 +34,8 @@ ///////////////////////////////cc.p//////////////////////////////////////// prefix_ senf::scheduler::detail::TimerDispatcher::TimerDispatcher() - : blocked_ (true) -{ - if (pipe(timerPipe_) < 0) - SENF_THROW_SYSTEM_EXCEPTION("pipe()"); - senf::scheduler::detail::FdManager::instance().set(timerPipe_[0], detail::FdManager::EV_READ, this); - - sigemptyset(&sigSet_); - sigaddset(&sigSet_, SIGALRM); - sigprocmask(SIG_BLOCK, &sigSet_, 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 sigevent ev; - ::memset(&ev, 0, sizeof(ev)); - ev.sigev_notify = SIGEV_SIGNAL; - ev.sigev_signo = SIGALRM; - ev.sigev_value.sival_ptr = this; - if (timer_create(CLOCK_MONOTONIC, &ev, &timerId_) < 0) - SENF_THROW_SYSTEM_EXCEPTION("timer_create()"); -} + : source_ (new POSIXTimerSource()) +{} prefix_ senf::scheduler::detail::TimerDispatcher::~TimerDispatcher() { @@ -66,21 +43,12 @@ prefix_ senf::scheduler::detail::TimerDispatcher::~TimerDispatcher() TimerSet::iterator const i_end (timers_.end()); for (; i != i_end; ++i) senf::scheduler::detail::FIFORunner::instance().dequeue(&(*i)); - - timer_delete(timerId_); - ::signal(SIGALRM, SIG_IGN); - sigprocmask(SIG_UNBLOCK, &sigSet_, 0); - senf::scheduler::detail::FdManager::instance().remove(timerPipe_[0]); - close(timerPipe_[0]); - close(timerPipe_[1]); } void senf::scheduler::detail::TimerDispatcher::add(TimerEvent & event) { TimerSet::iterator i (timers_.insert(event)); senf::scheduler::detail::FIFORunner::instance().enqueue(&(*i)); - if (! blocked_) - reschedule(); } prefix_ void senf::scheduler::detail::TimerDispatcher::remove(TimerEvent & event) @@ -90,32 +58,10 @@ prefix_ void senf::scheduler::detail::TimerDispatcher::remove(TimerEvent & event return; senf::scheduler::detail::FIFORunner::instance().dequeue(&(*i)); timers_.erase(i); - if (! blocked_) - reschedule(); -} - -prefix_ void senf::scheduler::detail::TimerDispatcher::blockSignals() -{ - if (blocked_) - return; - sigprocmask(SIG_BLOCK, &sigSet_, 0); - blocked_ = true; -} - -prefix_ void senf::scheduler::detail::TimerDispatcher::unblockSignals() -{ - if (! blocked_) - return; - reschedule(); - sigprocmask(SIG_UNBLOCK, &sigSet_, 0); - blocked_ = false; } -prefix_ void senf::scheduler::detail::TimerDispatcher::signal(int events) +prefix_ void senf::scheduler::detail::TimerDispatcher::prepareRun() { - siginfo_t info; - if (read(timerPipe_[0], &info, sizeof(info)) < int(sizeof(info))) - return; TimerSet::iterator i (timers_.begin()); TimerSet::iterator const i_end (timers_.end()); ClockService::clock_type now (senf::scheduler::detail::FdManager::instance().eventTime()); @@ -123,42 +69,12 @@ prefix_ void senf::scheduler::detail::TimerDispatcher::signal(int events) i->setRunnable(); } -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; - // We can't do much on error anyway so we ignore errors here - if (siginfo->si_value.sival_ptr == 0) - return; - write(static_cast<TimerDispatcher*>(siginfo->si_value.sival_ptr)->timerPipe_[1], - siginfo, sizeof(*siginfo)); -} - prefix_ void senf::scheduler::detail::TimerDispatcher::reschedule() { - struct itimerspec timer; - memset(&timer, 0, sizeof(timer)); - timer.it_interval.tv_sec = 0; - timer.it_interval.tv_nsec = 0; - if (timers_.empty()) { - SENF_LOG( (senf::log::VERBOSE)("Timer disabled") ); - timer.it_value.tv_sec = 0; - timer.it_value.tv_nsec = 0; - } - else { - ClockService::clock_type next (timers_.begin()->timeout_); - if (next <= 0) - next = 1; - timer.it_value.tv_sec = ClockService::in_seconds(next); - timer.it_value.tv_nsec = ClockService::in_nanoseconds( - next - ClockService::seconds(timer.it_value.tv_sec)); - SENF_LOG( (senf::log::VERBOSE)("Next timeout scheduled @" << timer.it_value.tv_sec << "." - << std::setw(9) << std::setfill('0') << timer.it_value.tv_nsec) ); - } - if (timer_settime(timerId_, TIMER_ABSTIME, &timer, 0)<0) - SENF_THROW_SYSTEM_EXCEPTION("timer_settime()"); + if (timers_.empty()) + source_->notimeout(); + else + source_->timeout(timers_.begin()->timeout_); } /////////////////////////////////////////////////////////////////////////// diff --git a/Scheduler/TimerEvent.cci b/Scheduler/TimerEvent.cci index 85273801..5fcf5ef5 100644 --- a/Scheduler/TimerEvent.cci +++ b/Scheduler/TimerEvent.cci @@ -82,6 +82,16 @@ prefix_ void senf::scheduler::TimerEvent::timeout(ClockService::clock_type timeo /////////////////////////////////////////////////////////////////////////// // senf::scheduler::detail::TimerDispatcher +prefix_ void senf::scheduler::detail::TimerDispatcher::enable() +{ + source_->enable(); +} + +prefix_ void senf::scheduler::detail::TimerDispatcher::disable() +{ + source_->disable(); +} + prefix_ bool senf::scheduler::detail::TimerDispatcher::empty() const { diff --git a/Scheduler/TimerEvent.ih b/Scheduler/TimerEvent.ih index 1c5ea524..af9c1047 100644 --- a/Scheduler/TimerEvent.ih +++ b/Scheduler/TimerEvent.ih @@ -27,7 +27,9 @@ #define IH_SENF_Scheduler_TimerEvent_ 1 // Custom includes +#include <boost/scoped_ptr.hpp> #include "../boost/intrusive/iset.hpp" +#include "TimerSource.hh" ///////////////////////////////ih.p//////////////////////////////////////// @@ -44,8 +46,7 @@ namespace detail { }; class TimerDispatcher - : public detail::FdManager::Event, - public singleton<TimerDispatcher> + : public singleton<TimerDispatcher> { SENF_LOG_CLASS_AREA(); @@ -56,9 +57,12 @@ namespace detail { void add(TimerEvent & event); void remove(TimerEvent & event); - void unblockSignals(); - void blockSignals(); - + void enable(); + void disable(); + + void prepareRun(); + void reschedule(); + bool empty() const; protected: @@ -67,20 +71,13 @@ namespace detail { TimerDispatcher(); ~TimerDispatcher(); - virtual void signal(int events); - static void sigHandler(int signal, ::siginfo_t * siginfo, void *); - void reschedule(); - typedef boost::intrusive::imultiset< TimerSetBase::value_traits<TimerEvent>, TimerSetCompare, false > TimerSet; TimerSet timers_; - int timerPipe_[2]; - sigset_t sigSet_; - bool blocked_; - timer_t timerId_; + boost::scoped_ptr<TimerSource> source_; friend void senf::scheduler::restart(); friend class singleton<TimerDispatcher>; diff --git a/Scheduler/TimerEvent.test.cc b/Scheduler/TimerEvent.test.cc index b6269448..cbab9f6c 100644 --- a/Scheduler/TimerEvent.test.cc +++ b/Scheduler/TimerEvent.test.cc @@ -61,10 +61,12 @@ BOOST_AUTO_UNIT_TEST(timerDispatcher) 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::detail::TimerDispatcher::instance().enable() ); + SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().reschedule() ); SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() ); - SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().blockSignals() ); + SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().prepareRun() ); SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() ); + SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().disable() ); senf::ClockService::clock_type t2 (senf::ClockService::now()); BOOST_CHECK( called ); BOOST_CHECK( ! timer.enabled() ); @@ -74,10 +76,12 @@ BOOST_AUTO_UNIT_TEST(timerDispatcher) 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::detail::TimerDispatcher::instance().enable() ); + SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().reschedule() ); SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() ); - SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().blockSignals() ); + SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().prepareRun() ); SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() ); + SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().disable() ); BOOST_CHECK_PREDICATE( is_close, (t) (senf::ClockService::now()) ); BOOST_CHECK( called ); } diff --git a/Scheduler/TimerSource.cc b/Scheduler/TimerSource.cc new file mode 100644 index 00000000..17d2de7e --- /dev/null +++ b/Scheduler/TimerSource.cc @@ -0,0 +1,162 @@ +// $Id$ +// +// Copyright (C) 2009 +// 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 TimerSource non-inline non-template implementation */ + +#include "TimerSource.hh" +//#include "TimerSource.ih" + +// Custom includes + +//#include "TimerSource.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::scheduler::detail::TimerSource + +prefix_ senf::scheduler::detail::TimerSource::~TimerSource() +{} + +/////////////////////////////////////////////////////////////////////////// +// senf::scheduler::detail::POSIXTimerSource + +prefix_ senf::scheduler::detail::POSIXTimerSource::POSIXTimerSource() + : timeoutEnabled_ (false), timeout_ (0), signalEnabled_ (false) +{ + if (pipe(timerPipe_) < 0) + SENF_THROW_SYSTEM_EXCEPTION("pipe()"); + senf::scheduler::detail::FdManager::instance().set( + timerPipe_[0], detail::FdManager::EV_READ, this); + + sigemptyset(&sigSet_); + sigaddset(&sigSet_, SIGALRM); + sigprocmask(SIG_BLOCK, &sigSet_, 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 sigevent ev; + ::memset(&ev, 0, sizeof(ev)); + ev.sigev_notify = SIGEV_SIGNAL; + ev.sigev_signo = SIGALRM; + ev.sigev_value.sival_ptr = this; + if (timer_create(CLOCK_MONOTONIC, &ev, &timerId_) < 0) + SENF_THROW_SYSTEM_EXCEPTION("timer_create()"); +} + +prefix_ senf::scheduler::detail::POSIXTimerSource::~POSIXTimerSource() +{ + timer_delete(timerId_); + ::signal(SIGALRM, SIG_IGN); + sigprocmask(SIG_UNBLOCK, &sigSet_, 0); + senf::scheduler::detail::FdManager::instance().remove(timerPipe_[0]); + close(timerPipe_[0]); + close(timerPipe_[1]); +} + +prefix_ void +senf::scheduler::detail::POSIXTimerSource::timeout(ClockService::clock_type timeout) +{ + if (! timeoutEnabled_ || timeout_ != timeout) { + timeout_ = timeout; + if (timeout_ <= 0) + timeout_ = 1; + timeoutEnabled_ = true; + reschedule(); + } +} + +prefix_ void senf::scheduler::detail::POSIXTimerSource::notimeout() +{ + if (timeoutEnabled_) { + timeoutEnabled_ = false; + reschedule(); + } +} + +prefix_ void senf::scheduler::detail::POSIXTimerSource::enable() +{ + if (! signalEnabled_) { + signalEnabled_ = true; + sigprocmask(SIG_UNBLOCK, &sigSet_, 0); + } +} + +prefix_ void senf::scheduler::detail::POSIXTimerSource::disable() +{ + if (signalEnabled_) { + signalEnabled_ = false; + sigprocmask(SIG_BLOCK, &sigSet_, 0); + } +} + +prefix_ void senf::scheduler::detail::POSIXTimerSource::sigHandler(int, + ::siginfo_t * siginfo, + void *) +{ + if (siginfo->si_value.sival_ptr == 0) + return; + static char data = '\xD0'; + write(static_cast<POSIXTimerSource*>(siginfo->si_value.sival_ptr)->timerPipe_[1], + &data, sizeof(data)); +} + +prefix_ void senf::scheduler::detail::POSIXTimerSource::signal(int events) +{ + char data; + read(timerPipe_[0], &data, sizeof(data)); + timeoutEnabled_ = false; +} + +prefix_ void senf::scheduler::detail::POSIXTimerSource::reschedule() +{ + struct itimerspec timer; + memset(&timer, 0, sizeof(timer)); + if (timeoutEnabled_) { + timer.it_value.tv_sec = ClockService::in_seconds(timeout_); + timer.it_value.tv_nsec = ClockService::in_nanoseconds( + timeout_ - ClockService::seconds(timer.it_value.tv_sec)); + } + if (timer_settime(timerId_, TIMER_ABSTIME, &timer, 0)<0) + SENF_THROW_SYSTEM_EXCEPTION("timer_settime()"); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "TimerSource.mpp" + + +// 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/TimerSource.cci b/Scheduler/TimerSource.cci new file mode 100644 index 00000000..de097756 --- /dev/null +++ b/Scheduler/TimerSource.cci @@ -0,0 +1,51 @@ +// $Id$ +// +// Copyright (C) 2009 +// 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 TimerSource inline non-template implementation */ + +//#include "TimerSource.ih" + +// Custom includes + +#define prefix_ inline +///////////////////////////////cci.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::scheduler::detail::TimerSource + +prefix_ senf::scheduler::detail::TimerSource::TimerSource() +{} + +///////////////////////////////cci.e/////////////////////////////////////// +#undef prefix_ + + +// 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/TimerSource.hh b/Scheduler/TimerSource.hh new file mode 100644 index 00000000..f17c6fcd --- /dev/null +++ b/Scheduler/TimerSource.hh @@ -0,0 +1,117 @@ +// $Id$ +// +// Copyright (C) 2009 +// 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 TimerSource public header */ + +#ifndef HH_SENF_Scheduler_TimerSource_ +#define HH_SENF_Scheduler_TimerSource_ 1 + +// Custom includes +#include <boost/utility.hpp> +#include <signal.h> +#include "ClockService.hh" +#include "FdManager.hh" + +//#include "TimerSource.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace senf { +namespace scheduler { +namespace detail { + + class TimerSource + : boost::noncopyable + { + public: + virtual ~TimerSource(); + + virtual void timeout(ClockService::clock_type timeout) = 0; + virtual void notimeout() = 0; + + virtual void enable() = 0; + virtual void disable() = 0; + + protected: + TimerSource(); + }; + + class POSIXTimerSource + : public detail::FdManager::Event, public TimerSource + { + public: + POSIXTimerSource(); + ~POSIXTimerSource(); + + virtual void timeout(ClockService::clock_type timeout); + virtual void notimeout(); + + virtual void enable(); + virtual void disable(); + + private: + static void sigHandler(int signal, ::siginfo_t * siginfo, void *); + virtual void signal(int events); + void reschedule(); + + bool timeoutEnabled_; + ClockService::clock_type timeout_; + int timerPipe_[2]; + sigset_t sigSet_; + bool signalEnabled_; + timer_t timerId_; + }; + + class PollTimerSource + : public TimerSource + { + public: + virtual void timeout(ClockService::clock_type timeout); + virtual void disableTimeout(); + }; + + class TimerFDTimerSource + : public TimerSource + { + public: + virtual void timeout(ClockService::clock_type timeout); + virtual void disableTimeout(); + }; + +}}} + +///////////////////////////////hh.e//////////////////////////////////////// +#include "TimerSource.cci" +//#include "TimerSource.ct" +//#include "TimerSource.cti" +#endif + + +// 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: -- GitLab