Keep timers with active waits referenced.
Avoids calling the wait callback with reference count zero. In case of a non-pending timer, the wait will be canceled if the wait reference is the last one to avoid keeping starved timers.
This commit is contained in:
parent
9b75a3b7d9
commit
b33f710420
|
@ -79,7 +79,10 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
|
||||||
foreach (tm; processed_timers) {
|
foreach (tm; processed_timers) {
|
||||||
auto cb = tm.callback;
|
auto cb = tm.callback;
|
||||||
tm.callback = null;
|
tm.callback = null;
|
||||||
if (cb) cb(tm.id, true);
|
if (cb) {
|
||||||
|
cb(tm.id, true);
|
||||||
|
releaseRef(tm.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return processed_timers.length > 0;
|
return processed_timers.length > 0;
|
||||||
|
@ -119,7 +122,10 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
|
||||||
if (!tm.pending) return;
|
if (!tm.pending) return;
|
||||||
TimerCallback2 cb;
|
TimerCallback2 cb;
|
||||||
swap(cb, tm.callback);
|
swap(cb, tm.callback);
|
||||||
if (cb) cb(timer, false);
|
if (cb) {
|
||||||
|
cb(timer, false);
|
||||||
|
releaseRef(timer);
|
||||||
|
}
|
||||||
tm.pending = false;
|
tm.pending = false;
|
||||||
m_timerQueue.remove(tm);
|
m_timerQueue.remove(tm);
|
||||||
}
|
}
|
||||||
|
@ -138,6 +144,7 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
|
||||||
{
|
{
|
||||||
assert(!m_timers[timer].callback, "Calling wait() on a timer that is already waiting.");
|
assert(!m_timers[timer].callback, "Calling wait() on a timer that is already waiting.");
|
||||||
m_timers[timer].callback = callback;
|
m_timers[timer].callback = callback;
|
||||||
|
addRef(timer);
|
||||||
}
|
}
|
||||||
alias wait = EventDriverTimers.wait;
|
alias wait = EventDriverTimers.wait;
|
||||||
|
|
||||||
|
@ -146,6 +153,7 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
|
||||||
auto pt = m_timers[timer];
|
auto pt = m_timers[timer];
|
||||||
assert(pt.callback);
|
assert(pt.callback);
|
||||||
pt.callback = null;
|
pt.callback = null;
|
||||||
|
releaseRef(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
final override void addRef(TimerID descriptor)
|
final override void addRef(TimerID descriptor)
|
||||||
|
@ -164,7 +172,20 @@ final class LoopTimeoutTimerDriver : EventDriverTimers {
|
||||||
if (descriptor !in m_timers) return true;
|
if (descriptor !in m_timers) return true;
|
||||||
|
|
||||||
auto tm = m_timers[descriptor];
|
auto tm = m_timers[descriptor];
|
||||||
if (!--tm.refCount) {
|
tm.refCount--;
|
||||||
|
|
||||||
|
// cancel starved timer waits
|
||||||
|
if (tm.callback && tm.refCount == 1 && !tm.pending) {
|
||||||
|
debug addRef(descriptor);
|
||||||
|
cancelWait(tm.id);
|
||||||
|
debug {
|
||||||
|
assert(tm.refCount == 1);
|
||||||
|
releaseRef(descriptor);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tm.refCount) {
|
||||||
if (tm.pending) stop(tm.id);
|
if (tm.pending) stop(tm.id);
|
||||||
m_timers.remove(descriptor);
|
m_timers.remove(descriptor);
|
||||||
() @trusted {
|
() @trusted {
|
||||||
|
|
Loading…
Reference in a new issue