Always remove task from queue when switching to it. Fixes #58.

Previously the task was only removed if switchTo was called from another task. Now it also gets removed when switchTo (e.g. due to a runTask() call) gets called form outside of a task.
This commit is contained in:
Sönke Ludwig 2018-02-22 16:14:26 +01:00
parent 0ff503afa6
commit 2653c8c5e0

View file

@ -414,6 +414,8 @@ final package class TaskFiber : Fiber {
} }
} }
assert(!m_queue, "Fiber done but still scheduled to be resumed!?");
// make the fiber available for the next task // make the fiber available for the next task
recycleFiber(this); recycleFiber(this);
} }
@ -779,15 +781,8 @@ package struct TaskScheduler {
auto thisthr = thist ? thist.thread : () @trusted { return Thread.getThis(); } (); auto thisthr = thist ? thist.thread : () @trusted { return Thread.getThis(); } ();
assert(t.thread is thisthr, "Cannot switch to a task that lives in a different thread."); assert(t.thread is thisthr, "Cannot switch to a task that lives in a different thread.");
if (thist == Task.init && defer == No.defer) {
assert(TaskFiber.getThis().m_yieldLockCount == 0, "Cannot yield within an active yieldLock()!");
debug (VibeTaskLog) logTrace("switch to task from global context");
resumeTask(t);
debug (VibeTaskLog) logTrace("task yielded control back to global context");
} else {
auto tf = () @trusted { return t.taskFiber; } (); auto tf = () @trusted { return t.taskFiber; } ();
auto thistf = () @trusted { return thist.taskFiber; } ();
assert(!thistf || !thistf.m_queue, "Calling task is running, but scheduled to be resumed!?");
if (tf.m_queue) { if (tf.m_queue) {
debug (VibeTaskLog) logTrace("Task to switch to is already scheduled. Moving to front of queue."); debug (VibeTaskLog) logTrace("Task to switch to is already scheduled. Moving to front of queue.");
assert(tf.m_queue is &m_taskQueue, "Task is already enqueued, but not in the main task queue."); assert(tf.m_queue is &m_taskQueue, "Task is already enqueued, but not in the main task queue.");
@ -795,6 +790,15 @@ package struct TaskScheduler {
assert(!tf.m_queue, "Task removed from queue, but still has one set!?"); assert(!tf.m_queue, "Task removed from queue, but still has one set!?");
} }
if (thist == Task.init && defer == No.defer) {
assert(TaskFiber.getThis().m_yieldLockCount == 0, "Cannot yield within an active yieldLock()!");
debug (VibeTaskLog) logTrace("switch to task from global context");
resumeTask(t);
debug (VibeTaskLog) logTrace("task yielded control back to global context");
} else {
auto thistf = () @trusted { return thist.taskFiber; } ();
assert(!thistf || !thistf.m_queue, "Calling task is running, but scheduled to be resumed!?");
debug (VibeTaskLog) logDebugV("Switching tasks (%s already in queue)", m_taskQueue.length); debug (VibeTaskLog) logDebugV("Switching tasks (%s already in queue)", m_taskQueue.length);
if (defer) { if (defer) {
m_taskQueue.insertFront(tf); m_taskQueue.insertFront(tf);
@ -878,6 +882,7 @@ package struct TaskScheduler {
debug if (TaskFiber.ms_taskEventCallback) () @trusted { TaskFiber.ms_taskEventCallback(TaskEvent.yield, task); } (); debug if (TaskFiber.ms_taskEventCallback) () @trusted { TaskFiber.ms_taskEventCallback(TaskEvent.yield, task); } ();
() @trusted { Fiber.yield(); } (); () @trusted { Fiber.yield(); } ();
debug if (TaskFiber.ms_taskEventCallback) () @trusted { TaskFiber.ms_taskEventCallback(TaskEvent.resume, task); } (); debug if (TaskFiber.ms_taskEventCallback) () @trusted { TaskFiber.ms_taskEventCallback(TaskEvent.resume, task); } ();
assert(!task.m_fiber.m_queue, "Task is still scheduled after resumption.");
} }
} }