Source: ../../libxorp/eventloop.hh
|
|
|
|
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// vim:set sts=4 ts=8:
// Copyright (c) 2001-2009 XORP, Inc.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License, Version
// 2.1, June 1999 as published by the Free Software Foundation.
// Redistribution and/or modification of this program under the terms of
// any other version of the GNU Lesser General Public License is not
// permitted.
//
// 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. For more details,
// see the GNU Lesser General Public License, Version 2.1, a copy of
// which can be found in the XORP LICENSE.lgpl file.
//
// XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
// http://xorp.net
// $XORP: xorp/libxorp/eventloop.hh,v 1.42 2009/01/05 18:30:57 jtc Exp $
#ifndef __LIBXORP_EVENTLOOP_HH__
#define __LIBXORP_EVENTLOOP_HH__
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include "xorpfd.hh"
#include "clock.hh"
#include "timer.hh"
#include "task.hh"
#include "callback.hh"
#include "ioevents.hh"
#ifdef HOST_OS_WINDOWS
#include "win_dispatcher.hh"
#else
#include "selector.hh"
#endif
/**
* @short Event Loop.
*
* Co-ordinates interactions between a TimerList and a SelectorList
* for Xorp processes. All XorpTimer and select operations should be
* co-ordinated through this interface.
*/
class EventLoop {
public:
/**
* Constructor
*/
EventLoop();
/**
* Destructor.
*/
~EventLoop();
/**
* Invoke all pending callbacks relating to XorpTimer and file
* descriptor activity. This function may block if there are no
* selectors ready. It may block forever if there are no timers
* pending. The @ref timers_pending method can be used to detect
* whether there are timers pending, while the @ref events_pending
* method can be used to detect whether there any events pending.
* An event can be either timer or task.
* The @ref descriptor_count method can be used to see if there are
* any select'able file descriptors.
*
* <pre>
EventLoop e;
...
while(e.events_pending() || e.descriptor_count() > 0) {
e.run();
}
* </pre>
*
* Non-xorp processes which use Xorp code should create a periodic
* timer to prevent the run() function from blocking indefinitely
* when there are no pending XorpTimer or SelectList objects. The
* period of the timer will depend on the application's existing
* needs.
*
* <pre>
static bool wakeup_hook(int n) {
static int count = 0;
count += n;
printf("count = %d\n", n);
return true;
}
int main() {
... // Program initialization
// Add a Xorp EventLoop
EventLoop e;
XorpTimer wakeywakey = e.new_periodic_ms(100, callback(wakeup_hook, 1));
// Program's main loop
for(;;) {
... do what program does in its main loop ...
e.run(); // process events
}
}
* </pre>
*/
void run();
void set_debug(bool v) {
_is_debug = v;
#ifndef HOST_OS_WINDOWS
_selector_list.set_debug(v);
#endif
}
bool is_debug() const { return (_is_debug); }
/**
* @return reference to the @ref TimerList used by the @ref
* EventLoop instance.
*/
TimerList& timer_list() { return _timer_list; }
#ifndef HOST_OS_WINDOWS
/**
* @return reference to the @ref SelectorList used by the @ref
* EventLoop instance.
* XXX: Deprecated.
*/
SelectorList& selector_list() { return _selector_list; }
#endif
/**
* Add a new one-off timer to the EventLoop.
*
* @param when the absolute time when the timer expires.
* @param ocb callback object that is invoked when timer expires.
* @return a @ref XorpTimer object that must be assigned to remain
* scheduled.
*/
XorpTimer new_oneoff_at(const TimeVal& when,
const OneoffTimerCallback& ocb,
int priority = XorpTask::PRIORITY_DEFAULT);
/**
* Add a new one-off timer to the EventLoop.
*
* @param wait the relative time when the timer expires.
* @param ocb callback object that is invoked when timer expires.
* @return a @ref XorpTimer object that must be assigned to remain
* scheduled.
*/
XorpTimer new_oneoff_after(const TimeVal& wait,
const OneoffTimerCallback& ocb,
int priority = XorpTask::PRIORITY_DEFAULT);
/**
* Add a new one-off timer to the EventLoop.
*
* @param ms the relative time in milliseconds when the timer expires.
* @param ocb callback object that is invoked when timer expires.
* @return a @ref XorpTimer object that must be assigned to remain
* scheduled.
*/
XorpTimer new_oneoff_after_ms(int ms, const OneoffTimerCallback& ocb,
int priority = XorpTask::PRIORITY_DEFAULT);
/**
* Add periodic timer to the EventLoop.
*
* @param wait the period when the timer expires.
* @param pcb user callback object that is invoked when timer expires.
* If the callback returns false the periodic XorpTimer is unscheduled.
* @return a @ref XorpTimer object that must be assigned to remain
* scheduled.
*/
XorpTimer new_periodic(const TimeVal& wait,
const PeriodicTimerCallback& pcb,
int priority = XorpTask::PRIORITY_DEFAULT);
/**
* Add periodic timer to the EventLoop.
*
* @param ms the period in milliseconds when the timer expires.
* @param pcb user callback object that is invoked when timer expires.
* If the callback returns false the periodic XorpTimer is unscheduled.
* @return a @ref XorpTimer object that must be assigned to remain
* scheduled.
*/
XorpTimer new_periodic_ms(int ms, const PeriodicTimerCallback& pcb,
int priority = XorpTask::PRIORITY_DEFAULT);
/**
* Add a flag setting timer to the EventLoop.
*
* @param when the absolute time when the timer expires.
* @param flag_ptr pointer to a boolean variable that is to be set
* when the timer expires.
* @param to_value value to set the boolean variable to. Default value
* is true.
* @return a @ref XorpTimer object that must be assigned to remain
* scheduled.
*/
XorpTimer set_flag_at(const TimeVal& when,
bool* flag_ptr,
bool to_value = true);
/**
* Add a flag setting timer to the EventLoop.
*
* @param wait the relative time when the timer expires.
* @param flag_ptr pointer to a boolean variable that is to be set
* when the timer expires.
* @param to_value value to set the boolean variable to. Default value
* is true.
* @return a @ref XorpTimer object that must be assigned to remain
* scheduled.
*/
XorpTimer set_flag_after(const TimeVal& wait,
bool* flag_ptr,
bool to_value = true);
/**
* Add a flag setting timer to the EventLoop.
*
* @param ms the relative time in millisecond when the timer expires.
* @param flag_ptr pointer to a boolean variable that is set to
* false when this function is called and will be set to true when
* the @ref XorpTimer expires.
* @param flag_ptr pointer to a boolean variable that is to be set
* when the timer expires.
* @param to_value value to set the boolean variable to. Default value
* is true.
* @return a @ref XorpTimer object that must be assigned to remain
* scheduled.
*/
XorpTimer set_flag_after_ms(int ms, bool* flag_ptr, bool to_value = true);
/**
* Create a custom timer associated with the EventLoop.
*
* The @ref XorpTimer object created needs to be explicitly
* scheduled with the available @ref XorpTimer methods.
*
* @param cb user callback object that is invoked when timer expires.
* @return a @ref XorpTimer object that must be assigned to remain
* scheduled.
*/
XorpTimer new_timer(const BasicTimerCallback& cb);
/**
* Create a new one-time task to be scheduled with the timers and
* file handlers.
*
* @param cb callback object that is invoked when task is run.
* @param priority the scheduling priority for the task.
* @param scheduler_class the scheduling class within the priority level.
* @return a @ref XorpTask object that must be assigned to remain
* scheduled.
*/
XorpTask new_oneoff_task(const OneoffTaskCallback& cb,
int priority = XorpTask::PRIORITY_DEFAULT,
int weight = XorpTask::WEIGHT_DEFAULT);
/**
* Create a new repeated task to be scheduled with the timers and file
* handlers.
*
* @param cb callback object that is invoked when task is run.
* If the callback returns true, the task will continue to run,
* otherwise it will be unscheduled.
* @param priority the scheduling priority for the task.
* @param scheduler_class the scheduling class within the priority level.
* @return a @ref XorpTask object that must be assigned to remain
* scheduled.
*/
XorpTask new_task(const RepeatedTaskCallback& cb,
int priority = XorpTask::PRIORITY_DEFAULT,
int weight = XorpTask::WEIGHT_DEFAULT);
/**
* Add a file descriptor and callback to be invoked when
* descriptor is ready for input or output. An IoEventType
* determines what type of I/O event will cause the callback to be
* invoked.
*
* Only one callback may be associated with each event
* type, e.g. one callback for read pending, one callback for
* write pending.
*
* If multiple event types in are associated with the same
* callback, the callback is only invoked once, but the mask
* argument passed to the callback shows multiple event types.
*
* @param fd the file descriptor.
* @param type the @ref IoEventType of the event.
* @param cb object to be invoked when file descriptor has I/O
* pending.
* @return true on success, false if any error occurred.
*/
bool add_ioevent_cb(XorpFd fd, IoEventType type, const IoEventCb& cb,
int priority = XorpTask::PRIORITY_DEFAULT);
/**
* Remove callbacks associated with file descriptor.
*
* @param fd the file descriptor.
* @param type the event type to clear.
* The special value IOT_ANY means clear any kind of callback.
* @return true on success, false if any error occurred.
*/
bool remove_ioevent_cb(XorpFd fd, IoEventType type = IOT_ANY);
/**
* @return true if any XorpTimers are present on EventLoop's TimerList.
*/
bool timers_pending() const;
/**
* @return true if any XorpTimers are present on EventLoop's
* TimerList or any XorpTasks are present on the TaskList.
*/
bool events_pending() const;
/**
* @return the number of XorpTimers present on EventLoop's TimerList.
*/
size_t timer_list_length() const;
/**
* Get current time according to EventLoop's TimerList
*/
void current_time(TimeVal& now) const;
/**
* Get the count of the descriptors that have been added.
*
* @return the count of the descriptors that have been added.
*/
size_t descriptor_count() const;
void set_aggressiveness(int num);
private:
EventLoop(const EventLoop&); // not implemented
EventLoop& operator=(const EventLoop&); // not implemented
bool do_work(bool can_block);
private:
ClockBase* _clock;
TimerList _timer_list;
TaskList _task_list;
int _aggressiveness;
time_t _last_ev_run; // 0 - Means run not called yet.
time_t _last_warned;
bool _is_debug; // If true, debug enabled
// Was the last event at this priority a selector or a task.
bool _last_ev_type[XorpTask::PRIORITY_INFINITY];
#ifdef HOST_OS_WINDOWS
WinDispatcher _win_dispatcher;
#else
SelectorList _selector_list;
#endif
};
// ----------------------------------------------------------------------------
// Deferred definitions
inline XorpTimer
EventLoop::new_timer(const BasicTimerCallback& cb)
{
return _timer_list.new_timer(cb);
}
inline XorpTimer
EventLoop::new_oneoff_at(const TimeVal& tv, const OneoffTimerCallback& ocb,
int priority)
{
return _timer_list.new_oneoff_at(tv, ocb, priority);
}
inline XorpTimer
EventLoop::new_oneoff_after(const TimeVal& wait,
const OneoffTimerCallback& ocb,
int priority)
{
return _timer_list.new_oneoff_after(wait, ocb, priority);
}
inline XorpTimer
EventLoop::new_oneoff_after_ms(int ms, const OneoffTimerCallback& ocb,
int priority)
{
TimeVal wait(ms / 1000, (ms % 1000) * 1000);
return _timer_list.new_oneoff_after(wait, ocb, priority);
}
inline XorpTimer
EventLoop::new_periodic(const TimeVal& wait, const PeriodicTimerCallback& pcb,
int priority)
{
return _timer_list.new_periodic(wait, pcb, priority);
}
inline XorpTimer
EventLoop::new_periodic_ms(int ms, const PeriodicTimerCallback& pcb,
int priority)
{
TimeVal wait(ms / 1000, (ms % 1000) * 1000);
return _timer_list.new_periodic(wait, pcb, priority);
}
inline XorpTimer
EventLoop::set_flag_at(const TimeVal& tv, bool *flag_ptr, bool to_value)
{
return _timer_list.set_flag_at(tv, flag_ptr, to_value);
}
inline XorpTimer
EventLoop::set_flag_after(const TimeVal& wait, bool *flag_ptr, bool to_value)
{
return _timer_list.set_flag_after(wait, flag_ptr, to_value);
}
inline XorpTimer
EventLoop::set_flag_after_ms(int ms, bool *flag_ptr, bool to_value)
{
TimeVal wait(ms / 1000, (ms % 1000) * 1000);
return _timer_list.set_flag_after(wait, flag_ptr, to_value);
}
inline bool
EventLoop::timers_pending() const
{
return !_timer_list.empty();
}
inline bool
EventLoop::events_pending() const
{
return ((!_timer_list.empty()) || (!_task_list.empty()));
}
inline size_t
EventLoop::timer_list_length() const
{
return _timer_list.size();
}
inline void
EventLoop::current_time(TimeVal& t) const
{
_timer_list.current_time(t);
}
#endif // __LIBXORP_EVENTLOOP_HH__
Generated by: pavlin on kobe.xorp.net on Wed Jan 7 19:10:36 2009, using kdoc 2.0a54+XORP.