Use MonoTime for timers.

This commit is contained in:
Sönke Ludwig 2020-03-15 21:29:27 +01:00
parent e8f35c0e0f
commit 215735f48f
3 changed files with 25 additions and 27 deletions

View file

@ -19,6 +19,7 @@ import eventcore.drivers.threadedfile;
import eventcore.internal.consumablequeue : ConsumableQueue; import eventcore.internal.consumablequeue : ConsumableQueue;
import eventcore.internal.utils; import eventcore.internal.utils;
import core.time : MonoTime;
import std.algorithm.comparison : among, min, max; import std.algorithm.comparison : among, min, max;
version (Posix) { version (Posix) {
@ -221,17 +222,17 @@ final class PosixEventDriverCore(Loop : PosixEventLoop, Timers : EventDriverTime
if (timeout <= 0.seconds) { if (timeout <= 0.seconds) {
got_events = m_loop.doProcessEvents(0.seconds); got_events = m_loop.doProcessEvents(0.seconds);
m_timers.process(currStdTime); m_timers.process(MonoTime.currTime);
} else { } else {
long now = currStdTime; auto now = MonoTime.currTime;
do { do {
auto nextto = max(min(m_timers.getNextTimeout(now), timeout), 0.seconds); auto nextto = max(min(m_timers.getNextTimeout(now), timeout), 0.seconds);
got_events = m_loop.doProcessEvents(nextto); got_events = m_loop.doProcessEvents(nextto);
long prev_step = now; auto prev_step = now;
now = currStdTime; now = MonoTime.currTime;
got_events |= m_timers.process(now); got_events |= m_timers.process(now);
if (timeout != Duration.max) if (timeout != Duration.max)
timeout -= (now - prev_step).hnsecs; timeout -= now - prev_step;
} while (timeout > 0.seconds && !m_exit && !got_events); } while (timeout > 0.seconds && !m_exit && !got_events);
} }

View file

@ -7,7 +7,7 @@ import eventcore.driver;
import eventcore.internal.consumablequeue; import eventcore.internal.consumablequeue;
import eventcore.internal.dlist; import eventcore.internal.dlist;
import eventcore.internal.utils : mallocT, freeT, nogc_assert; import eventcore.internal.utils : mallocT, freeT, nogc_assert;
import core.time : Duration, MonoTime, hnsecs;
final class LoopTimeoutTimerDriver : EventDriverTimers { final class LoopTimeoutTimerDriver : EventDriverTimers {
import std.experimental.allocator.building_blocks.free_list; import std.experimental.allocator.building_blocks.free_list;
@ -17,7 +17,6 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
import std.container.array; import std.container.array;
import std.datetime : Clock; import std.datetime : Clock;
import std.range : SortedRange, assumeSorted, take; import std.range : SortedRange, assumeSorted, take;
import core.time : hnsecs, Duration;
import core.memory : GC; import core.memory : GC;
private { private {
@ -46,24 +45,22 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
package @property size_t pendingCount() const @safe nothrow { return m_timerQueue.length; } package @property size_t pendingCount() const @safe nothrow { return m_timerQueue.length; }
final package Duration getNextTimeout(long stdtime) final package Duration getNextTimeout(MonoTime time)
@safe nothrow { @safe nothrow {
if (m_timerQueue.empty) return Duration.max; if (m_timerQueue.empty) return Duration.max;
return (m_timerQueue.front.timeout - stdtime).hnsecs; return m_timerQueue.front.timeout - time;
} }
final package bool process(long stdtime) final package bool process(MonoTime time)
@trusted nothrow { @trusted nothrow {
assert(m_firedTimers.length == 0); assert(m_firedTimers.length == 0);
if (m_timerQueue.empty) return false; if (m_timerQueue.empty) return false;
TimerSlot ts = void;
ts.timeout = stdtime+1;
foreach (tm; m_timerQueue[]) { foreach (tm; m_timerQueue[]) {
if (tm.timeout > stdtime) break; if (tm.timeout > time) break;
if (tm.repeatDuration > 0) { if (tm.repeatDuration > Duration.zero) {
do tm.timeout += tm.repeatDuration; do tm.timeout += tm.repeatDuration;
while (tm.timeout <= stdtime); while (tm.timeout <= time);
} else tm.pending = false; } else tm.pending = false;
m_firedTimers.put(tm); m_firedTimers.put(tm);
} }
@ -72,7 +69,7 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
foreach (tm; processed_timers) { foreach (tm; processed_timers) {
m_timerQueue.remove(tm); m_timerQueue.remove(tm);
if (tm.repeatDuration > 0) if (tm.repeatDuration > Duration.zero)
enqueueTimer(tm); enqueueTimer(tm);
} }
@ -98,7 +95,7 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
GC.addRange(tm, TimerSlot.sizeof, typeid(TimerSlot)); GC.addRange(tm, TimerSlot.sizeof, typeid(TimerSlot));
tm.id = id; tm.id = id;
tm.refCount = 1; tm.refCount = 1;
tm.timeout = long.max; tm.timeout = MonoTime.max;
m_timers[id] = tm; m_timers[id] = tm;
return id; return id;
} }
@ -108,8 +105,8 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
scope (failure) assert(false); scope (failure) assert(false);
auto tm = m_timers[timer]; auto tm = m_timers[timer];
if (tm.pending) stop(timer); if (tm.pending) stop(timer);
tm.timeout = Clock.currStdTime + timeout.total!"hnsecs"; tm.timeout = MonoTime.currTime + timeout;
tm.repeatDuration = repeat.total!"hnsecs"; tm.repeatDuration = repeat;
tm.pending = true; tm.pending = true;
enqueueTimer(tm); enqueueTimer(tm);
} }
@ -137,7 +134,7 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
final override bool isPeriodic(TimerID descriptor) final override bool isPeriodic(TimerID descriptor)
{ {
return m_timers[descriptor].repeatDuration > 0; return m_timers[descriptor].repeatDuration > Duration.zero;
} }
final override void wait(TimerID timer, TimerCallback2 callback) final override void wait(TimerID timer, TimerCallback2 callback)
@ -239,8 +236,8 @@ struct TimerSlot {
TimerID id; TimerID id;
uint refCount; uint refCount;
bool pending; bool pending;
long timeout; // stdtime MonoTime timeout;
long repeatDuration; Duration repeatDuration;
TimerCallback2 callback; // TODO: use a list with small-value optimization TimerCallback2 callback; // TODO: use a list with small-value optimization
DataInitializer userDataDestructor; DataInitializer userDataDestructor;

View file

@ -96,7 +96,7 @@ final class WinAPIEventDriverCore : EventDriverCore {
override ExitReason processEvents(Duration timeout = Duration.max) override ExitReason processEvents(Duration timeout = Duration.max)
{ {
import std.algorithm : min; import std.algorithm : min;
import core.time : hnsecs, seconds; import core.time : MonoTime, seconds;
if (m_exit) { if (m_exit) {
m_exit = false; m_exit = false;
@ -106,12 +106,12 @@ final class WinAPIEventDriverCore : EventDriverCore {
if (!waiterCount) return ExitReason.outOfWaiters; if (!waiterCount) return ExitReason.outOfWaiters;
bool got_event; bool got_event;
long now = currStdTime; auto now = MonoTime.currTime;
do { do {
auto nextto = min(m_timers.getNextTimeout(now), timeout); auto nextto = min(m_timers.getNextTimeout(now), timeout);
got_event |= doProcessEvents(nextto); got_event |= doProcessEvents(nextto);
long prev_step = now; auto prev_step = now;
now = currStdTime; now = MonoTime.currTime;
got_event |= m_timers.process(now); got_event |= m_timers.process(now);
if (m_exit) { if (m_exit) {
@ -119,7 +119,7 @@ final class WinAPIEventDriverCore : EventDriverCore {
return ExitReason.exited; return ExitReason.exited;
} else if (got_event) break; } else if (got_event) break;
if (timeout != Duration.max) if (timeout != Duration.max)
timeout -= (now - prev_step).hnsecs; timeout -= now - prev_step;
} while (timeout > 0.seconds); } while (timeout > 0.seconds);
if (!waiterCount) return ExitReason.outOfWaiters; if (!waiterCount) return ExitReason.outOfWaiters;