Avoid GC allocations for LoopTimeoutTimerDriver.m_firedTimers.

This commit is contained in:
Sönke Ludwig 2018-10-22 21:18:37 +02:00
parent 4a605640bc
commit d66f257179

View file

@ -4,8 +4,9 @@
module eventcore.drivers.timer; module eventcore.drivers.timer;
import eventcore.driver; import eventcore.driver;
import eventcore.internal.consumablequeue;
import eventcore.internal.dlist; import eventcore.internal.dlist;
import eventcore.internal.utils : nogc_assert; import eventcore.internal.utils : mallocT, freeT, nogc_assert;
final class LoopTimeoutTimerDriver : EventDriverTimers { final class LoopTimeoutTimerDriver : EventDriverTimers {
@ -24,7 +25,7 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
TimerSlot*[TimerID] m_timers; TimerSlot*[TimerID] m_timers;
StackDList!TimerSlot m_timerQueue; StackDList!TimerSlot m_timerQueue;
TimerID m_lastTimerID; TimerID m_lastTimerID;
TimerSlot*[] m_firedTimers; ConsumableQueue!(TimerSlot*) m_firedTimers;
} }
static this() static this()
@ -32,6 +33,17 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
ms_allocator.parent = Mallocator.instance; ms_allocator.parent = Mallocator.instance;
} }
this()
@nogc @safe nothrow {
m_firedTimers = mallocT!(ConsumableQueue!(TimerSlot*));
}
~this()
@nogc @trusted nothrow {
try freeT(m_firedTimers);
catch (Exception e) assert(false, e.msg);
}
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(long stdtime)
@ -53,27 +65,24 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
do tm.timeout += tm.repeatDuration; do tm.timeout += tm.repeatDuration;
while (tm.timeout <= stdtime); while (tm.timeout <= stdtime);
} else tm.pending = false; } else tm.pending = false;
m_firedTimers ~= tm; m_firedTimers.put(tm);
} }
foreach (tm; m_firedTimers) { auto processed_timers = m_firedTimers.consume();
foreach (tm; processed_timers) {
m_timerQueue.remove(tm); m_timerQueue.remove(tm);
if (tm.repeatDuration > 0) if (tm.repeatDuration > 0)
enqueueTimer(tm); enqueueTimer(tm);
} }
foreach (tm; m_firedTimers) { foreach (tm; processed_timers) {
auto cb = tm.callback; auto cb = tm.callback;
tm.callback = null; tm.callback = null;
if (cb) cb(tm.id); if (cb) cb(tm.id);
} }
bool any_fired = m_firedTimers.length > 0; return processed_timers.length > 0;
m_firedTimers.length = 0;
m_firedTimers.assumeSafeAppend();
return any_fired;
} }
final override TimerID create() final override TimerID create()