Mercurial > projects > mde
view mde/scheduler.d @ 4:9a990644948c
Many changes: upgraded to tango 0.99.4, reorganised mde/input, large changes to mde/mergetag and mde/init, separated off test/MTTest.d and more.
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Sun, 06 Jan 2008 17:38:51 +0000 |
parents | |
children | 0047b364b6d9 |
line wrap: on
line source
/** Scheduler */ module mde.scheduler; import tango.time.Time; // NOTE: Currently has no support for removing functions. To fix, assign ID and store fct pointers // in an associative array, returning the ID [on adding fct pointer]. // FIXME: support delegates or not? /// This class can run scheduled functions per frame or every t seconds (sim-time). class Scheduler { /** The type of function pointer to be passed to the scheduler. * * The double $(I time) parameter gives the number of (sim) seconds since the function was last * called, or zero on the first run. */ alias void function (double time) scheduleFct; /** Add a function to be called per frame. */ static void perFrame (scheduleFct fct) { frameFcts ~= fct; } /** Add a function to be called per t secs or n 100-nano-sec intevals. * * Since the scheduler cannot guarantee a maximum time between calls, the interval at which * functions are called is always greater than or equal to the inverval specified here. Of * course, the actual inteval is given when the function is run. */ static void perTime (double t, scheduleFct fct) { perTime (TimeSpan.interval(t), fct); } /** ditto */ static void perTime (TimeSpan n, scheduleFct fct) in { assert (n > TimeSpan (0L)); } body { timeFcts ~= TimeFct (fct, n); } /** This function should get called by the main loop, once per frame. * * The parameter time should be the current sim-time, using the tango.core.Types.Time enum; all * time evaluations will use this. */ static void run (Time time) { double interval; // Call all per-frame functions: if (lastTime == Time (0L)) interval = 0.0; // 0 interval for first loop else interval = (time-lastTime).interval(); foreach (fct; frameFcts) fct(interval); // Call all per-interval functions: foreach (fct; timeFcts) if (time >= fct.nextCall) { if (fct.nextCall == Time (0L)) interval = 0.0; // 0 interval for first call else interval = (time - (fct.nextCall - fct.interval)).interval(); fct.nextCall = time + fct.interval; // when to call next fct.fct (interval); // call } } /* Holds details for functions called per time interval. */ private struct TimeFct { scheduleFct fct; // function to call TimeSpan interval; // interval to call at // Storing nextCall is more efficient than storing lastCall since only this number has to // be compared to time every frame where fct is not called: Time nextCall = Time (0L); static TimeFct opCall (scheduleFct f, TimeSpan t) { // static CTOR TimeFct ret; ret.fct = f; ret.interval = t; return ret; } } private static Time lastTime = Time (0L); private static scheduleFct[] frameFcts; private static TimeFct[] timeFcts; }