jes/src/jtk/timer.d

93 lines
2.0 KiB
D

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;
}
}