#ifndef _H_TQUEUE
#define _H_TQUEUE
#include <security_utilities/utilities.h>
#include <security_utilities/debugging.h>
namespace Security {
template <class Time>
class ScheduleQueue {
public:
ScheduleQueue() { first.fwd = first.back = &first; }
virtual ~ScheduleQueue() { }
public:
class Event {
friend class ScheduleQueue;
public:
Event() : mScheduled(false) { }
~Event() { if (scheduled()) unschedule(); }
void unschedule();
Time when() const { return fireTime; }
bool scheduled() const { return mScheduled; }
private:
Time fireTime; bool mScheduled; Event *back, *fwd;
void putBefore(Event *ev)
{ back = ev->back; fwd = ev; ev->back = back->fwd = this; mScheduled = true; }
};
public:
void schedule(Event *event, Time when);
void unschedule(Event *event)
{ event->unschedule(); }
bool empty() const { return first.fwd == &first; }
Time next() const { assert(!empty()); return first.fwd->fireTime; }
Event *pop(Time now);
private:
Event first; };
template <class Time>
void ScheduleQueue<Time>::Event::unschedule()
{
assert(mScheduled);
back->fwd = fwd; fwd->back = back;
mScheduled = false;
secdebug("schedq", "event %p unscheduled", this);
}
template <class Time>
inline void ScheduleQueue<Time>::schedule(Event *event, Time when)
{
Event *ev = first.fwd;
if (event->scheduled()) {
if (when == event->fireTime) { secdebug("schedq", "%p (%.3f) no change", event, double(when));
return;
}
else if (when > event->fireTime && event != first.fwd) ev = event->back;
event->unschedule();
}
event->fireTime = when;
for (; ev != &first; ev = ev->fwd) {
if (ev->fireTime > when) {
event->putBefore(ev);
secdebug("schedq", "%p (%.3f) scheduled before %p", event, double(when), ev);
return;
}
}
event->putBefore(&first);
secdebug("schedq", "%p (%.3f) scheduled last", event, double(when));
}
template <class Time>
inline typename ScheduleQueue<Time>::Event *ScheduleQueue<Time>::pop(Time now)
{
if (!empty()) {
Event *top = first.fwd;
if (top->fireTime <= now) {
top->unschedule();
secdebug("schedq", "event %p delivered at %.3f", top, double(now));
return top;
}
}
return NULL;
}
}
#endif // _H_TQUEUE