From: g0dil Date: Mon, 6 Nov 2006 15:40:15 +0000 (+0000) Subject: Simple timeout implementation X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=2654c3b13a187f38dc026e04c76ea5c885b34787;p=senf.git Simple timeout implementation git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@150 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Scheduler/Scheduler.cc b/Scheduler/Scheduler.cc index 5e8a860..4f39c4b 100644 --- a/Scheduler/Scheduler.cc +++ b/Scheduler/Scheduler.cc @@ -71,6 +71,7 @@ #include #include #include "Utils/Exception.hh" +#include "Utils/MicroTime.hh" static const int EPollInitialSize = 16; @@ -83,6 +84,11 @@ prefix_ satcom::lib::Scheduler::Scheduler & satcom::lib::Scheduler::instance() return instance; } +prefix_ void satcom::lib::Scheduler::timeout(unsigned long timeout, TimerCallback const & cb) +{ + timerQueue_.push(TimerSpec(now()+1000*timeout,cb)); +} + prefix_ satcom::lib::Scheduler::Scheduler() : epollFd_(epoll_create(EPollInitialSize)) { @@ -90,7 +96,7 @@ prefix_ satcom::lib::Scheduler::Scheduler() throw SystemException(errno); } -prefix_ void satcom::lib::Scheduler::do_add(int fd, InternalCallback const & cb, EventId eventMask) +prefix_ void satcom::lib::Scheduler::do_add(int fd, SimpleCallback const & cb, EventId eventMask) { FdTable::iterator i (fdTable_.find(fd)); int action (EPOLL_CTL_MOD); @@ -141,6 +147,7 @@ prefix_ void satcom::lib::Scheduler::do_remove(int fd, EventId eventMask) throw SystemException(errno); } + prefix_ int satcom::lib::Scheduler::EventSpec::epollMask() const { @@ -158,11 +165,21 @@ prefix_ void satcom::lib::Scheduler::process() terminate_ = false; while (! terminate_) { struct epoll_event ev; - int events = epoll_wait(epollFd_, &ev, 1, 1000); + MicroTime timeNow = now(); + while ( ! timerQueue_.empty() && timerQueue_.top().timeout <= timeNow ) { + timerQueue_.top().cb(); + timerQueue_.pop(); + } + if (terminate_) + return; + int timeout = timerQueue_.empty() ? -1 : int((timerQueue_.top().timeout - timeNow)/1000); + + int events = epoll_wait(epollFd_, &ev, 1, timeout); if (events<0) // Hmm ... man epoll says, it will NOT return with EINTR ?? throw SystemException(errno); if (events==0) + // Timeout .. it will be run when reachiung the top of the loop continue; FdTable::iterator i = fdTable_.find(ev.data.fd); diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh index 8916723..a535fad 100644 --- a/Scheduler/Scheduler.hh +++ b/Scheduler/Scheduler.hh @@ -25,10 +25,13 @@ // Custom includes #include +#include #include #include #include +#include "Utils/MicroTime.hh" + //#include "scheduler.mpp" ///////////////////////////////hh.p//////////////////////////////////////// @@ -59,6 +62,8 @@ namespace lib { typedef boost::function::param_type, EventId) > Callback; }; + typedef boost::function SimpleCallback; + typedef boost::function TimerCallback; /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members @@ -78,38 +83,52 @@ namespace lib { template void add(Handle const & handle, typename GenericCallback::Callback const & cb, - EventId eventMask = EV_ALL); - template + EventId eventMask = EV_ALL); + template void remove(Handle const & handle, EventId eventMask = EV_ALL); - void process(); + void timeout(unsigned long timeout, TimerCallback const & cb); + void process(); void terminate(); protected: private: Scheduler(); - - typedef boost::function InternalCallback; - - void do_add(int fd, InternalCallback const & cb, EventId eventMask = EV_ALL); + + void do_add(int fd, SimpleCallback const & cb, EventId eventMask = EV_ALL); void do_remove(int fd, EventId eventMask = EV_ALL); - + struct EventSpec { - InternalCallback cb_read; - InternalCallback cb_prio; - InternalCallback cb_write; - InternalCallback cb_hup; - InternalCallback cb_err; + SimpleCallback cb_read; + SimpleCallback cb_prio; + SimpleCallback cb_write; + SimpleCallback cb_hup; + SimpleCallback cb_err; int epollMask() const; }; + + struct TimerSpec + { + TimerSpec() : timeout(), cb() {} + TimerSpec(unsigned long long timeout_, TimerCallback cb_) + : timeout(timeout_), cb(cb_) {} + + bool operator< (TimerSpec const & other) const + { return timeout > other.timeout; } + + unsigned long long timeout; + TimerCallback cb; + }; typedef std::map FdTable; + typedef std::priority_queue TimerQueue; FdTable fdTable_; + TimerQueue timerQueue_; int epollFd_; bool terminate_; }; diff --git a/Scheduler/Scheduler.test.cc b/Scheduler/Scheduler.test.cc index fb5ae35..26dd7fd 100644 --- a/Scheduler/Scheduler.test.cc +++ b/Scheduler/Scheduler.test.cc @@ -163,6 +163,11 @@ namespace { } Scheduler::instance().terminate(); } + + void timeout() + { + Scheduler::instance().terminate(); + } struct HandleWrapper { @@ -182,6 +187,12 @@ namespace { return; callback(handle.fd_,event); } + + bool is_close(MicroTime a, MicroTime b) + { + return (a +#include +#include + +#include "Utils/Exception.hh" + +//#include "MicroTime.mpp" +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +prefix_ satcom::lib::MicroTime satcom::lib::now() +{ + struct timeval tv; + if (gettimeofday(&tv,0) < 0) + throw SystemException(errno); + return 1000000*MicroTime(tv.tv_sec) + tv.tv_usec; +} + + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ +//#include "MicroTime.mpp" + + +// Local Variables: +// mode: c++ +// End: diff --git a/Utils/MicroTime.hh b/Utils/MicroTime.hh new file mode 100644 index 0000000..f4fc8ca --- /dev/null +++ b/Utils/MicroTime.hh @@ -0,0 +1,33 @@ +// $Id$ +// +// Copyright (C) 2006 + +#ifndef HH_MicroTime_ +#define HH_MicroTime_ 1 + +// Custom includes +#include + +//#include "MicroTime.mpp" +///////////////////////////////hh.p//////////////////////////////////////// + +namespace satcom { +namespace lib { + + typedef boost::uint64_t MicroTime; + + MicroTime now(); + +}} + +///////////////////////////////hh.e//////////////////////////////////////// +//#include "MicroTime.cci" +//#include "MicroTime.ct" +//#include "MicroTime.cti" +//#include "MicroTime.mpp" +#endif + + +// Local Variables: +// mode: c++ +// End: diff --git a/Utils/MicroTime.test.cc b/Utils/MicroTime.test.cc new file mode 100644 index 0000000..93dfd54 --- /dev/null +++ b/Utils/MicroTime.test.cc @@ -0,0 +1,30 @@ +// $Id$ +// +// Copyright (C) 2006 + +// Unit tests + +//#include "MicroTime.test.hh" +//#include "MicroTime.test.ih" + +// Custom includes +#include "MicroTime.hh" + +#include +#include + +#define prefix_ +///////////////////////////////cc.p//////////////////////////////////////// + +BOOST_AUTO_UNIT_TEST(microTime) +{ + BOOST_CHECK_NO_THROW( satcom::lib::now() ); +} + +///////////////////////////////cc.e//////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// End: