diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2017-02-03 07:41:33 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2017-02-13 12:42:41 +0200 |
commit | 0d3ce80a2f0cd8398225e7ef7a1abbe7e77a38fc (patch) | |
tree | ddc78f3db07d5ba2cbccde7b62e95df8be099bc0 /build2/scheduler.cxx | |
parent | 63f6a8256e3f9fb47cb941be63baa70e2be48d3b (diff) |
Add support for waiting on other threads task counts in scheduler
Diffstat (limited to 'build2/scheduler.cxx')
-rw-r--r-- | build2/scheduler.cxx | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/build2/scheduler.cxx b/build2/scheduler.cxx index 47d38e4..c151847 100644 --- a/build2/scheduler.cxx +++ b/build2/scheduler.cxx @@ -18,17 +18,20 @@ namespace build2 // See if we can run some of our own tasks. // - task_queue& tq (*task_queue_); // Must have been set by async() or task - // would have been 0. - - for (lock ql (tq.mutex); !tq.shutdown && !empty_back (tq); ) - pop_back (tq, ql); - - // Note that empty task queue doesn't automatically mean the task count - // is zero (some might still be executing asynchronously). + // If we are waiting on someone else's task count then there migh still + // be no queue which is set by async(). // - if (task_count == 0) - return; + if (task_queue* tq = task_queue_) + { + for (lock ql (tq->mutex); !tq->shutdown && !empty_back (*tq); ) + pop_back (*tq, ql); + + // Note that empty task queue doesn't automatically mean the task count + // is zero (some might still be executing asynchronously). + // + if (task_count == 0) + return; + } suspend (task_count); } @@ -66,7 +69,18 @@ namespace build2 bool collision; { lock l (s.mutex); - collision = (s.waiters++ != 0); + + // We have a collision if there is already a waiter for a different + // task count. + // + collision = (s.waiters++ != 0 && s.tcount != &tc); + + // This is nuanced: we want to always have the task count of the last + // thread to join the queue. Otherwise, if threads are leaving and + // joining the queue simultaneously, we may end up with a task count of + // a thread group that is no longer waiting. + // + s.tcount = &tc; // Since we use a mutex for synchronization, we can relax the atomic // access. |