module jtk.timer; import jtk.time; import std.algorithm; import core.sync.mutex; private extern(C) void jtk_wake(); class Timer { private static __gshared Timer[Timer] timers; private static __gshared Mutex timers_mutex; private ulong next; private ulong interval; void * user; this(ulong delay, ulong interval, void * user) { ulong current_time = us_time(); this.next = current_time + (delay * 1000u); this.interval = interval * 1000u; this.user = user; timers_mutex.lock_nothrow(); timers[this] = this; timers_mutex.unlock_nothrow(); /* Wake the wait loop in case this timer will expire before the * previously calculated timeout. */ jtk_wake(); } void remove() { timers_mutex.lock_nothrow(); timers.remove(this); timers_mutex.unlock_nothrow(); } package void service() { if (this.interval == 0u) { remove(); } else { this.next += this.interval; } } package static Timer get_expired_timer() { ulong current_time = us_time(); Timer expired_timer = null; timers_mutex.lock_nothrow(); foreach (Timer timer; timers) { if (timer.next <= current_time) { expired_timer = timer; break; } } timers_mutex.unlock_nothrow(); return expired_timer; } package static ulong time_to_next_timer_expiration() { ulong rv = cast(ulong)-1; ulong current_time = us_time(); timers_mutex.lock_nothrow(); foreach (Timer timer; timers) { if (timer.next <= current_time) { rv = 0u; break; } rv = min(rv, timer.next - current_time); } timers_mutex.unlock_nothrow(); return rv; } package static void timer_init() { timers_mutex = new Mutex; } }