.name("someServer");
// Run the scheduler
- senf::Scheduler::instance().process();
+ senf::scheduler::process();
}
\endcode
.name("myserver");
// You need to enter the scheduler main-loop for the server to work
- senf::Scheduler::instance().process();
+ senf::scheduler::process();
// Alternatively enter the main-loop via the PPI
// senf::ppi::run();
prefix_ senf::console::detail::ReadlineClientReader::ReadlineClientReader(Client & client)
: ClientReader(client), ch_ (-1), skipChars_ (0),
readevent_ ( "ReadlineClientReader", senf::membind(&ReadlineClientReader::charEvent, this),
- client.handle(), Scheduler::EV_READ, false ),
+ client.handle(), scheduler::FdEvent::EV_READ, false ),
terminate_ (false)
{
if (instance_ != 0)
prefix_ void senf::console::detail::ReadlineClientReader::charEvent(int event)
{
char ch;
- if (event != Scheduler::EV_READ || handle().read(&ch, &ch+1) <= &ch) {
+ if (event != scheduler::FdEvent::EV_READ || handle().read(&ch, &ch+1) <= &ch) {
stopClient();
return;
}
prefix_ senf::console::Server & senf::console::Server::start(ServerHandle handle)
{
- // Uah .... ensure the scheduler is created before the instance pointer so it get's destructed
- // AFTER it.
- (void) senf::Scheduler::instance();
boost::intrusive_ptr<Server> p (new Server(handle));
detail::ServerManager::add(boost::intrusive_ptr<Server>(p));
return *p;
: ClientReader (client),
readevent_ ("NoninteractiveClientReader",
senf::membind(&NoninteractiveClientReader::newData, this),
- handle(), senf::Scheduler::EV_READ)
+ handle(), senf::scheduler::FdEvent::EV_READ)
{}
prefix_ void senf::console::detail::NoninteractiveClientReader::v_disablePrompt()
prefix_ void
senf::console::detail::NoninteractiveClientReader::newData(int event)
{
- if (event != senf::Scheduler::EV_READ || handle().eof()) {
+ if (event != senf::scheduler::FdEvent::EV_READ || handle().eof()) {
if (! buffer_.empty())
handleInput(buffer_);
stopClient();
: out_t(boost::ref(*this)), senf::log::IOStreamTarget(out_t::member), server_ (server),
handle_ (handle),
readevent_ ("senf::console::Client", boost::bind(&Client::setNoninteractive,this),
- handle, Scheduler::EV_READ, false),
+ handle, scheduler::FdEvent::EV_READ, false),
timer_ ("senf::console::Client interactive timeout",
boost::bind(&Client::setInteractive, this),
- Scheduler::instance().eventTime() + ClockService::milliseconds(INTERACTIVE_TIMEOUT),
+ scheduler::eventTime() + ClockService::milliseconds(INTERACTIVE_TIMEOUT),
false),
name_ (server.name()), reader_ (), mode_ (server.mode())
{
void shutdownServer()
{
- senf::Scheduler::instance().terminate();
+ senf::scheduler::terminate();
throw senf::console::Executor::ExitException();
}
senf::console::Server::start( senf::INet4SocketAddress(23232u) )
.name("testServer");
- senf::Scheduler::instance().process();
+ senf::scheduler::process();
}
\f
MCSniffer sniffer2 (
senf::INet4Address::from_string("233.132.152.2"), f2);
- senf::Scheduler::instance().process();
+ senf::scheduler::process();
}
catch (std::exception const & ex) {
std::cerr << senf::prettyName(typeid(ex)) << ": " << ex.what() << "\n";
void run()
{
- senf::Scheduler::instance().process();
+ senf::scheduler::process();
}
private:
void run()
{
- senf::Scheduler::instance().process();
+ senf::scheduler::process();
}
private:
void run()
{
event.enable();
- senf::Scheduler::instance().process();
+ senf::scheduler::process();
}
private:
prefix_ senf::ClockService::clock_type senf::ppi::EventManager::now()
{
- return Scheduler::instance().eventTime();
+ return scheduler::eventTime();
}
prefix_ senf::ClockService::clock_type senf::ppi::EventManager::time()
// with the enumeration symbols
enum EventFlags {
- Read = Scheduler::EV_READ /**< FileHandle is readable */
- , Prio = Scheduler::EV_PRIO /**< FileHandle priority data is readable */
- , Write = Scheduler::EV_WRITE /**< FileHandle is writable */
- , Hup = Scheduler::EV_HUP /**< Hangup condition on FileHandle */
- , Err = Scheduler::EV_ERR /**< Some other error condition on FileHandle */
+ Read = scheduler::FdEvent::EV_READ /**< FileHandle is readable */
+ , Prio = scheduler::FdEvent::EV_PRIO /**< FileHandle priority data is readable */
+ , Write = scheduler::FdEvent::EV_WRITE /**< FileHandle is writable */
+ , Hup = scheduler::FdEvent::EV_HUP /**< Hangup condition on FileHandle */
+ , Err = scheduler::FdEvent::EV_ERR /**< Some other error condition on FileHandle */
};
///////////////////////////////////////////////////////////////////////////
{
init();
RunGuard guard (*this);
- Scheduler::instance().process();
+ scheduler::process();
}
////////////////////////////////////////
namespace {
void timeout() {
- senf::Scheduler::instance().terminate();
+ senf::scheduler::terminate();
}
}
namespace {
void timeout() {
- senf::Scheduler::instance().terminate();
+ senf::scheduler::terminate();
}
}
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-prefix_ senf::scheduler::FIFORunner::FIFORunner()
+prefix_ senf::scheduler::detail::FIFORunner::FIFORunner()
: tasks_ (), next_ (tasks_.end()), watchdogMs_ (1000), watchdogCount_(0), hangCount_ (0)
{
struct sigevent ev;
SENF_THROW_SYSTEM_EXCEPTION("sigprocmask()");
}
-prefix_ senf::scheduler::FIFORunner::~FIFORunner()
+prefix_ senf::scheduler::detail::FIFORunner::~FIFORunner()
{
timer_delete(watchdogId_);
signal(SIGURG, SIG_DFL);
// will mostly be localized to the end of the queue. only occasionally one of the dormant tasks will
// be runnable. This additional traversal time will be amortized over a larger time.
-prefix_ void senf::scheduler::FIFORunner::dequeue(TaskInfo * task)
+prefix_ void senf::scheduler::detail::FIFORunner::dequeue(TaskInfo * task)
{
TaskList::iterator i (TaskList::current(*task));
if (next_ == i)
namespace {
struct NullTask
- : public senf::scheduler::FIFORunner::TaskInfo
+ : public senf::scheduler::detail::FIFORunner::TaskInfo
{
- NullTask() : senf::scheduler::FIFORunner::TaskInfo ("<null>") {}
+ NullTask() : senf::scheduler::detail::FIFORunner::TaskInfo ("<null>") {}
void run() {};
};
}
-prefix_ void senf::scheduler::FIFORunner::run()
+prefix_ void senf::scheduler::detail::FIFORunner::run()
{
// This algorithm is carefully adjusted to make it work even when arbitrary tasks are removed
// from the queue
next_ = tasks_.end();
}
-prefix_ void senf::scheduler::FIFORunner::watchdog(int, siginfo_t * si, void *)
+prefix_ void senf::scheduler::detail::FIFORunner::watchdog(int, siginfo_t * si, void *)
{
FIFORunner & runner (*static_cast<FIFORunner *>(si->si_value.sival_ptr));
if (runner.watchdogCount_ > 0) {
#define prefix_ inline
///////////////////////////////cci.p///////////////////////////////////////
-prefix_ senf::scheduler::FIFORunner::TaskInfo::TaskInfo(std::string const & name)
+prefix_ senf::scheduler::detail::FIFORunner::TaskInfo::TaskInfo(std::string const & name)
: runnable_ (false), name_ (name)
{}
-prefix_ senf::scheduler::FIFORunner::TaskInfo::~TaskInfo()
+prefix_ senf::scheduler::detail::FIFORunner::TaskInfo::~TaskInfo()
{}
-prefix_ void senf::scheduler::FIFORunner::TaskInfo::setRunnable()
+prefix_ void senf::scheduler::detail::FIFORunner::TaskInfo::setRunnable()
{
runnable_ = true;
}
-prefix_ void senf::scheduler::FIFORunner::enqueue(TaskInfo * task)
+prefix_ void senf::scheduler::detail::FIFORunner::enqueue(TaskInfo * task)
{
tasks_.push_back(*task);
#ifdef SENF_DEBUG
#endif
}
-prefix_ void senf::scheduler::FIFORunner::taskTimeout(unsigned ms)
+prefix_ void senf::scheduler::detail::FIFORunner::taskTimeout(unsigned ms)
{
watchdogMs_ = ms;
}
-prefix_ unsigned senf::scheduler::FIFORunner::taskTimeout()
+prefix_ unsigned senf::scheduler::detail::FIFORunner::taskTimeout()
const
{
return watchdogMs_;
}
-prefix_ unsigned senf::scheduler::FIFORunner::hangCount()
+prefix_ unsigned senf::scheduler::detail::FIFORunner::hangCount()
const
{
return hangCount_;
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-
- class Scheduler;
-
namespace scheduler {
- /** \brief Task execution scheduler
+ void restart();
- The FIFORunner implements a simple FIFO scheduler for callback tasks. All tasks are held in
- a queue. Whenever a task is run, it is moved to the end of the queue. Running the queue will
- run all tasks which have been marked runnable.
+namespace detail {
- When running a task, it's runnable flag is always reset. The flag is set whenever an event
- is posted for the task.
- */
class FIFORunner
: public singleton<FIFORunner>
{
typedef boost::intrusive::ilist<TaskListBase::value_traits<TaskInfo>, false> TaskList;
public:
- ///////////////////////////////////////////////////////////////////////////
- // Types
-
- /** \brief Task structure
-
- TaskInfo is the base-class for all tasks.
- */
class TaskInfo
: public TaskListBase
{
friend class FIFORunner;
};
-
- ///////////////////////////////////////////////////////////////////////////
- ///\name Structors and default members
- ///@{
-
using singleton<FIFORunner>::instance;
using singleton<FIFORunner>::alive;
- ///@}
- ///////////////////////////////////////////////////////////////////////////
-
- void enqueue(TaskInfo * task); ///< Add task to queue
- void dequeue(TaskInfo * task); ///< Remove task from queue
+ void enqueue(TaskInfo * task);
+ void dequeue(TaskInfo * task);
- void run(); ///< Run queue
+ void run();
- void taskTimeout(unsigned ms); ///< Set task timeout to \a ms milliseconds
- unsigned taskTimeout() const; ///< Get task timeout in milliseconds
+ void taskTimeout(unsigned ms);
+ unsigned taskTimeout() const;
unsigned hangCount() const; ///< Number of task expirations
/**< The FIFORunner manages a watchdog which checks, that a
unsigned watchdogCount_;
unsigned hangCount_;
+ friend void senf::scheduler::restart();
friend class singleton<FIFORunner>;
- friend class senf::Scheduler;
};
-}}
+}}}
///////////////////////////////hh.e////////////////////////////////////////
#include "FIFORunner.cci"
prefix_ senf::scheduler::detail::FdDispatcher::~FdDispatcher()
{
for (FdSet::iterator i (fds_.begin()); i != fds_.end(); ++i) {
- FdManager::instance().remove(i->fd_);
- FIFORunner::instance().dequeue(&(*i));
+ detail::FdManager::instance().remove(i->fd_);
+ detail::FIFORunner::instance().dequeue(&(*i));
}
}
if (event.events_ & events)
throw FdEvent::DuplicateEventRegistrationException();
- if (! FdManager::instance().set(event.fd_, events | event.events_, &event))
+ if (! detail::FdManager::instance().set(event.fd_, events | event.events_, &event))
return false;
- FIFORunner::instance().enqueue(&event);
+ detail::FIFORunner::instance().enqueue(&event);
fds_.insert(range.first, event);
return true;
prefix_ void senf::scheduler::detail::FdDispatcher::remove(FdEvent & event)
{
fds_.erase(FdSet::current(event));
- FIFORunner::instance().dequeue(&event);
+ detail::FIFORunner::instance().dequeue(&event);
std::pair<FdSet::iterator,FdSet::iterator> range (fds_.equal_range(event));
if (range.first == range.second)
- FdManager::instance().remove(event.fd_);
+ detail::FdManager::instance().remove(event.fd_);
else {
int events (0);
for (FdSet::iterator i (range.first); i != range.second; ++i)
events |= i->events_;
- FdManager::instance().set(event.fd_, events, &(*range.first));
+ detail::FdManager::instance().set(event.fd_, events, &(*range.first));
}
}
if (event.events_ & events)
throw FdEvent::DuplicateEventRegistrationException();
- FIFORunner::instance().enqueue(&event);
+ detail::FIFORunner::instance().enqueue(&event);
fds_.insert(range.first, event);
- FdManager::instance().timeout(0);
+ detail::FdManager::instance().timeout(0);
}
prefix_ senf::scheduler::detail::FileDispatcher::FileDispatcher()
- : managerTimeout_ (scheduler::FdManager::instance().timeout())
+ : managerTimeout_ (scheduler::detail::FdManager::instance().timeout())
{}
prefix_ senf::scheduler::detail::FileDispatcher::~FileDispatcher()
{
- FdManager::instance().timeout(-1);
+ detail::FdManager::instance().timeout(-1);
for (FdSet::iterator i (fds_.begin()); i != fds_.end(); ++i)
- FIFORunner::instance().dequeue(&(*i));
+ detail::FIFORunner::instance().dequeue(&(*i));
}
prefix_ void senf::scheduler::detail::FileDispatcher::prepareRun()
prefix_ void senf::scheduler::detail::FileDispatcher::remove(FdEvent & event)
{
fds_.erase(FdSet::current(event));
- FIFORunner::instance().dequeue(&event);
+ detail::FIFORunner::instance().dequeue(&event);
if (fds_.empty())
- FdManager::instance().timeout(managerTimeout_);
+ detail::FdManager::instance().timeout(managerTimeout_);
}
///////////////////////////////////////////////////////////////////////////
// senf::scheduler::FdEvent
prefix_ senf::scheduler::FdEvent::FdEvent(std::string const & name, Callback const & cb)
- : FIFORunner::TaskInfo (name), cb_ (cb), fd_ (-1), pollable_ (true), events_ (0)
+ : detail::FIFORunner::TaskInfo (name), cb_ (cb), fd_ (-1), pollable_ (true), events_ (0)
{}
prefix_ senf::scheduler::FdEvent::~FdEvent()
{
managerTimeout_ = t;
if (fds_.empty())
- FdManager::instance().timeout(managerTimeout_);
+ detail::FdManager::instance().timeout(managerTimeout_);
}
prefix_ int senf::scheduler::detail::FileDispatcher::timeout()
prefix_ senf::scheduler::FdEvent::FdEvent(std::string const & name, Callback const & cb,
Handle const & handle, int events,
bool initiallyEnabled)
- : FIFORunner::TaskInfo (name), cb_ (cb), fd_ (retrieve_filehandle(handle)), pollable_ (true),
+ : detail::FIFORunner::TaskInfo (name), cb_ (cb), fd_ (retrieve_filehandle(handle)), pollable_ (true),
events_ (events)
{
if (initiallyEnabled)
callback is a member function it should be defined as a class member).
*/
class FdEvent
- : public FIFORunner::TaskInfo,
+ : public detail::FIFORunner::TaskInfo,
public detail::FdSetBase,
- public FdManager::Event
+ public detail::FdManager::Event
{
public:
///////////////////////////////////////////////////////////////////////////
typedef boost::function<void (int)> Callback;
enum Events {
- EV_READ = FdManager::EV_READ, EV_PRIO = FdManager::EV_PRIO, EV_WRITE = FdManager::EV_WRITE,
- EV_HUP = FdManager::EV_HUP, EV_ERR = FdManager::EV_ERR,
- EV_ALL = FdManager::EV_READ | FdManager::EV_WRITE | FdManager::EV_PRIO
+ EV_NONE = 0,
+ EV_READ = detail::FdManager::EV_READ,
+ EV_PRIO = detail::FdManager::EV_PRIO,
+ EV_WRITE = detail::FdManager::EV_WRITE,
+ EV_HUP = detail::FdManager::EV_HUP,
+ EV_ERR = detail::FdManager::EV_ERR,
+ EV_ALL = (detail::FdManager::EV_READ
+ | detail::FdManager::EV_WRITE
+ | detail::FdManager::EV_PRIO)
};
///////////////////////////////////////////////////////////////////////////
///////////////////////////////ih.p////////////////////////////////////////
namespace senf {
+namespace scheduler {
- class Scheduler;
+ void restart();
-namespace scheduler {
namespace detail {
struct FdSetCompare {
FdSet fds_;
- friend class senf::Scheduler;
+ friend void senf::scheduler::restart();
friend class singleton<FdDispatcher>;
friend class senf::scheduler::FdEvent;
};
FdSet fds_;
int managerTimeout_;
- friend class senf::Scheduler;
+ friend void senf::scheduler::restart();
friend class singleton<FileDispatcher>;
};
BOOST_AUTO_UNIT_TEST(fdDispatcher)
{
- senf::scheduler::FdManager::instance().timeout(1000);
+ senf::scheduler::detail::FdManager::instance().timeout(1000);
int pid (start_server());
BOOST_REQUIRE( pid );
senf::scheduler::FdEvent sockwrite ("testHandler", boost::bind(&callback, sock, _1),
sock, senf::scheduler::FdEvent::EV_WRITE, false);
event = 0;
- SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_READ );
BOOST_CHECK_EQUAL( size, 4 );
buffer[size] = 0;
SENF_CHECK_NO_THROW( sockwrite.enable() );
event = 0;
sleep(1);
- SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_WRITE );
SENF_CHECK_NO_THROW( sockwrite.disable() );
event = 0;
sleep(1);
- SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_HUP | senf::scheduler::FdEvent::EV_READ );
BOOST_CHECK_EQUAL( size, 2 );
buffer[size]=0;
BOOST_CHECK_EQUAL( buffer, "OK" );
BOOST_CHECK_EQUAL( calls, 3 );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
BOOST_CHECK_EQUAL( calls, 3 );
// Ensure, removing an already closed file-descriptor doesn't wreak havoc
close(sock);
}
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
BOOST_CHECK_EQUAL( calls, 3 );
BOOST_CHECK (stop_server(pid));
try {
senf::scheduler::FdEvent fde ("testHandler", &handler,
fd, senf::scheduler::FdEvent::EV_READ);
- SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
SENF_CHECK_NO_THROW( senf::scheduler::detail::FileDispatcher::instance().prepareRun() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
BOOST_CHECK( called );
BOOST_CHECK_PREDICATE( is_close, (t)(senf::ClockService::now()) );
called = false;
t = senf::ClockService::now();
- SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
SENF_CHECK_NO_THROW( senf::scheduler::detail::FileDispatcher::instance().prepareRun() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
BOOST_CHECK( ! called );
BOOST_CHECK_PREDICATE(
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-prefix_ void senf::scheduler::FdManager::processOnce()
+prefix_ void senf::scheduler::detail::FdManager::processOnce()
{
Poller<Event>::range events (poller_.wait());
eventTime_ = ClockService::now();
///////////////////////////////////////////////////////////////////////////
// senf::scheduler::FdManager
-prefix_ senf::scheduler::FdManager::FdManager()
+prefix_ senf::scheduler::detail::FdManager::FdManager()
: eventTime_ (senf::ClockService::now())
{}
-prefix_ bool senf::scheduler::FdManager::set(int fd, int events, Event * entry)
+prefix_ bool senf::scheduler::detail::FdManager::set(int fd, int events, Event * entry)
{
return poller_.set(fd, events, entry);
}
-prefix_ void senf::scheduler::FdManager::remove(int fd)
+prefix_ void senf::scheduler::detail::FdManager::remove(int fd)
{
poller_.remove(fd);
}
-prefix_ void senf::scheduler::FdManager::timeout(int t)
+prefix_ void senf::scheduler::detail::FdManager::timeout(int t)
{
poller_.timeout(t);
}
-prefix_ int senf::scheduler::FdManager::timeout()
+prefix_ int senf::scheduler::detail::FdManager::timeout()
const
{
return poller_.timeout();
}
-prefix_ senf::ClockService::clock_type senf::scheduler::FdManager::eventTime()
+prefix_ senf::ClockService::clock_type senf::scheduler::detail::FdManager::eventTime()
const
{
return eventTime_;
}
///////////////////////////////////////////////////////////////////////////
-// senf::scheduler::FdManager::Event
+// senf::scheduler::detail::FdManager::Event
-prefix_ senf::scheduler::FdManager::Event::~Event()
+prefix_ senf::scheduler::detail::FdManager::Event::~Event()
{}
///////////////////////////////cci.e///////////////////////////////////////
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-
- class Scheduler;
-
namespace scheduler {
- /** \brief Manage file descriptor event processing
-
- The FdManager is the internal class which manages all events (all events need to somehow be
- made accessible via a file descriptor). File descriptors are added or removed from the
- FdManager which then allows waiting until an event occurs on one of the descriptors.
+ void restart();
- Registered events must be derived from FdManager::Event. The FdManager does \e not manage
- the event classes, it just manages pointers to externally owned events (the events are owned
- by the respective dispatchers).
+namespace detail {
- When an event is posted, it's \c signal() member is called. However, this call will \e not
- execute the user callback registered for the event, it will just mark the relevant tasks as
- runnable.
-
- \implementation
- */
class FdManager
: public singleton<FdManager>
{
public:
- ///////////////////////////////////////////////////////////////////////////
- // Types
-
///< Event baseclass
struct Event {
virtual ~Event();
EV_HUP = Poller<Event>::EV_HUP, EV_ERR = Poller<Event>::EV_ERR
};
- ///////////////////////////////////////////////////////////////////////////
- ///\name Structors and default members
- ///@{
-
using singleton<FdManager>::instance;
using singleton<FdManager>::alive;
- ///@}
- ///////////////////////////////////////////////////////////////////////////
-
- bool set(int fd, int events, Event * entry); ///< Set file descriptor event mask
- /**< This sets the event mask for \a fd to \a events which
- is a combination of values from the \c Events enum. If
- \a fd is already registered, the registration is
- changed to conform to the parameters passed, otherwise
- a new registration is added.
- \param[in] fd file descriptor
- \param[in] events events to register for
- \param[in] entry event to signal
- \returns \c true, if \a fd supports polling, \c false
- otherwise */
- void remove(int fd); ///< Remove \a fd from the manager
-
+ bool set(int fd, int events, Event * entry);
+ void remove(int fd);
void timeout(int t); ///< Set event timeout
/**< proceseOnce() will wait for max \a t milliseconds for
an event to occur. If set to -1, processOnce() will
wait forever. */
- int timeout() const; ///< Get timeout in milliseconds
-
+ int timeout() const;
void processOnce(); ///< Wait for events
/**< This call waits until at least one event is posted but
no longer than the current timeout(). */
-
ClockService::clock_type eventTime() const; ///< Time of last event
protected:
Poller<Event> poller_;
senf::ClockService::clock_type eventTime_;
+ friend void senf::scheduler::restart();
friend class singleton<FdManager>;
- friend class senf::Scheduler;
};
-}}
+}}}
///////////////////////////////hh.e////////////////////////////////////////
#include "FdManager.cci"
\li The Dispatcher registeres all callbacks as tasks with the runner
(senf::scheduler::FIFORunner).
- \li The senf::scheduler::FdManager uses senf::scheduler::Poller to access the low-level epoll()
+ \li The senf::scheduler::FdManager uses senf::scheduler::detail::Poller to access the low-level epoll()
API.
All these classes are \e not singletons. They are all instantiatied by the senf::Scheduler
///////////////////////////////ct.p////////////////////////////////////////
template <class Value>
-prefix_ bool senf::scheduler::Poller<Value>::set(int fd, int events, Value * data)
+prefix_ bool senf::scheduler::detail::Poller<Value>::set(int fd, int events, Value * data)
{
struct epoll_event ev = { events, { data } };
if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &ev) != -1)
}
template <class Value>
-prefix_ void senf::scheduler::Poller<Value>::remove(int fd)
+prefix_ void senf::scheduler::detail::Poller<Value>::remove(int fd)
{
if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, 0) == -1)
if (errno != ENOENT && errno != EBADF && errno != EPERM)
}
template <class Value>
-prefix_ typename senf::scheduler::Poller<Value>::range senf::scheduler::Poller<Value>::wait()
+prefix_ typename senf::scheduler::detail::Poller<Value>::range senf::scheduler::detail::Poller<Value>::wait()
{
static epoll_event events[NumEvents];
int rv (0);
///////////////////////////////cti.p///////////////////////////////////////
template <class Value>
-prefix_ senf::scheduler::Poller<Value>::Poller()
+prefix_ senf::scheduler::detail::Poller<Value>::Poller()
: timeout_ (-1)
{
epollFd_ = epoll_create(NumEvents);
}
template <class Value>
-prefix_ senf::scheduler::Poller<Value>::~Poller()
+prefix_ senf::scheduler::detail::Poller<Value>::~Poller()
{
close(epollFd_);
}
template <class Value>
-prefix_ void senf::scheduler::Poller<Value>::timeout(int t)
+prefix_ void senf::scheduler::detail::Poller<Value>::timeout(int t)
{
timeout_ = t;
}
template <class Value>
-prefix_ int senf::scheduler::Poller<Value>::timeout()
+prefix_ int senf::scheduler::detail::Poller<Value>::timeout()
const
{
return timeout_;
}
template <class Value>
-prefix_ typename senf::scheduler::Poller<Value>::GetPollResult::result_type
-senf::scheduler::Poller<Value>::GetPollResult::operator()(epoll_event const & ev)
+prefix_ typename senf::scheduler::detail::Poller<Value>::GetPollResult::result_type
+senf::scheduler::detail::Poller<Value>::GetPollResult::operator()(epoll_event const & ev)
const
{
namespace senf {
namespace scheduler {
+namespace detail {
/** \brief Epoll abstraction
enum Events {
EV_READ = EPOLLIN, EV_PRIO = EPOLLPRI, EV_WRITE = EPOLLOUT,
EV_HUP = EPOLLHUP, EV_ERR = EPOLLERR
-};
-
+ };
+
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
};
-}}
+}}}
///////////////////////////////hh.e////////////////////////////////////////
//#include "Poller.cci"
prefix_ void senf::ReadHelper<Handle>::process(Handle handle,int event)
{
try {
- if (event != senf::Scheduler::EV_READ)
+ if (event != senf::scheduler::FdEvent::EV_READ)
throw SystemException(EPIPE SENF_EXC_DEBUGINFO);
std::string rcv;
handle.read(rcv, maxSize_ - data_.size());
#define prefix_
///////////////////////////////cc.p////////////////////////////////////////
-prefix_ void senf::Scheduler::process()
+namespace {
+ bool terminate_ (false);
+}
+
+prefix_ void senf::scheduler::terminate()
+{
+ terminate_ = true;
+}
+
+prefix_ void senf::scheduler::process()
{
terminate_ = false;
- while(! terminate_ && ! (scheduler::detail::FdDispatcher::instance().empty() &&
- scheduler::detail::TimerDispatcher::instance().empty() &&
- scheduler::detail::FileDispatcher::instance().empty())) {
- scheduler::detail::SignalDispatcher::instance().unblockSignals();
- scheduler::detail::TimerDispatcher::instance().unblockSignals();
- scheduler::FdManager::instance().processOnce();
- scheduler::detail::TimerDispatcher::instance().blockSignals();
- scheduler::detail::SignalDispatcher::instance().blockSignals();
- scheduler::detail::FileDispatcher::instance().prepareRun();
- scheduler::FIFORunner::instance().run();
+ while(! terminate_ && ! (detail::FdDispatcher::instance().empty() &&
+ detail::TimerDispatcher::instance().empty() &&
+ detail::FileDispatcher::instance().empty())) {
+ detail::SignalDispatcher::instance().unblockSignals();
+ detail::TimerDispatcher::instance().unblockSignals();
+ detail::FdManager::instance().processOnce();
+ detail::TimerDispatcher::instance().blockSignals();
+ detail::SignalDispatcher::instance().blockSignals();
+ detail::FileDispatcher::instance().prepareRun();
+ detail::FIFORunner::instance().run();
}
}
-prefix_ void senf::Scheduler::restart()
+prefix_ void senf::scheduler::restart()
{
- scheduler::FdManager* fdm (&scheduler::FdManager::instance());
- scheduler::FIFORunner* ffr (&scheduler::FIFORunner::instance());
- scheduler::detail::FdDispatcher* fdd (&scheduler::detail::FdDispatcher::instance());
- scheduler::detail::TimerDispatcher* td (&scheduler::detail::TimerDispatcher::instance());
- scheduler::detail::SignalDispatcher* sd (&scheduler::detail::SignalDispatcher::instance());
- scheduler::detail::FileDispatcher* fld (&scheduler::detail::FileDispatcher::instance());
+ detail::FdManager* fdm (&detail::FdManager::instance());
+ detail::FIFORunner* ffr (&detail::FIFORunner::instance());
+ detail::FdDispatcher* fdd (&detail::FdDispatcher::instance());
+ detail::TimerDispatcher* tdd (&detail::TimerDispatcher::instance());
+ detail::SignalDispatcher* sdd (&detail::SignalDispatcher::instance());
+ detail::FileDispatcher* fld (&detail::FileDispatcher::instance());
fld->~FileDispatcher();
- sd->~SignalDispatcher();
- td->~TimerDispatcher();
+ sdd->~SignalDispatcher();
+ tdd->~TimerDispatcher();
fdd->~FdDispatcher();
ffr->~FIFORunner();
fdm->~FdManager();
- new (fdm) scheduler::FdManager();
- new (ffr) scheduler::FIFORunner();
- new (fdd) scheduler::detail::FdDispatcher();
- new (td) scheduler::detail::TimerDispatcher();
- new (sd) scheduler::detail::SignalDispatcher();
- new (fld) scheduler::detail::FileDispatcher();
+ new (fdm) detail::FdManager();
+ new (ffr) detail::FIFORunner();
+ new (fdd) detail::FdDispatcher();
+ new (tdd) detail::TimerDispatcher();
+ new (sdd) detail::SignalDispatcher();
+ new (fld) detail::FileDispatcher();
}
///////////////////////////////////////////////////////////////////////////
-// senf::SchedulerLogTimeSource
+// senf::schedulerLogTimeSource
-prefix_ senf::log::time_type senf::SchedulerLogTimeSource::operator()()
+prefix_ senf::log::time_type senf::scheduler::LogTimeSource::operator()()
const
{
- return Scheduler::instance().eventTime();
+ return eventTime();
}
///////////////////////////////cc.e////////////////////////////////////////
// public members
-prefix_ senf::Scheduler::Scheduler & senf::Scheduler::instance()
+prefix_ senf::ClockService::clock_type senf::scheduler::eventTime()
{
- static Scheduler instance;
- return instance;
+ return scheduler::detail::FdManager::instance().eventTime();
}
-prefix_ void senf::Scheduler::terminate()
+prefix_ void senf::scheduler::taskTimeout(unsigned ms)
{
- terminate_ = true;
+ scheduler::detail::FIFORunner::instance().taskTimeout(ms);
}
-prefix_ senf::ClockService::clock_type senf::Scheduler::eventTime()
- const
+prefix_ unsigned senf::scheduler::taskTimeout()
{
- return scheduler::FdManager::instance().eventTime();
+ return scheduler::detail::FIFORunner::instance().taskTimeout();
}
-prefix_ void senf::Scheduler::taskTimeout(unsigned ms)
+prefix_ unsigned senf::scheduler::hangCount()
{
- scheduler::FIFORunner::instance().taskTimeout(ms);
+ return scheduler::detail::FIFORunner::instance().hangCount();
}
-prefix_ unsigned senf::Scheduler::taskTimeout()
- const
-{
- return scheduler::FIFORunner::instance().taskTimeout();
-}
-
-prefix_ unsigned senf::Scheduler::hangCount()
- const
-{
- return scheduler::FIFORunner::instance().hangCount();
-}
-
-prefix_ senf::Scheduler::Scheduler()
- : terminate_ (false)
-{}
-
///////////////////////////////cci.e///////////////////////////////////////
#undef prefix_
#include "FdEvent.hh"
#include "TimerEvent.hh"
#include "SignalEvent.hh"
-#include "../Utils/Logger/SenfLog.hh"
//#include "scheduler.mpp"
///////////////////////////////hh.p////////////////////////////////////////
-/** \brief SENF Project namespace */
namespace senf {
- /** \brief Visible scheduler interface
-
- 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
-
- The %scheduler is entered by calling it's process() member. This call will continue to run as
- long as there is something to do, or until one of the handlers calls terminate(). The
- %scheduler has 'something to do' as long as there is any file descriptor or timeout active.
-
- The %scheduler only provides low level primitive scheduling capability. Additional helpers
- are defined on top of this functionality (e.g. ReadHelper or WriteHelper or the interval
- timers of the PPI).
+/** \brief Visible scheduler interface
+
+ 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
+
+ The %scheduler is entered by calling it's process() member. This call will continue to run as
+ long as there is something to do, or until one of the handlers calls terminate(). The
+ %scheduler has 'something to do' as long as there is any file descriptor or timeout active.
+
+ The %scheduler only provides low level primitive scheduling capability. Additional helpers
+ are defined on top of this functionality (e.g. ReadHelper or WriteHelper or the interval
+ timers of the PPI).
+
+
+ \section sched_handlers Specifying handlers
+
+ All handlers are passed as generic <a
+ href="http://www.boost.org/doc/html/function.html">Boost.Function</a> objects. This allows
+ to pass any callable as a handler. Depending on the type of handler, some additional
+ arguments may be passed to the handler by the %scheduler.
+
+ 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), EV_READ)
+ // Timeout function
+ void timeout( int n) {..}
+ // Call timeout() handler with argument 'n'
+ Scheduler::instance().timeout(boost::bind(&timeout, n))
+ \endcode
+
+ To use member-functions as callbacks, use either <a
+ 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)), 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, EV_ALL);
+ Scheduler::instance().remove(handle);
+ \endcode
+
+ The callback will be called with one additional argument. This argument is the event mask of
+ type EventId. This mask will tell, which of the registered events are signaled. The
+ additional flags EV_HUP or EV_ERR (on hangup or error condition) may be set additionally.
+
+ Only a single handler may be registered for any combination of file descriptor and event
+ (registering multiple callbacks for a single fd and event does not make sense).
+
+ The %scheduler will accept any object as \a handle argument as long as retrieve_filehandle()
+ may be called on that object
+ \code
+ int fd = retrieve_filehandle(handle);
+ \endcode
+ to fetch the file handle given some abstract handle type. retrieve_filehandle() will be
+ found using ADL depending on the argument namespace. A default implementation is provided
+ for \c int arguments (file descriptors)
+
+
+ \section sched_timers Registering timers
+
+ The %scheduler has very simple timer support. There is only one type of timer: A single-shot
+ deadline timer. More complex timers are built based on this. Timers are managed using
+ timeout() and cancelTimeout()
+ \code
+ int id = Scheduler::instance().timeout(Scheduler::instance().eventTime() + ClockService::milliseconds(100),
+ &callback);
+ Scheduler::instance().cancelTimeout(id);
+ \endcode
+ Timing is based on the ClockService, which provides a high resolution and strictly
+ 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
+
+ The %scheduler also incorporates standard POSIX/UNIX signals. Signals registered with the
+ %scheduler will be handled \e synchronously within the event loop.
+ \code
+ Scheduler::instance().registerSignal(SIGUSR1, &callback);
+ Scheduler::instance().unregisterSignal(SIGUSR1);
+ \endcode
+ When registering a signal with the %scheduler, that signal will automatically be blocked so
+ it can be handled within the %scheduler.
+
+ A registered signal does \e not count as 'something to do'. It is therefore not possible to
+ wait for signals \e only.
+
+ \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.
+ */
+namespace scheduler {
+
+ /** \brief Event handler main loop
+
+ This member must be called at some time to enter the event handler main loop. Only while
+ this function is running any events are handled. The call will return if
+ \li a callback calls terminate()
+ \li the run queue becomes empty.
+ */
+ void process();
+ /** \brief Called by callbacks to terminate the main loop
- \section sched_handlers Specifying handlers
+ This member may be called by any callback to tell the main loop to terminate. The main loop
+ will return to it's caller after the currently running callback returns.
+ */
+ void terminate();
- All handlers are passed as generic <a
- href="http://www.boost.org/doc/html/function.html">Boost.Function</a> objects. This allows
- to pass any callable as a handler. Depending on the type of handler, some additional
- arguments may be passed to the handler by the %scheduler.
+ /** \brief Return date/time of last event
- 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), EV_READ)
- // Timeout function
- void timeout( int n) {..}
- // Call timeout() handler with argument 'n'
- Scheduler::instance().timeout(boost::bind(&timeout, n))
- \endcode
+ 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).
+ */
+ ClockService::clock_type eventTime();
- To use member-functions as callbacks, use either <a
- 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)), EV_READ)
- \endcode
+ /** \brief Set task watchdog timeout */
+ void taskTimeout(unsigned ms);
- The handler can also be identified by an arbitrary, user specified name. This name is used
- in error messages to identify the failing handler.
+ /** \brief Current task watchdog timeout */
+ unsigned taskTimeout();
+ /** \brief Number of watchdog events */
+ unsigned hangCount();
- \section sched_fd Registering file descriptors
-
- File descriptors are managed using add() or remove()
- \code
- Scheduler::instance().add(handle, &callback, EV_ALL);
- Scheduler::instance().remove(handle);
- \endcode
-
- The callback will be called with one additional argument. This argument is the event mask of
- type EventId. This mask will tell, which of the registered events are signaled. The
- additional flags EV_HUP or EV_ERR (on hangup or error condition) may be set additionally.
-
- Only a single handler may be registered for any combination of file descriptor and event
- (registering multiple callbacks for a single fd and event does not make sense).
-
- The %scheduler will accept any object as \a handle argument as long as retrieve_filehandle()
- may be called on that object
- \code
- int fd = retrieve_filehandle(handle);
- \endcode
- to fetch the file handle given some abstract handle type. retrieve_filehandle() will be
- found using ADL depending on the argument namespace. A default implementation is provided
- for \c int arguments (file descriptors)
-
-
- \section sched_timers Registering timers
-
- The %scheduler has very simple timer support. There is only one type of timer: A single-shot
- deadline timer. More complex timers are built based on this. Timers are managed using
- timeout() and cancelTimeout()
- \code
- int id = Scheduler::instance().timeout(Scheduler::instance().eventTime() + ClockService::milliseconds(100),
- &callback);
- Scheduler::instance().cancelTimeout(id);
- \endcode
- Timing is based on the ClockService, which provides a high resolution and strictly
- 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
-
- The %scheduler also incorporates standard POSIX/UNIX signals. Signals registered with the
- %scheduler will be handled \e synchronously within the event loop.
- \code
- Scheduler::instance().registerSignal(SIGUSR1, &callback);
- Scheduler::instance().unregisterSignal(SIGUSR1);
- \endcode
- When registering a signal with the %scheduler, that signal will automatically be blocked so
- it can be handled within the %scheduler.
-
- A registered signal does \e not count as 'something to do'. It is therefore not possible to
- wait for signals \e only.
-
- \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.
- */
- class Scheduler
- : boost::noncopyable
- {
- public:
-
- SENF_LOG_CLASS_AREA();
-
- ///////////////////////////////////////////////////////////////////////////
- // Types
-
- /** \brief Types of file descriptor events
-
- These events are grouped into to classes:
- \li Ordinary file descriptor events for which handlers may be registered. These are
- EV_READ, EV_PRIO and EV_WRITE. EV_ALL is a combination of these three.
- \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 = 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 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
- ///@{
-
- // private default constructor
- // no copy constructor
- // no copy assignment
- // default destructor
- // no conversion constructors
-
- /** \brief Return %scheduler instance
-
- 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
- */
- static Scheduler & instance();
-
- ///@}
- ///////////////////////////////////////////////////////////////////////////
-
- 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
- running any events are handled. The call will return
- only, if any callback calls terminate(). */
-
- void terminate(); ///< Called by callbacks to terminate the main loop
- /**< This member may be called by any callback to tell the
- main loop to terminate. The main loop will return to
- it's caller after the currently running callback
- returns. */
+ /** \brief Restart scheduler
- 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();
-
- bool terminate_;
- };
+ This call will restart all scheduler dispatchers (timers, signals, file descriptors). This
+ is necessary after a fork().
+ \warning This call will \e remove all registered events from the scheduler
+ */
+ void restart();
/** \brief %scheduler specific time source for Utils/Logger framework
This time source may be used to provide timing information for log messages within the
Utils/Logger framework. This time source will use Scheduler::eventTime() to provide timing
information.
+
+ Using this information reduces the number of necessary ClockService::now() calls and thus
+ the number of system calls.
*/
- struct SchedulerLogTimeSource : public senf::log::TimeSource
+ struct LogTimeSource : public senf::log::TimeSource
{
senf::log::time_type operator()() const;
};
-}
+}}
///////////////////////////////hh.e////////////////////////////////////////
#include "Scheduler.cci"
void callback(int fd, int ev)
{
event = ev;
- switch (event & Scheduler::EV_ALL) {
- case Scheduler::EV_READ:
+ switch (event & senf::scheduler::FdEvent::EV_ALL) {
+ case senf::scheduler::FdEvent::EV_READ:
size = recv(fd,buffer,1024,0);
break;
- case Scheduler::EV_PRIO:
+ case senf::scheduler::FdEvent::EV_PRIO:
size = recv(fd,buffer,1024,MSG_OOB);
- Scheduler::instance().terminate();
break;
- case Scheduler::EV_WRITE:
+ case senf::scheduler::FdEvent::EV_WRITE:
size = write(fd,buffer,size);
- Scheduler::instance().terminate();
break;
}
- Scheduler::instance().terminate();
+ senf::scheduler::terminate();
}
bool timeoutCalled = false;
void timeout()
{
timeoutCalled = true;
- Scheduler::instance().terminate();
+ senf::scheduler::terminate();
}
struct HandleWrapper
void sigusr(siginfo_t const &)
{
sigtime = ClockService::now();
- Scheduler::instance().terminate();
+ senf::scheduler::terminate();
}
void delay(unsigned long milliseconds)
void blockingHandler()
{
delay(2200);
- Scheduler::instance().terminate();
+ senf::scheduler::terminate();
}
}
///////////////////////////////////////////////////////////////////////////
- BOOST_CHECK_NO_THROW( Scheduler::instance() );
-
{
senf::scheduler::FdEvent fde1 ("testFdEvent", boost::bind(&callback, sock, _1),
sock, senf::scheduler::FdEvent::EV_READ);
- event = Scheduler::EV_NONE;
- BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
- BOOST_CHECK_EQUAL( event, Scheduler::EV_READ );
+ event = senf::scheduler::FdEvent::EV_NONE;
+ BOOST_CHECK_NO_THROW( senf::scheduler::process() );
+ BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_READ );
BOOST_REQUIRE_EQUAL( size, 4 );
buffer[size]=0;
BOOST_CHECK_EQUAL( buffer, "READ" );
handle, senf::scheduler::FdEvent::EV_WRITE);
strcpy(buffer,"WRITE");
size=5;
- event = Scheduler::EV_NONE;
- BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
- BOOST_CHECK_EQUAL( event, Scheduler::EV_WRITE );
+ event = senf::scheduler::FdEvent::EV_NONE;
+ BOOST_CHECK_NO_THROW( senf::scheduler::process() );
+ BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_WRITE );
SENF_CHECK_NO_THROW( fde2.disable() );
- event = Scheduler::EV_NONE;
+ event = senf::scheduler::FdEvent::EV_NONE;
sleep(1);
- BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
- BOOST_CHECK_EQUAL( event, Scheduler::EventId(Scheduler::EV_READ|Scheduler::EV_HUP) );
+ BOOST_CHECK_NO_THROW( senf::scheduler::process() );
+ BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_READ|senf::scheduler::FdEvent::EV_HUP );
BOOST_REQUIRE_EQUAL( size, 2 );
buffer[size]=0;
BOOST_CHECK_EQUAL( buffer, "OK" );
senf::scheduler::TimerEvent timer2 ("testTimer2", &timeout,
ClockService::now()+ClockService::milliseconds(400));
- event = Scheduler::EV_NONE;
+ event = senf::scheduler::FdEvent::EV_NONE;
ClockService::clock_type t (ClockService::now());
- BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
+ BOOST_CHECK_NO_THROW( senf::scheduler::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()) );
+ BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_NONE );
+ BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (senf::scheduler::eventTime()) );
timeoutCalled = false;
- BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
+ BOOST_CHECK_NO_THROW( senf::scheduler::process() );
BOOST_CHECK_PREDICATE( is_close, (ClockService::now()-t) (ClockService::milliseconds(400)) );
BOOST_CHECK( timeoutCalled );
- BOOST_CHECK_EQUAL( event, Scheduler::EV_NONE );
+ BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::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 );
+ BOOST_CHECK_NO_THROW( senf::scheduler::process() );
+ BOOST_CHECK_EQUAL( senf::scheduler::hangCount(), 1u );
}
{
ClockService::clock_type t = ClockService::now();
::kill(::getpid(), SIGUSR1);
delay(100);
- BOOST_CHECK_NO_THROW( Scheduler::instance().process() );
+ BOOST_CHECK_NO_THROW( senf::scheduler::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( senf::scheduler::process() );
}
///////////////////////////////////////////////////////////////////////////
if (pipe(sigPipe_) <0)
SENF_THROW_SYSTEM_EXCEPTION("pipe()");
sigemptyset(&sigSet_);
- FdManager::instance().set(sigPipe_[0], FdManager::EV_READ, this);
+ detail::FdManager::instance().set(sigPipe_[0], detail::FdManager::EV_READ, this);
}
prefix_ senf::scheduler::detail::SignalDispatcher::~SignalDispatcher()
{
for (SignalSet::iterator i (handlers_.begin()); i != handlers_.end(); ++i) {
::signal(i->signal_, SIG_DFL);
- FIFORunner::instance().dequeue(&(*i));
+ detail::FIFORunner::instance().dequeue(&(*i));
}
sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
- FdManager::instance().remove(sigPipe_[0]);
+ detail::FdManager::instance().remove(sigPipe_[0]);
close(sigPipe_[0]);
close(sigPipe_[1]);
}
handlers_.insert(event);
sigaddset(&sigSet_, event.signal_);
- FIFORunner::instance().enqueue(&event);
+ detail::FIFORunner::instance().enqueue(&event);
sigset_t sig;
sigemptyset(&sig);
prefix_ void senf::scheduler::detail::SignalDispatcher::remove(SignalEvent & event)
{
::signal(event.signal_, SIG_DFL);
- FIFORunner::instance().dequeue(&event);
+ detail::FIFORunner::instance().dequeue(&event);
handlers_.erase(event);
sigset_t sig;
sigemptyset(&sig);
prefix_ senf::scheduler::SignalEvent::SignalEvent(int signal, Callback const & cb,
bool initiallyEnabled)
- : FIFORunner::TaskInfo(signalName(signal)), signal_ (signal), cb_ (cb)
+ : detail::FIFORunner::TaskInfo(signalName(signal)), signal_ (signal), cb_ (cb)
{
if (initiallyEnabled)
enable();
callback is a member function it should be defined as a class member).
*/
class SignalEvent
- : public FIFORunner::TaskInfo,
+ : public detail::FIFORunner::TaskInfo,
public detail::SignalSetBase
{
public:
friend class detail::SignalSetCompare;
friend class detail::FindNumericSignal;
friend class detail::SignalDispatcher;
- friend class senf::Scheduler;
};
///////////////////////////////ih.p////////////////////////////////////////
namespace senf {
-
- class Scheduler;
-
namespace scheduler {
+
+ void restart();
+
namespace detail {
struct SignalSetCompare {
};
class SignalDispatcher
- : public FdManager::Event,
+ : public detail::FdManager::Event,
public singleton<SignalDispatcher>
{
typedef boost::intrusive::iset< SignalSetBase::value_traits<SignalEvent>,
bool blocked_;
sigset_t sigSet_;
+ friend void senf::scheduler::restart();
friend class senf::scheduler::SignalEvent;
friend class singleton<SignalDispatcher>;
- friend class senf::Scheduler;
};
}}}
BOOST_AUTO_UNIT_TEST(signalDispatcher)
{
- senf::scheduler::FdManager::instance().timeout(1000);
+ senf::scheduler::detail::FdManager::instance().timeout(1000);
senf::scheduler::SignalEvent sig (SIGUSR1, &handler);
SENF_CHECK_NO_THROW( sig.disable() );
::kill(::getpid(), SIGUSR1);
sleep(1);
SENF_CHECK_NO_THROW( senf::scheduler::detail::SignalDispatcher::instance().unblockSignals() );
- SENF_CHECK_NO_THROW( senf::scheduler::FdManager::instance().processOnce() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
SENF_CHECK_NO_THROW( senf::scheduler::detail::SignalDispatcher::instance().blockSignals() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
BOOST_CHECK( called );
}
{
if (pipe(timerPipe_) < 0)
SENF_THROW_SYSTEM_EXCEPTION("pipe()");
- senf::scheduler::FdManager::instance().set(timerPipe_[0], FdManager::EV_READ, this);
+ senf::scheduler::detail::FdManager::instance().set(timerPipe_[0], detail::FdManager::EV_READ, this);
sigemptyset(&sigSet_);
sigaddset(&sigSet_, SIGALRM);
TimerSet::iterator i (timers_.begin());
TimerSet::iterator const i_end (timers_.end());
for (; i != i_end; ++i)
- senf::scheduler::FIFORunner::instance().dequeue(&(*i));
+ senf::scheduler::detail::FIFORunner::instance().dequeue(&(*i));
timer_delete(timerId_);
::signal(SIGALRM, SIG_IGN);
sigprocmask(SIG_UNBLOCK, &sigSet_, 0);
- senf::scheduler::FdManager::instance().remove(timerPipe_[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::FIFORunner::instance().enqueue(&(*i));
+ senf::scheduler::detail::FIFORunner::instance().enqueue(&(*i));
if (! blocked_)
reschedule();
}
TimerSet::iterator i (TimerSet::current(event));
if (i == timers_.end())
return;
- senf::scheduler::FIFORunner::instance().dequeue(&(*i));
+ senf::scheduler::detail::FIFORunner::instance().dequeue(&(*i));
timers_.erase(i);
if (! blocked_)
reschedule();
return;
TimerSet::iterator i (timers_.begin());
TimerSet::iterator const i_end (timers_.end());
- ClockService::clock_type now (senf::scheduler::FdManager::instance().eventTime());
+ ClockService::clock_type now (senf::scheduler::detail::FdManager::instance().eventTime());
for (; i != i_end && i->timeout_ <= now ; ++i)
i->setRunnable();
}
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)
+ : detail::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)
+ : detail::FIFORunner::TaskInfo (name), cb_ (cb), timeout_ (0)
{}
prefix_ senf::scheduler::TimerEvent::~TimerEvent()
callback is a member function it should be defined as a class member).
*/
class TimerEvent
- : public FIFORunner::TaskInfo,
+ : public detail::FIFORunner::TaskInfo,
public detail::TimerSetBase
{
public:
///////////////////////////////ih.p////////////////////////////////////////
namespace senf {
+namespace scheduler {
- class Scheduler;
+ void restart();
-namespace scheduler {
namespace detail {
struct TimerSetCompare {
};
class TimerDispatcher
- : public FdManager::Event,
+ : public detail::FdManager::Event,
public singleton<TimerDispatcher>
{
SENF_LOG_CLASS_AREA();
bool blocked_;
timer_t timerId_;
- friend class senf::Scheduler;
+ friend void senf::scheduler::restart();
friend class singleton<TimerDispatcher>;
};
BOOST_AUTO_UNIT_TEST(timerDispatcher)
{
- senf::scheduler::FdManager::instance().timeout(1000);
+ senf::scheduler::detail::FdManager::instance().timeout(1000);
senf::ClockService::clock_type t (senf::ClockService::now());
{
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::FdManager::instance().processOnce() );
SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().blockSignals() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
senf::ClockService::clock_type t2 (senf::ClockService::now());
BOOST_CHECK( called );
BOOST_CHECK( ! timer.enabled() );
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::FdManager::instance().processOnce() );
SENF_CHECK_NO_THROW( senf::scheduler::detail::TimerDispatcher::instance().blockSignals() );
- SENF_CHECK_NO_THROW( senf::scheduler::FIFORunner::instance().run() );
+ SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
BOOST_CHECK_PREDICATE( is_close, (t) (senf::ClockService::now()) );
BOOST_CHECK( called );
}
}
template <class Handle>
-prefix_ void
-senf::WriteHelper<Handle>::dispatchProcess(ptr helper, Handle handle,
- senf::Scheduler::EventId event)
+prefix_ void senf::WriteHelper<Handle>::dispatchProcess(ptr helper, Handle handle,
+ senf::scheduler::FdEvent::Events event)
{
// since we have a 'ptr' argument, the instance cannot be deleted
// before this method returns
template <class Handle>
prefix_ void senf::WriteHelper<Handle>::process(Handle handle,
- senf::Scheduler::EventId event)
+ senf::scheduler::FdEvent::Events event)
{
bool complete_ (false);
try {
- if (event != senf::Scheduler::EV_WRITE)
+ if (event != senf::scheduler::FdEvent::EV_WRITE)
throw SystemException(EPIPE SENF_EXC_DEBUGINFO);
offset_ = handle.write(std::make_pair(offset_,data_.end()));
if (offset_ == data_.end()) {
private:
WriteHelper(Handle handle, std::string const & data, Callback callback);
- static void dispatchProcess(ptr helper, Handle handle, senf::Scheduler::EventId event);
- void process(Handle handle, senf::Scheduler::EventId event);
+ static void dispatchProcess(ptr helper, Handle handle,
+ senf::scheduler::FdEvent::Events event);
+ void process(Handle handle, senf::scheduler::FdEvent::Events event);
void done();
Handle handle_;
friend class FileBody;
};
- /** \brief Adapt FileHandle to senf::Scheduler
+ /** \brief Adapt FileHandle to senf::scheduler
\related senf::FileHandle
\internal
LIBC_CALL( ::setsid, () );
LIBC_CALL( ::sigprocmask, (SIG_SETMASK, &oldsig, 0) );
- senf::Scheduler::instance().restart();
+ senf::scheduler::restart();
return;
}
LIBC_CALL( ::close, (coutpipe[1]) );
LIBC_CALL( ::close, (cerrpipe[1]) );
- senf::Scheduler::instance().restart();
+ senf::scheduler::restart();
detail::DaemonWatcher watcher (pid, coutpipe[0], cerrpipe[0], stdout_, stderr_);
watcher.run();
prefix_ void senf::detail::DaemonWatcher::run()
{
- Scheduler::instance().process();
+ scheduler::process();
}
////////////////////////////////////////
childDied(); // does not return
if (::kill(childPid_, SIGUSR1) < 0 && errno != ESRCH)
SENF_THROW_SYSTEM_EXCEPTION("::kill()");
- timer_.timeout(Scheduler::instance().eventTime() + ClockService::seconds(1));
+ timer_.timeout(scheduler::eventTime() + ClockService::seconds(1));
}
}
prefix_ void senf::detail::DaemonWatcher::childOk()
{
- Scheduler::instance().terminate();
+ scheduler::terminate();
}
///////////////////////////////////////////////////////////////////////////
prefix_ void senf::detail::DaemonWatcher::Forwarder::writeData(int event, Target * target)
{
- if (event != Scheduler::EV_WRITE) {
+ if (event != scheduler::FdEvent::EV_WRITE) {
// Broken pipe while writing data ? Not much, we can do here, we just drop the data
targets_.erase_and_destroy(Targets::current(*target),DestroyDelete());
if (targets_.empty() && src_ == -1)
By default, the logging library will call gettimeofday() for each log message. To change the
time source, just pass the new class or instance to senf::log::timeSource:
\code
- // Use senf::Scheduler::instance().eventTime() to time log messages
- senf::log::timeSource<senf::SchedulerLogTimeSource>();
+ // Use senf::scheduler::eventTime() to time log messages
+ senf::log::timeSource<senf::scheduler::LogTimeSource>();
\endcode
*/