jtk.timer: make thread safe

This commit is contained in:
Josh Holtrop 2020-07-08 11:17:12 -04:00
parent 3f326a46f0
commit 0963b80234
2 changed files with 31 additions and 4 deletions

View File

@ -1,5 +1,7 @@
module jtk.init; module jtk.init;
static import jtk.timer;
private extern(C) bool jtk_init(); private extern(C) bool jtk_init();
bool init() bool init()
@ -9,5 +11,7 @@ bool init()
return false; return false;
} }
jtk.timer.Timer.timer_init();
return true; return true;
} }

View File

@ -2,10 +2,14 @@ module jtk.timer;
import jtk.time; import jtk.time;
import std.algorithm; import std.algorithm;
import core.sync.mutex;
private extern(C) void jtk_wake();
class Timer class Timer
{ {
private static Timer[Timer] timers; private static __gshared Timer[Timer] timers;
private static __gshared Mutex timers_mutex;
private ulong next; private ulong next;
@ -19,12 +23,19 @@ class Timer
this.next = current_time + (delay * 1000u); this.next = current_time + (delay * 1000u);
this.interval = interval * 1000u; this.interval = interval * 1000u;
this.user = user; this.user = user;
timers_mutex.lock_nothrow();
timers[this] = this; 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() void remove()
{ {
timers_mutex.lock_nothrow();
timers.remove(this); timers.remove(this);
timers_mutex.unlock_nothrow();
} }
package void service() package void service()
@ -42,28 +53,40 @@ class Timer
package static Timer get_expired_timer() package static Timer get_expired_timer()
{ {
ulong current_time = us_time(); ulong current_time = us_time();
Timer expired_timer = null;
timers_mutex.lock_nothrow();
foreach (Timer timer; timers) foreach (Timer timer; timers)
{ {
if (timer.next <= current_time) if (timer.next <= current_time)
{ {
return timer; expired_timer = timer;
break;
} }
} }
return null; timers_mutex.unlock_nothrow();
return expired_timer;
} }
package static ulong time_to_next_timer_expiration() package static ulong time_to_next_timer_expiration()
{ {
ulong rv = cast(ulong)-1; ulong rv = cast(ulong)-1;
ulong current_time = us_time(); ulong current_time = us_time();
timers_mutex.lock_nothrow();
foreach (Timer timer; timers) foreach (Timer timer; timers)
{ {
if (timer.next <= current_time) if (timer.next <= current_time)
{ {
return 0u; rv = 0u;
break;
} }
rv = min(rv, timer.next - current_time); rv = min(rv, timer.next - current_time);
} }
timers_mutex.unlock_nothrow();
return rv; return rv;
} }
package static void timer_init()
{
timers_mutex = new Mutex;
}
} }