From 21c5af3dc018ec1f2218a3df3c8195cfcfe3aefa Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 3 Feb 2017 08:17:21 +0200 Subject: Add support for passing alternative task start counts to scheduler --- build2/scheduler | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) (limited to 'build2/scheduler') diff --git a/build2/scheduler b/build2/scheduler index 42f82e0..5b0f566 100644 --- a/build2/scheduler +++ b/build2/scheduler @@ -58,7 +58,7 @@ namespace build2 // F should return void and not throw any exceptions. The way the result // of a task is communicated back to the master thread is ad hoc, usually // via "out" arguments. Such result(s) can only be retrieved by the master - // once its task count reaches 0. + // once its task count reaches the start count. // // The argument passing semantics is the same as for std::thread. In // particular, lvalue-references are passed as copies (use ref()/cref() @@ -71,16 +71,43 @@ namespace build2 // template void - async (atomic_count& task_count, F&&, A&&...); + async (size_t start_count, atomic_count& task_count, F&&, A&&...); - // Wait until the task count reaches 0. If the scheduler is shutdown while - // waiting, throw system_error(ECANCELED). + template + void + async (atomic_count& task_count, F&& f, A&&... a) + { + async (0, task_count, forward (f), forward (a)...); + } + + // Wait until the task count reaches the start count. If the scheduler is + // shutdown while waiting, throw system_error(ECANCELED). // // Note that it is valid to wait on another thread's task count (that is, - // without making any async() calls in this thread). + // without making any async() calls in this thread). However, if the start + // count differs from the one passed to async(), then whomever sets the + // start count to this alternative value must also call resume() below + // in order to signal waiting threads. + // + // Note also that in this case (waiting on someone else's start count), + // the async() call could execute the tasks synchronously without ever + // incrementing the task count. Thus if waiting on another thread's start + // count starts before/during async() calls, then it must be "gated" with + // an alternative (lower) start count. // void - wait (atomic_count& task_count); + wait (size_t start_count, atomic_count& task_count); + + void + wait (atomic_count& task_count) + { + wait (0, task_count); + } + + // Resume threads waiting on this task count. + // + void + resume (atomic_count& task_count); // Startup and shutdown. // @@ -205,10 +232,7 @@ namespace build2 helper (void*); void - suspend (atomic_count& task_count); - - void - resume (atomic_count& task_count); + suspend (size_t start_count, atomic_count& task_count); // Task encapsulation. // @@ -219,6 +243,7 @@ namespace build2 using args_type = std::tuple...>; atomic_count* task_count; + size_t start_count; func_type func; args_type args; -- cgit v1.1