From 0963b80234b3be7f4c7256d7ab4d126625dd7a17 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Wed, 8 Jul 2020 11:17:12 -0400 Subject: [PATCH] jtk.timer: make thread safe --- src/jtk/init.d | 4 ++++ src/jtk/timer.d | 31 +++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/jtk/init.d b/src/jtk/init.d index aca3ea5..d6de12c 100644 --- a/src/jtk/init.d +++ b/src/jtk/init.d @@ -1,5 +1,7 @@ module jtk.init; +static import jtk.timer; + private extern(C) bool jtk_init(); bool init() @@ -9,5 +11,7 @@ bool init() return false; } + jtk.timer.Timer.timer_init(); + return true; } diff --git a/src/jtk/timer.d b/src/jtk/timer.d index df053dc..1ce0ac0 100644 --- a/src/jtk/timer.d +++ b/src/jtk/timer.d @@ -2,10 +2,14 @@ module jtk.timer; import jtk.time; import std.algorithm; +import core.sync.mutex; + +private extern(C) void jtk_wake(); class Timer { - private static Timer[Timer] timers; + private static __gshared Timer[Timer] timers; + private static __gshared Mutex timers_mutex; private ulong next; @@ -19,12 +23,19 @@ class Timer 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() @@ -42,28 +53,40 @@ class Timer 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) { - return timer; + expired_timer = timer; + break; } } - return null; + 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) { - return 0u; + 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; + } }