#define HH_Scheduler_ 1
// Custom includes
-#include <signal.h>
-#include <setjmp.h>
-#include <map>
-#include <queue>
-#include <boost/function.hpp>
-#include <boost/utility.hpp>
-#include <boost/call_traits.hpp>
-#include <boost/integer.hpp>
-#include "ClockService.hh"
+#include "../Utils/Logger/SenfLog.hh"
+#include "FdEvent.hh"
+#include "TimerEvent.hh"
+#include "SignalEvent.hh"
#include "../Utils/Logger/SenfLog.hh"
//#include "scheduler.mpp"
/** \brief SENF Project namespace */
namespace senf {
- /** \brief Singleton class to manage the event loop
+ /** \brief Visible scheduler interface
- The %scheduler singleton manages the central event loop. It manages and dispatches all types
- of events managed by the scheduler library:
+ The %scheduler singleton manages access to the %scheduler library. It provides access to
+ several event dispatchers:
\li File descriptor notifications
\li Timeouts
\li UNIX Signals
If you need to pass additional information to your handler, use <a
href="http://www.boost.org/libs/bind/bind.html">Boost.Bind</a>:
\code
+ // Handle callback function
+ void callback(UDPv4ClientSocketHandle handle, senf::Scheduler::EventId event) {..}
// Pass 'handle' as additional first argument to callback()
- Scheduler::instance().add(handle, boost::bind(&callback, handle, _1))
+ Scheduler::instance().add(handle, boost::bind(&callback, handle, _1), EV_READ)
+ // Timeout function
+ void timeout( int n) {..}
// Call timeout() handler with argument 'n'
Scheduler::instance().timeout(boost::bind(&timeout, n))
\endcode
href="http://www.boost.org/libs/bind/bind.html">Boost.Bind</a> or senf::membind()
\code
// e.g. in Foo::Foo() constructor:
- Scheduler::instance().add(handle_, senf::membind(&Foo::callback, this))
+ Scheduler::instance().add(handle_, senf::membind(&Foo::callback, this)), EV_READ)
\endcode
-
+
+ The handler can also be identified by an arbitrary, user specified name. This name is used
+ in error messages to identify the failing handler.
+
\section sched_fd Registering file descriptors
File descriptors are managed using add() or remove()
\code
- Scheduler::instance().add(handle, &callback);
+ Scheduler::instance().add(handle, &callback, EV_ALL);
Scheduler::instance().remove(handle);
\endcode
Scheduler::instance().cancelTimeout(id);
\endcode
Timing is based on the ClockService, which provides a high resolution and strictly
- monotonous time source. Registering a timeout will fire the callback when the target time is
- reached. The timer may be canceled by passing the returned \a id to cancelTimeout().
-
- There are two parameters which adjust the exact: \a timeoutEarly and \a timeoutAdjust. \a
- timeoutEarly is the time, a callback may be called before the deadline time is
- reached. Setting this value below the scheduling granularity of the kernel will have the
- %scheduler go into a <em>busy wait</em> (that is, an endless loop consuming 100% of CPU
- recources) until the deadline time is reached! This is seldom desired. The default setting
- of 11ms is adequate in most cases (it's slightly above the lowest linux scheduling
- granularity).
-
- The other timeout scheduling parameter is \a timeoutAdjust. This value will be added to the
- timeout value before calculating the next delay value thereby compensating for \a
- timeoutEarly. By default, this value is set to 0 but may be changed if needed.
+ monotonous time source which again is based on POSIX timers. Registering a timeout will fire
+ the callback when the target time is reached. The timer may be canceled by passing the
+ returned \a id to cancelTimeout().
\section sched_signals Registering POSIX/UNIX signals
A registered signal does \e not count as 'something to do'. It is therefore not possible to
wait for signals \e only.
- \todo Fix EventId parameter (probably to int) to allow |-ing without casting ...
-
+ \todo Change the Scheduler API to use RAII. Additionally, this will remove all dynamic
+ memory allocations from the scheduler.
\todo Fix the file support to use threads (?) fork (?) and a pipe so it works reliably even
over e.g. NFS.
*/
\li Error flags. These additional flags may be passed to a handler to pass an error
condition to the handler.
*/
- enum EventId {
- EV_NONE = 0 /**< No event */
- , EV_READ = 1 /**< File descriptor is readable */
- , EV_PRIO = 2 /**< File descriptor has OOB data */
- , EV_WRITE = 4 /**< File descriptor is writable */
- , EV_ALL = 7 /**< Used to register all events at once (read/prio/write) */
- , EV_HUP = 8 /**< Hangup condition on file handle */
- , EV_ERR = 16 /**< Error condition on file handle */
+ enum EventId {
+ EV_NONE = 0 /**< No event */
+ , EV_READ = scheduler::FdManager::EV_READ /**< File descriptor is readable */
+ , EV_PRIO = scheduler::FdManager::EV_PRIO /**< File descriptor has OOB data */
+ , EV_WRITE = scheduler::FdManager::EV_WRITE /**< File descriptor is writable */
+ , EV_ALL = scheduler::FdManager::EV_READ
+ | scheduler::FdManager::EV_PRIO
+ | scheduler::FdManager::EV_WRITE /**< Used to register all events at once
+ (read/prio/write) */
+ , EV_HUP = scheduler::FdManager::EV_HUP /**< Hangup condition on file handle */
+ , EV_ERR = scheduler::FdManager::EV_ERR /**< Error condition on file handle */
};
- /** \brief Template typedef for Callback type
-
- This is a template typedef (which does not exist in C++) that is, a template class whose
- sole member is a typedef symbol defining the callback type given the handle type.
-
- The Callback is any callable object taking a \c Handle and an \c EventId as argument.
- \code
- template <class Handle>
- struct GenericCallback {
- typedef boost::function<void (typename boost::call_traits<Handle>::param_type,
- EventId) > Callback;
- };
- \endcode
- */
- typedef boost::function<void (EventId)> FdCallback;
+ /** \brief Callback type for file descriptor events */
+ typedef boost::function<void (int)> FdCallback;
/** \brief Callback type for timer events */
typedef boost::function<void ()> SimpleCallback;
+ /** \brief Callback type for signal events */
+ typedef boost::function<void (siginfo_t const &)> SignalCallback;
+
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
This static member is used to access the singleton instance. This member is save to
return a correctly initialized %scheduler instance even if called at global construction
time
-
- \implementation This static member just defines the %scheduler as a static method
- variable. The C++ standard then provides above guarantee. The instance will be
- initialized the first time, the code flow passes the variable declaration found in
- the instance() body.
*/
static Scheduler & instance();
///@}
///////////////////////////////////////////////////////////////////////////
- ///\name File Descriptors
- ///\{
-
- template <class Handle>
- void add(Handle const & handle, FdCallback const & cb,
- int eventMask = EV_ALL); ///< Add file handle event callback
- /**< add() will add a callback to the %scheduler. The
- callback will be called for the given type of event on
- the given arbitrary file-descriptor or
- handle-like object. If there already is a Callback
- registered for one of the events requested, the new
- handler will replace the old one.
- \param[in] handle file descriptor or handle providing
- the Handle interface defined above.
- \param[in] cb callback
- \param[in] eventMask arbitrary combination via '|'
- operator of EventId designators. */
- template <class Handle>
- void remove(Handle const & handle, int eventMask = EV_ALL); ///< Remove event callback
- /**< remove() will remove any callback registered for any of
- the given events on the given file descriptor or handle
- like object.
- \param[in] handle file descriptor or handle providing
- the Handle interface defined above.
- \param[in] eventMask arbitrary combination via '|'
- operator of EventId designators. */
-
- ///\}
-
- ///\name Timeouts
- ///\{
-
- unsigned timeout(ClockService::clock_type timeout, SimpleCallback const & cb);
- ///< Add timeout event
- /**< \param[in] timeout timeout in nanoseconds
- \param[in] cb callback to call after \a timeout
- milliseconds */
-
- void cancelTimeout(unsigned id); ///< Cancel timeout \a id
-
- ClockService::clock_type timeoutEarly() const;
- ///< Fetch the \a timeoutEarly parameter
- void timeoutEarly(ClockService::clock_type v);
- ///< Set the \a timeoutEarly parameter
-
- ClockService::clock_type timeoutAdjust() const;\
- ///< Fetch the \a timeoutAdjust parameter
- void timeoutAdjust(ClockService::clock_type v);
- ///< Set the \a timeoutAdjust parameter
-
- ///\}
-
- ///\name Signal handlers
- ///\{
-
- void registerSignal(unsigned signal, SimpleCallback const & cb);
- ///< Add signal handler
- /**< \param[in] signal signal number to register handler for
- \param[in] cb callback to call whenever \a signal is
- delivered. */
-
- void unregisterSignal(unsigned signal);
- ///< Remove signal handler for \a signal
-
- /// The signal number passed to registerSignal or unregisterSignal is invalid
- struct InvalidSignalNumberException : public std::exception
- { virtual char const * what() const throw()
- { return "senf::Scheduler::InvalidSignalNumberException"; } };
-
-
- ///\}
-
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
returns. */
ClockService::clock_type eventTime() const; ///< Return date/time of last event
+ /**< This is the timestamp, the last event has been
+ signaled. This is the real time at which the event is
+ delivered \e not the time it should have been delivered
+ (in the case of timers). */
+
+ void taskTimeout(unsigned ms);
+ unsigned taskTimeout() const;
+ unsigned hangCount() const;
+
+ void restart();
protected:
private:
Scheduler();
- void do_add(int fd, FdCallback const & cb, int eventMask = EV_ALL);
- void do_remove(int fd, int eventMask = EV_ALL);
-
- void registerSigHandlers();
- static void sigHandler(int signal, ::siginfo_t * siginfo, void *);
-
-# ifndef DOXYGEN
-
- /** \brief Descriptor event specification
- \internal */
- struct EventSpec
- {
- FdCallback cb_read;
- FdCallback cb_prio;
- FdCallback cb_write;
-
- EventSpec() : file(false) {}
-
- int epollMask() const;
-
- bool file;
- };
-
- /** \brief Timer event specification
- \internal */
- struct TimerSpec
- {
- TimerSpec() : timeout(), cb() {}
- TimerSpec(ClockService::clock_type timeout_, SimpleCallback cb_, unsigned id_)
- : timeout(timeout_), cb(cb_), id(id_), canceled(false) {}
-
- bool operator< (TimerSpec const & other) const
- { return timeout > other.timeout; }
-
- ClockService::clock_type timeout;
- SimpleCallback cb;
- unsigned id;
- bool canceled;
- };
-
-# endif
-
- typedef std::map<int,EventSpec> FdTable;
- typedef std::map<unsigned,TimerSpec> TimerMap; // sorted by id
- typedef std::vector<unsigned> FdEraseList;
-
-# ifndef DOXYGEN
-
- struct TimerSpecCompare
- {
- typedef TimerMap::iterator first_argument_type;
- typedef TimerMap::iterator second_argument_type;
- typedef bool result_type;
-
- result_type operator()(first_argument_type a, second_argument_type b);
- };
-
-# endif
-
- typedef std::priority_queue<TimerMap::iterator, std::vector<TimerMap::iterator>,
- TimerSpecCompare> TimerQueue; // sorted by time
-
- typedef std::vector<SimpleCallback> SigHandlers;
-
- FdTable fdTable_;
- FdEraseList fdErase_;
- unsigned files_;
-
- unsigned timerIdCounter_;
- TimerQueue timerQueue_;
- TimerMap timerMap_;
-
- SigHandlers sigHandlers_;
- ::sigset_t sigset_;
- int sigpipe_[2];
-
- int epollFd_;
bool terminate_;
- ClockService::clock_type eventTime_;
- ClockService::clock_type eventEarly_;
- ClockService::clock_type eventAdjust_;
};
- /** \brief Default file descriptor accessor
-
- retrieve_filehandle() provides the %scheduler with support for explicit file descriptors as
- file handle argument.
-
- \relates Scheduler
- */
- int retrieve_filehandle(int fd);
-
/** \brief %scheduler specific time source for Utils/Logger framework
This time source may be used to provide timing information for log messages within the
*/
struct SchedulerLogTimeSource : public senf::log::TimeSource
{
- boost::posix_time::ptime operator()() const;
+ senf::log::time_type operator()() const;
};
}
///////////////////////////////hh.e////////////////////////////////////////
#include "Scheduler.cci"
//#include "Scheduler.ct"
-#include "Scheduler.cti"
+//#include "Scheduler.cti"
#endif
\f