/** * @file Sched.cc * * Imlpementation of event scheduler * * Author: Peter Helfer * Date: 2016-11-03 */ #include <string> #include "Sched.hh" namespace Sched { enum EventDataType { NONE, UINT, DBLE, VOID_PTR }; struct EventData { union { uint u; double d; void *v; }; EventData() {} EventData(uint u) : u(u) {} EventData(double d) : d(d) {} EventData(void *v) : v(v) {} }; union Callback { NoneCallback n; UintCallback u; DbleCallback d; VoidPtrCallback v; }; /** * A scheduled event */ struct Event { double time; EventDataType type; Callback cb; EventData data; Event *next; Event( double time, EventDataType type, Callback cb, EventData data) : time(time), type(type), cb(cb), data(data), next(NULL) {} }; /** * List of scheduled events. */ static Event *nextEvent = NULL; /** * Schedule an event * @param time Time for which event will be scheduled * @param cb Callback function * @param data Event Data */ void scheduleEvent( double time, EventDataType type, Callback cb, EventData data) { Event *newEv = new Event(time, type, cb, data); // Find event after which to insert new event // Event **p = &nextEvent; while ((*p != NULL) && ((*p)->time <= time)) { p = &((*p)->next); } newEv->next = *p; *p = newEv; } void scheduleEvent( double time, NoneCallback ncb) { Callback cb; cb.n = ncb; scheduleEvent(time, NONE, cb, EventData()); } void scheduleEvent( double time, UintCallback ucb, uint data) { Callback cb; cb.u = ucb; EventData d; d.u = data; scheduleEvent(time, UINT, cb, d); } void scheduleEvent( double time, DbleCallback dcb, double data) { Callback cb; cb.d = dcb; EventData d; d.d = data; scheduleEvent(time, DBLE, cb, d); } void scheduleEvent( double time, VoidPtrCallback vcb, void *data) { Callback cb; cb.v = vcb; EventData d; d.v = data; scheduleEvent(time, VOID_PTR, cb, d); } /** * Clear all scheduled events */ void clearEvents() { for (Event *ev = nextEvent; ev != NULL; ev = ev->next) { delete ev; } nextEvent = NULL; } /** * Process a scheduled event. */ static void processEvent(Event *event, double now) { switch(event->type) { case NONE: event->cb.n(event->time, now); break; case UINT: event->cb.u(event->time, now, event->data.u); break; case DBLE: event->cb.d(event->time, now, event->data.d); break; case VOID_PTR: event->cb.v(event->time, now, event->data.v); break; default: abort(); } } /** * Process all events scheduled at or before the specified time */ void processEvents(double now) { while (nextEvent != NULL && nextEvent->time <= now) { Event *ev = nextEvent; processEvent(ev, now); nextEvent = ev->next; delete ev; } } }