#ifndef _H_TQUEUE
#define _H_TQUEUE
#include <Security/utilities.h>
#include <Security/cssmalloc.h>
#include <Security/debugging.h>
#ifdef _CPP_CDSA_UTILITIES_TQUEUE
#pragma export on
#endif
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;
debug("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) return;
else if (when > event->fireTime) ev = event->back;
event->unschedule();
}
event->fireTime = when;
for (; ev != &first; ev = ev->fwd)
if (ev->fireTime > when) {
event->putBefore(ev);
return;
}
event->putBefore(&first);
debug("schedq", "event %p set for %.3f", 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();
debug("schedq", "event %p delivered at %.3f", top, double(now));
return top;
}
}
return NULL;
}
}
#ifdef _CPP_CDSA_UTILITIES_TQUEUE
#pragma export off
#endif
#endif // _H_TQUEUE