From 2653c8c5e03276537695fe52377a0b474bb9c4d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Thu, 22 Feb 2018 16:14:26 +0100 Subject: [PATCH] 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. --- source/vibe/core/task.d | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/source/vibe/core/task.d b/source/vibe/core/task.d index 1aa02f4..cb187ac 100644 --- a/source/vibe/core/task.d +++ b/source/vibe/core/task.d @@ -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 recycleFiber(this); } @@ -456,7 +458,7 @@ final package class TaskFiber : Fiber { try call(Fiber.Rethrow.no); catch (Exception e) assert(false, e.msg); } (); - } + } /** Blocks until the task has ended. */ @@ -779,21 +781,23 @@ package struct TaskScheduler { 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."); + + auto tf = () @trusted { return t.taskFiber; } (); + if (tf.m_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."); + m_taskQueue.remove(tf); + 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 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) { - 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."); - m_taskQueue.remove(tf); - assert(!tf.m_queue, "Task removed from queue, but still has one set!?"); - } debug (VibeTaskLog) logDebugV("Switching tasks (%s already in queue)", m_taskQueue.length); if (defer) { @@ -878,6 +882,7 @@ package struct TaskScheduler { debug if (TaskFiber.ms_taskEventCallback) () @trusted { TaskFiber.ms_taskEventCallback(TaskEvent.yield, task); } (); () @trusted { Fiber.yield(); } (); debug if (TaskFiber.ms_taskEventCallback) () @trusted { TaskFiber.ms_taskEventCallback(TaskEvent.resume, task); } (); + assert(!task.m_fiber.m_queue, "Task is still scheduled after resumption."); } }