Fix Task.running and Task.yield directly after runTask/yieldLock.

The status of the task was erroneously reported as not running until the task was actually executed for the first time (which only happens after the yield lock has been lifted).
This commit is contained in:
Sönke Ludwig 2018-04-08 01:30:43 +02:00
parent 0d09c3f28d
commit fd92a7f555
2 changed files with 20 additions and 3 deletions

View file

@ -395,6 +395,21 @@ package Task runTask_internal(alias TFI_SETUP)()
return handle; return handle;
} }
unittest { // ensure task.running is true directly after runTask
Task t;
bool hit = false;
{
auto l = yieldLock();
t = runTask({ hit = true; });
assert(!hit);
assert(t.running);
}
t.join();
assert(!t.running);
assert(hit);
}
/** /**
Runs a new asynchronous task in a worker thread. Runs a new asynchronous task in a worker thread.

View file

@ -67,13 +67,15 @@ struct Task {
@property size_t taskCounter() const @safe { return m_taskCounter; } @property size_t taskCounter() const @safe { return m_taskCounter; }
@property inout(Thread) thread() inout @trusted { if (m_fiber) return this.taskFiber.thread; return null; } @property inout(Thread) thread() inout @trusted { if (m_fiber) return this.taskFiber.thread; return null; }
/** Determines if the task is still running. /** Determines if the task is still running or scheduled to be run.
*/ */
@property bool running() // FIXME: this is NOT thread safe @property bool running() // FIXME: this is NOT thread safe
const @trusted { const @trusted {
assert(m_fiber !is null, "Invalid task handle"); assert(m_fiber !is null, "Invalid task handle");
try if (this.taskFiber.state == Fiber.State.TERM) return false; catch (Throwable) {} try if (this.taskFiber.state == Fiber.State.TERM) return false; catch (Throwable) {}
return this.taskFiber.m_running && this.taskFiber.m_taskCounter == m_taskCounter; if (this.taskFiber.m_taskCounter != m_taskCounter)
return false;
return this.taskFiber.m_running || this.taskFiber.m_taskFunc.func !is null;
} }
package @property ref ThreadInfo tidInfo() @system { return m_fiber ? taskFiber.tidInfo : s_tidInfo; } // FIXME: this is not thread safe! package @property ref ThreadInfo tidInfo() @system { return m_fiber ? taskFiber.tidInfo : s_tidInfo; } // FIXME: this is not thread safe!
@ -465,7 +467,7 @@ final package class TaskFiber : Fiber {
void join(bool interruptiple)(size_t task_counter) void join(bool interruptiple)(size_t task_counter)
@trusted { @trusted {
auto cnt = m_onExit.emitCount; auto cnt = m_onExit.emitCount;
while (m_running && m_taskCounter == task_counter) { while ((m_running || m_taskFunc.func !is null) && m_taskCounter == task_counter) {
static if (interruptiple) static if (interruptiple)
cnt = m_onExit.wait(cnt); cnt = m_onExit.wait(cnt);
else else