Merge pull request #98 from vibe-d/issue-86-timer-memory-leak
Implement callback based timers without relying on a task. Fixes #86.
This commit is contained in:
commit
ec170e954d
|
@ -5,12 +5,14 @@
|
||||||
- Simplified worker task logic by avoiding an explicit event loop - [pull #95][issue95]
|
- Simplified worker task logic by avoiding an explicit event loop - [pull #95][issue95]
|
||||||
- Fixed an issue in `WindowsPath`, where an empty path was converted to "/" when cast to another path type - [pull #91][issue91]
|
- Fixed an issue in `WindowsPath`, where an empty path was converted to "/" when cast to another path type - [pull #91][issue91]
|
||||||
- Fixed two hang issues in `TaskPool` causing the worker task processing to possibly hang at shutdown or to temporarily hang during run time - [pull #96][issue96]
|
- Fixed two hang issues in `TaskPool` causing the worker task processing to possibly hang at shutdown or to temporarily hang during run time - [pull #96][issue96]
|
||||||
|
- Fixed internal timer callback tasks leaking memory - [issue #86][issue86], [pull #98][issue98]
|
||||||
|
|
||||||
[issue91]: https://github.com/vibe-d/vibe-core/issues/91
|
[issue91]: https://github.com/vibe-d/vibe-core/issues/91
|
||||||
[issue92]: https://github.com/vibe-d/vibe-core/issues/92
|
[issue92]: https://github.com/vibe-d/vibe-core/issues/92
|
||||||
[issue95]: https://github.com/vibe-d/vibe-core/issues/95
|
[issue95]: https://github.com/vibe-d/vibe-core/issues/95
|
||||||
[issue96]: https://github.com/vibe-d/vibe-core/issues/96
|
[issue96]: https://github.com/vibe-d/vibe-core/issues/96
|
||||||
[issue97]: https://github.com/vibe-d/vibe-core/issues/97
|
[issue97]: https://github.com/vibe-d/vibe-core/issues/97
|
||||||
|
[issue98]: https://github.com/vibe-d/vibe-core/issues/98
|
||||||
|
|
||||||
|
|
||||||
1.4.3 - 2018-09-03
|
1.4.3 - 2018-09-03
|
||||||
|
|
2
dub.sdl
2
dub.sdl
|
@ -4,7 +4,7 @@ authors "Sönke Ludwig"
|
||||||
copyright "Copyright © 2016-2018, rejectedsoftware e.K."
|
copyright "Copyright © 2016-2018, rejectedsoftware e.K."
|
||||||
license "MIT"
|
license "MIT"
|
||||||
|
|
||||||
dependency "eventcore" version="~>0.8.32"
|
dependency "eventcore" version="~>0.8.39"
|
||||||
dependency "stdx-allocator" version="~>2.77.0"
|
dependency "stdx-allocator" version="~>2.77.0"
|
||||||
|
|
||||||
targetName "vibe_core"
|
targetName "vibe_core"
|
||||||
|
|
|
@ -742,7 +742,7 @@ unittest {
|
||||||
|
|
||||||
See_also: createTimer
|
See_also: createTimer
|
||||||
*/
|
*/
|
||||||
Timer setTimer(Duration timeout, void delegate() nothrow @safe callback, bool periodic = false)
|
Timer setTimer(Duration timeout, Timer.Callback callback, bool periodic = false)
|
||||||
@safe nothrow {
|
@safe nothrow {
|
||||||
auto tm = createTimer(callback);
|
auto tm = createTimer(callback);
|
||||||
tm.rearm(timeout, periodic);
|
tm.rearm(timeout, periodic);
|
||||||
|
@ -784,16 +784,7 @@ Timer setTimer(Duration timeout, void delegate() callback, bool periodic = false
|
||||||
*/
|
*/
|
||||||
Timer createTimer(void delegate() nothrow @safe callback)
|
Timer createTimer(void delegate() nothrow @safe callback)
|
||||||
@safe nothrow {
|
@safe nothrow {
|
||||||
auto ret = Timer(eventDriver.timers.create());
|
return Timer(eventDriver.timers.create, callback);
|
||||||
if (callback !is null) {
|
|
||||||
runTask((void delegate() nothrow @safe cb, Timer tm) {
|
|
||||||
while (!tm.unique || tm.pending) {
|
|
||||||
tm.wait();
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
}, callback, ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1036,13 +1027,20 @@ struct Timer {
|
||||||
debug uint m_magicNumber = 0x4d34f916;
|
debug uint m_magicNumber = 0x4d34f916;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alias Callback = void delegate() @safe nothrow;
|
||||||
|
|
||||||
@safe:
|
@safe:
|
||||||
|
|
||||||
private this(TimerID id)
|
private this(TimerID id, Callback callback)
|
||||||
nothrow {
|
nothrow {
|
||||||
assert(id != TimerID.init, "Invalid timer ID.");
|
assert(id != TimerID.init, "Invalid timer ID.");
|
||||||
m_driver = eventDriver;
|
m_driver = eventDriver;
|
||||||
m_id = id;
|
m_id = id;
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
m_driver.timers.userData!Callback(m_id) = callback;
|
||||||
|
m_driver.timers.wait(m_id, &TimerCallbackHandler.instance.handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this(this)
|
this(this)
|
||||||
|
@ -1054,8 +1052,7 @@ struct Timer {
|
||||||
~this()
|
~this()
|
||||||
nothrow {
|
nothrow {
|
||||||
debug assert(m_magicNumber == 0x4d34f916, "Timer corrupted.");
|
debug assert(m_magicNumber == 0x4d34f916, "Timer corrupted.");
|
||||||
if (m_driver)
|
if (m_driver) releaseHandle!"timers"(m_id, () @trusted { return cast(shared)m_driver; } ());
|
||||||
releaseHandle!"timers"(m_id, () @trusted { return cast(shared)m_driver; } ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// True if the timer is yet to fire.
|
/// True if the timer is yet to fire.
|
||||||
|
@ -1080,13 +1077,34 @@ struct Timer {
|
||||||
void stop() nothrow { if (m_driver) m_driver.timers.stop(m_id); }
|
void stop() nothrow { if (m_driver) m_driver.timers.stop(m_id); }
|
||||||
|
|
||||||
/** Waits until the timer fires.
|
/** Waits until the timer fires.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
`true` is returned $(I iff) the timer was fired.
|
||||||
*/
|
*/
|
||||||
void wait()
|
bool wait()
|
||||||
{
|
{
|
||||||
asyncAwait!(TimerCallback,
|
auto cb = m_driver.timers.userData!Callback(m_id);
|
||||||
|
assert(cb is null, "Cannot wait on a timer that was created with a callback.");
|
||||||
|
|
||||||
|
auto res = asyncAwait!(TimerCallback2,
|
||||||
cb => m_driver.timers.wait(m_id, cb),
|
cb => m_driver.timers.wait(m_id, cb),
|
||||||
cb => m_driver.timers.cancelWait(m_id)
|
cb => m_driver.timers.cancelWait(m_id)
|
||||||
);
|
);
|
||||||
|
return res[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TimerCallbackHandler {
|
||||||
|
static TimerCallbackHandler instance;
|
||||||
|
void handle(TimerID timer, bool fired)
|
||||||
|
@safe nothrow {
|
||||||
|
if (fired) {
|
||||||
|
auto cb = eventDriver.timers.userData!(Timer.Callback)(timer);
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eventDriver.timers.isUnique(timer))
|
||||||
|
eventDriver.timers.wait(timer, &handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue