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.concurrency : Tid, thisTid;
|
||||
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;
|
||||
else alias UncaughtException = Exception;
|
||||
|
@ -413,6 +413,17 @@ final package class TaskFiber : Fiber {
|
|||
this.tidInfo.ident = Tid.init; // clear message box
|
||||
|
||||
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();
|
||||
|
||||
// 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();
|
||||
if (t == Task.init) return; // not really a task -> no-op
|
||||
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();
|
||||
if (tf.m_queue !is null) return; // already scheduled to be resumed
|
||||
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