From de9d72da80ee6452bc7948c15394f5437ae81533 Mon Sep 17 00:00:00 2001 From: Zygo Blaxell Date: Sun, 12 Jan 2025 13:54:54 -0500 Subject: [PATCH] task: flatten queues of dependent Tasks Suppose Task A, B, and C are created in that order, and currently running. Task T acquires Exclusion E. Task B, A, and C attempt to acquire the same Exclusion, in that order, but fail because Task T holds it. The result is Task T with a post-exec queue: T, [ B, A, C ] sort_requested Now suppose Task U acquires Exclusion F, then Task T attempts to acquire Exclusion F. Task T fails to acquire F, so T is inserted into U's post-exec queue. The result at the end of the execution of T is a tree: U, [ T ] sort_requested \-> [ B, A, C ] sort_requested Task T exits after failing to acquire a lock. When T exits, T will sort its post-exec queue and submit the post-exec queue for execution immediately: Worker 1: U, [ T ] sort_requested Worker 2: A, B, C This isn't ideal because T, A, B, and C all depend on at least one common Exclusion, so they are likely to immediately conflict with T when U exits and T runs again. Ideally, A, B, and C would at least remain in a common queue with T, and ideally that queue is sorted. Instead of inserting T into U's post-exec queue, insert T and all of T's post-exec queue, which creates a single flattened Task list: U, [ T, B, A, C ] sort_requested Then when U exits, it will sort [ T, B, A, C ] into [ A, B, C, T ], and run all of the queued Tasks in age priority order: U exited, [ T, B, A, C ] sort_requested U exited, [ A, B, C, T ] [ A, B, C, T ] on TaskConsumer queue Signed-off-by: Zygo Blaxell --- lib/task.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/task.cc b/lib/task.cc index 6bbf165..d0b5894 100644 --- a/lib/task.cc +++ b/lib/task.cc @@ -331,8 +331,11 @@ namespace crucible { PairLock lock(m_mutex, task->m_mutex); if (!task->m_run_now) { task->m_run_now = true; + // Move the task and its post-exec queue to follow this task, + // and request a sort of the flattened list. m_sort_queue = true; - append_nolock(task); + m_post_exec_queue.push_back(task); + m_post_exec_queue.splice(m_post_exec_queue.end(), task->m_post_exec_queue); } }