Merge pull request #162 from vibe-d/issue161-multiple-joiners
Fix Task.join() for multiple callers. Fixes #161.
This commit is contained in:
commit
a200328a0d
|
@ -362,7 +362,7 @@ final package class TaskFiber : Fiber {
|
||||||
import std.algorithm.mutation : swap;
|
import std.algorithm.mutation : swap;
|
||||||
import std.concurrency : Tid, thisTid;
|
import std.concurrency : Tid, thisTid;
|
||||||
import std.encoding : sanitize;
|
import std.encoding : sanitize;
|
||||||
import vibe.core.core : isEventLoopRunning, recycleFiber, taskScheduler, yield;
|
import vibe.core.core : isEventLoopRunning, recycleFiber, taskScheduler, yield, yieldLock;
|
||||||
|
|
||||||
version (VibeDebugCatchAll) alias UncaughtException = Throwable;
|
version (VibeDebugCatchAll) alias UncaughtException = Throwable;
|
||||||
else alias UncaughtException = Exception;
|
else alias UncaughtException = Exception;
|
||||||
|
@ -413,6 +413,17 @@ final package class TaskFiber : Fiber {
|
||||||
this.tidInfo.ident = Tid.init; // clear message box
|
this.tidInfo.ident = Tid.init; // clear message box
|
||||||
|
|
||||||
debug (VibeTaskLog) logTrace("Notifying joining tasks.");
|
debug (VibeTaskLog) logTrace("Notifying joining tasks.");
|
||||||
|
|
||||||
|
// Issue #161: This fiber won't be resumed before the next task
|
||||||
|
// is assigned, because it is already marked as de-initialized.
|
||||||
|
// Since ManualEvent.emit() will need to switch tasks, this
|
||||||
|
// would mean that only the first waiter is notified before
|
||||||
|
// this fiber gets a new task assigned.
|
||||||
|
// Using a yield lock forces all corresponding tasks to be
|
||||||
|
// enqueued into the schedule queue and resumed in sequence
|
||||||
|
// at the end of the scope.
|
||||||
|
auto l = yieldLock();
|
||||||
|
|
||||||
m_onExit.emit();
|
m_onExit.emit();
|
||||||
|
|
||||||
// make sure that the task does not get left behind in the yielder queue if terminated during yield()
|
// make sure that the task does not get left behind in the yielder queue if terminated during yield()
|
||||||
|
@ -723,7 +734,7 @@ package struct TaskScheduler {
|
||||||
auto t = Task.getThis();
|
auto t = Task.getThis();
|
||||||
if (t == Task.init) return; // not really a task -> no-op
|
if (t == Task.init) return; // not really a task -> no-op
|
||||||
auto tf = () @trusted { return t.taskFiber; } ();
|
auto tf = () @trusted { return t.taskFiber; } ();
|
||||||
debug (VibeTaskLog) logTrace("Yielding (interrupt=%s)", tf.m_interrupt);
|
debug (VibeTaskLog) logTrace("Yielding (interrupt=%s)", () @trusted { return (cast(shared)tf).getTaskStatus().interrupt; } ());
|
||||||
tf.handleInterrupt();
|
tf.handleInterrupt();
|
||||||
if (tf.m_queue !is null) return; // already scheduled to be resumed
|
if (tf.m_queue !is null) return; // already scheduled to be resumed
|
||||||
m_taskQueue.insertBack(tf);
|
m_taskQueue.insertBack(tf);
|
||||||
|
|
31
tests/issue-161-multiple-joiners.d
Normal file
31
tests/issue-161-multiple-joiners.d
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/+ dub.sdl:
|
||||||
|
name "tests"
|
||||||
|
dependency "vibe-core" path=".."
|
||||||
|
debugVersions "VibeTaskLog" "VibeAsyncLog"
|
||||||
|
+/
|
||||||
|
module tests;
|
||||||
|
|
||||||
|
import vibe.core.core;
|
||||||
|
import vibe.core.log;
|
||||||
|
import vibe.core.sync;
|
||||||
|
import core.time;
|
||||||
|
import core.stdc.stdlib : exit;
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
setTimer(5.seconds, { logError("Test has hung."); exit(1); });
|
||||||
|
|
||||||
|
Task t;
|
||||||
|
|
||||||
|
runTask({
|
||||||
|
t = runTask({ sleep(100.msecs); });
|
||||||
|
t.join();
|
||||||
|
});
|
||||||
|
|
||||||
|
yield();
|
||||||
|
|
||||||
|
assert(t && t.running);
|
||||||
|
|
||||||
|
t.join();
|
||||||
|
}
|
Loading…
Reference in a new issue