diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2017-02-08 07:42:41 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2017-02-13 12:42:42 +0200 |
commit | 5cefca444f7062c61cc9d118ffea5901e05186fd (patch) | |
tree | 879d608f9a9084c7eaa4e5cb8bcad5650d966730 /build2/operation.cxx | |
parent | db2a696f810e41189bcdf5524696ff3d0cfbe5a9 (diff) |
Implement parallel operation execution
Diffstat (limited to 'build2/operation.cxx')
-rw-r--r-- | build2/operation.cxx | 59 |
1 files changed, 20 insertions, 39 deletions
diff --git a/build2/operation.cxx b/build2/operation.cxx index 01f469e..f37d642 100644 --- a/build2/operation.cxx +++ b/build2/operation.cxx @@ -124,60 +124,41 @@ namespace build2 } void - execute (action a, const action_targets& ts, bool quiet) + execute (action a, action_targets& ts, bool quiet) { tracer trace ("execute"); + // Reverse the order of targets if the execution mode is 'last'. + // + if (current_mode == execution_mode::last) + reverse (ts.begin (), ts.end ()); + phase_guard pg (run_phase::execute); - // Execute collecting postponed targets (to be re-examined later). - // Do it in reverse order if the execution mode is 'last'. + // Similar logic to execute_members(): first start asynchronous execution + // of all the top-level targets. // - vector<reference_wrapper<const target>> psp; - - auto body = [a, quiet, &psp, &trace] (const void* v) + atomic_count task_count (0); + for (const void* v: ts) { const target& t (*static_cast<const target*> (v)); l5 ([&]{trace << diag_doing (a, t);}); - switch (execute (a, t)) - { - case target_state::unchanged: - { - if (!quiet) - info << diag_done (a, t); - break; - } - case target_state::postponed: - psp.push_back (t); - break; - case target_state::changed: - break; - case target_state::failed: - //@@ This could probably happen in a parallel build. - default: - assert (false); - } - }; - - if (current_mode == execution_mode::first) - for (const void* v: ts) body (v); - else - for (const void* v: reverse_iterate (ts)) body (v); + execute_async (a, t, 0, task_count); + } + sched.wait (task_count); - // We should have executed every target that we matched. + // We are now running serially and we should have executed every target + // that we matched. // assert (dependency_count == 0); - // Re-examine postponed targets. This is the only reliable way to - // find out whether the target has changed. - // - // Note: must be serial. - // - for (const target& t: psp) + for (const void* v: ts) { - switch (execute (a, t)) + const target& t (*static_cast<const target*> (v)); + + switch (t.synchronized_state ()) { case target_state::unchanged: { @@ -190,7 +171,7 @@ namespace build2 case target_state::postponed: assert (false); case target_state::failed: - //@@ This could probably happen in a parallel build. + //@@ MT: This could probably happen in a parallel build. default: assert (false); } |