From b37f1aa6398065be806e6605a023189685669885 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 15 Feb 2017 03:55:15 +0200 Subject: Implement parallel match --- build2/dist/operation.cxx | 87 +++++++++++++++++------------------------------ build2/dist/rule | 4 +-- build2/dist/rule.cxx | 10 +++--- 3 files changed, 39 insertions(+), 62 deletions(-) (limited to 'build2/dist') diff --git a/build2/dist/operation.cxx b/build2/dist/operation.cxx index e087069..6b50c14 100644 --- a/build2/dist/operation.cxx +++ b/build2/dist/operation.cxx @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -29,7 +28,7 @@ namespace build2 // install // static void - install (const process_path& cmd, file&, const dir_path&); + install (const process_path& cmd, const file&, const dir_path&); // cd && tar|zip ... /. // @@ -61,7 +60,7 @@ namespace build2 // For now we assume all the targets are from the same project. // - target& t (*static_cast (ts[0])); + const target& t (*static_cast (ts[0])); const scope* rs (t.base_scope ().root_scope ()); if (rs == nullptr) @@ -98,63 +97,34 @@ namespace build2 const string& dist_package (cast (l)); const process_path& dist_cmd (cast (rs->vars["dist.cmd"])); - // Match a rule for every operation supported by this project. Skip - // default_id. + // Verify all the targets are from the same project. // - auto match = [&trace, &rs, &ts] (const operation_info& o) + for (const void* v: ts) { - // Note that we are not calling operation_pre/post() callbacks - // here since the meta operation is dist and we know what we - // are doing. - // - set_current_oif (o); - dependency_count = 0; - - action a (dist_id, o.id); - - if (verb >= 6) - dump (a); - - { - phase_guard pg (run_phase::search_match); - - scheduler::atomic_count task_count (0); - { - model_slock ml; - - for (void* v: ts) - { - target& t (*static_cast (v)); - - if (rs != t.base_scope ().root_scope ()) - fail << "target " << t << " is from a different project" << - info << "one dist() meta-operation can handle one project" << - info << "consider using several dist() meta-operations"; - - l5 ([&]{trace << diag_doing (a, t);}); - - sched.async (task_count, - [a] (target& t) - { - model_slock ml; - build2::match (ml, a, t); // @@ MT exception. - }, - ref (t)); - } - } - sched.wait (task_count); - } + const target& t (*static_cast (v)); - if (verb >= 6) - dump (a); - }; + if (rs != t.base_scope ().root_scope ()) + fail << "target " << t << " is from a different project" << + info << "one dist() meta-operation can handle one project" << + info << "consider using several dist() meta-operations"; + } + // Match a rule for every operation supported by this project. Skip + // default_id. + // for (operations::size_type id (default_id + 1); id < rs->operations.size (); ++id) { if (const operation_info* oif = rs->operations[id]) - match (*oif); + { + // Note that we are not calling operation_pre/post() callbacks here + // since the meta operation is dist and we know what we are doing. + // + set_current_oif (*oif); + + match (action (dist_id, oif->id), ts); // Standard (perform) match. + } } // Add buildfiles that are not normally loaded as part of the @@ -256,13 +226,20 @@ namespace build2 if (perform.meta_operation_pre != nullptr) perform.meta_operation_pre (); + // This is a hack since according to the rules we need to completely + // reset the state. We could have done that (i.e., saved target names + // and then re-searched them in the new tree) but that would just slow + // things down while this little cheat seems harmless (i.e., assume + // the dist mete-opreation is "compatible" with perform). + // + size_t on (current_on); set_current_mif (perform); + current_on = on + 1; if (perform.operation_pre != nullptr) perform.operation_pre (update_id); set_current_oif (update); - dependency_count = 0; action a (perform_id, update_id); @@ -289,9 +266,9 @@ namespace build2 // Copy over all the files. // - for (void* v: files) + for (const void* v: files) { - file& t (*static_cast (v)); + const file& t (*static_cast (v)); // Figure out where this file is inside the target directory. // @@ -369,7 +346,7 @@ namespace build2 // install // static void - install (const process_path& cmd, file& t, const dir_path& d) + install (const process_path& cmd, const file& t, const dir_path& d) { dir_path reld (relative (d)); path relf (relative (t.path ())); diff --git a/build2/dist/rule b/build2/dist/rule index 61be24f..db8e731 100644 --- a/build2/dist/rule +++ b/build2/dist/rule @@ -22,10 +22,10 @@ namespace build2 rule () {} virtual match_result - match (slock&, action, target&, const string&) const override; + match (action, target&, const string&) const override; virtual recipe - apply (slock&, action, target&) const override; + apply (action, target&) const override; }; } } diff --git a/build2/dist/rule.cxx b/build2/dist/rule.cxx index f5c4018..bf5ab47 100644 --- a/build2/dist/rule.cxx +++ b/build2/dist/rule.cxx @@ -16,17 +16,17 @@ namespace build2 namespace dist { match_result rule:: - match (slock&, action, target&, const string&) const + match (action, target&, const string&) const { return true; // We always match. } recipe rule:: - apply (slock& ml, action a, target& t) const + apply (action a, target& t) const { const dir_path& out_root (t.root_scope ().out_path ()); - auto r (group_prerequisite_members (ml, a, t, false)); + auto r (group_prerequisite_members (a, t, false)); for (auto i (r.begin ()); i != r.end (); ++i) { prerequisite_member p (*i); @@ -43,12 +43,12 @@ namespace build2 if (p.type ().see_through && i.enter_group ()) continue; - target& pt (p.search ()); + const target& pt (p.search ()); // Don't match targets that are outside of our project. // if (pt.dir.sub (out_root)) - build2::match (ml, a, pt); + build2::match (a, pt); } return noop_recipe; // We will never be executed. -- cgit v1.1