Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Pancake2/PancakeScheduler.c
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
136 lines (106 sloc)
2.84 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "PancakeScheduler.h" | |
static PancakeSchedulerEvent *events = NULL; /* waiting events */ | |
static PancakeSchedulerEvent *unusedEvents = NULL; /* cached event instances */ | |
PANCAKE_API PancakeSchedulerEvent *PancakeSchedule(UNative time, PancakeSchedulerEventCallback callback, void *arg) { | |
PancakeSchedulerEvent *event; | |
if(unusedEvents) { | |
// Use cached event instance | |
event = unusedEvents; | |
CDL_DELETE(unusedEvents, unusedEvents); | |
} else { | |
// Allocate new event | |
event = PancakeAllocate(sizeof(PancakeSchedulerEvent)); | |
} | |
event->time = time; | |
event->callback = callback; | |
event->arg = arg; | |
if(events) { | |
if(events->prev->time <= time) { | |
CDL_PREPEND_ELEM(events, events, event); | |
events = event->next; | |
} else if(events->time >= time) { | |
CDL_PREPEND(events, event); | |
} else { | |
PancakeSchedulerEvent *ev; | |
// Iterate through events and find place for new event | |
CDL_FOREACH(events, ev) { | |
if(ev->time == time) { | |
CDL_PREPEND_ELEM(events, ev->next, event); | |
break; | |
} else if(ev->time < time && ev->next->time >= time) { | |
CDL_PREPEND_ELEM(events, ev->next, event); | |
break; | |
} | |
} | |
} | |
} else { | |
CDL_PREPEND(events, event); | |
} | |
PancakeDebug { | |
// Check for event order corruption | |
PancakeSchedulerEvent *ev; | |
UByte haveScheduledEvent = 0; | |
CDL_FOREACH(events, ev) { | |
if(ev->next != events) { | |
PancakeAssert(ev->time <= ev->next->time); | |
} | |
if(ev == event) { | |
haveScheduledEvent++; | |
} | |
} | |
PancakeAssert(haveScheduledEvent == 1); | |
} | |
return event; | |
} | |
PANCAKE_API extern inline void PancakeUnschedule(PancakeSchedulerEvent *event) { | |
CDL_DELETE(events, event); | |
CDL_PREPEND(unusedEvents, event); | |
} | |
PANCAKE_API extern inline UNative PancakeSchedulerGetNextExecutionTime() { | |
if(!events) { | |
return time(NULL) + 86400; | |
} | |
return events->time < time(NULL) ? time(NULL) : events->time; | |
} | |
PANCAKE_API extern inline UNative PancakeSchedulerGetNextExecutionTimeOffset() { | |
UNative now; | |
if(!events) { | |
return 86400; | |
} | |
now = time(NULL); | |
return events->time < now ? 0 : events->time - now; | |
} | |
PANCAKE_API extern inline UNative PancakeSchedulerGetNextScheduledTime() { | |
if(!events) { | |
return 0; | |
} | |
return events->time; | |
} | |
PANCAKE_API void PancakeSchedulerRun() { | |
PancakeSchedulerEvent *ev, *tmp, *tmp2; | |
UNative now = time(NULL); | |
CDL_FOREACH_SAFE(events, ev, tmp, tmp2) { | |
if(ev->time > now) { | |
break; | |
} | |
// Run event | |
ev->callback(ev->arg); | |
// Cache event instance | |
CDL_DELETE(events, ev); | |
CDL_PREPEND(unusedEvents, ev); | |
} | |
} | |
void PancakeSchedulerShutdown() { | |
PancakeSchedulerEvent *ev, *tmp, *tmp2; | |
CDL_FOREACH_SAFE(events, ev, tmp, tmp2) { | |
// Run all events, no matter when they are scheduled | |
ev->callback(ev->arg); | |
CDL_DELETE(events, ev); | |
PancakeFree(ev); | |
} | |
// Free cached events | |
CDL_FOREACH_SAFE(unusedEvents, ev, tmp, tmp2) { | |
CDL_DELETE(unusedEvents, ev); | |
PancakeFree(ev); | |
} | |
} |