1 /+ 2 Threaded sleep 3 +/ 4 module sily.async.timer; 5 6 import std.concurrency; 7 import core.thread; 8 9 /** 10 Executes delegate on timeout or interval 11 12 Params: 13 func = Delegate function to execute 14 timespan = Time in milliseconds 15 16 Example: 17 --- 18 // Using normal functions 19 void func() { writeln("Timer end"); } 20 import std.functional: toDelegate; 21 setTimeout(toDelegate(&func), 6000); 22 23 // Using inline delegates 24 setTimeout(delegate void() { writeln("Timer end"); }, 6000); 25 26 // Interval 27 setInterval(delegate void() { writeln("Timer tick"); }, 10); 28 29 // Stop timer 30 // After stopping timer it cannot be restarted 31 AsyncTimer timer = setInterval(delegate void() { writeln("Timer tick"); }, 10); 32 timer.stop(); 33 34 // Adjusting timer values 35 // Will be adjusted on next cycle (aka after 10 msec) 36 timer = setInterval(delegate void() { writeln("Timer tick"); }, 10); 37 timer.timespan = 50; 38 timer.interval = false; // will prevent timer from running next cycle 39 --- 40 */ 41 AsyncTimer setTimeout(void delegate() func, int timespan) { 42 return setAsyncTimer(func, AsyncTimer(timespan, false, new AsyncTimerValues())); 43 } 44 45 /// Ditto 46 AsyncTimer setInterval(void delegate() func, int timespan) { 47 return setAsyncTimer(func, AsyncTimer(timespan, true, new AsyncTimerValues())); 48 } 49 50 private AsyncTimer setAsyncTimer(void delegate() func, AsyncTimer timer) { 51 timer.start(); 52 spawn( 53 cast(shared) (&timeoutCallback), 54 cast(shared) func, 55 cast(shared) (timer.intervalptr()), 56 cast(shared) (timer.timespanptr()), 57 cast(shared) (timer.enabledptr()) 58 ); 59 return timer; 60 } 61 62 private static void timeoutCallback(shared void delegate() func, 63 shared bool* interval, 64 shared int* timespan, 65 shared bool* enabled) { 66 do { 67 Thread.sleep((*timespan).msecs); 68 if (*enabled) func(); 69 } while ((*enabled) && (*interval)); 70 (*(cast(bool*) enabled)) = false; 71 } 72 73 private static struct AsyncTimerValues { 74 private bool _enabled = false; 75 76 private int _timespan = 0; 77 78 private bool _isInterval = false; 79 } 80 81 /// Timer struct used by setTimeout and setInverval. Does not contains timer functionality itself. 82 static struct AsyncTimer { 83 private AsyncTimerValues* _timer; 84 85 @property int timespan() { return (*_timer)._timespan; } 86 @property void timespan(int p_timespan) { (*_timer)._timespan = p_timespan; } 87 88 @property bool interval() { return (*_timer)._isInterval; } 89 @property void interval(bool p_isInterval) { (*_timer)._isInterval = p_isInterval; } 90 91 @property bool enabled() { return (*_timer)._enabled; } 92 93 @property private bool* enabledptr() { return &((*_timer)._enabled); } 94 @property private int* timespanptr() { return &((*_timer)._timespan); } 95 @property private bool* intervalptr() { return &((*_timer)._isInterval); } 96 97 private this(int p_timespan, bool p_interval, AsyncTimerValues* timer) { 98 _timer = timer; 99 timespan = p_timespan; 100 interval = p_interval; 101 } 102 103 /// Stops timer (timeout and interval execution) 104 void stop() { 105 (*_timer)._enabled = false; 106 } 107 108 /// Will do nothing, used by timeout and interval 109 void start() { 110 (*_timer)._enabled = true; 111 } 112 113 /// Will sleep until timer is finished (not recommended with interval) 114 void await() { 115 while ((*_timer)._enabled) { 116 Thread.sleep(500.usecs); 117 } 118 } 119 } 120 121