From e84eedc54348e268ca95200b70caede9884076ea Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 28 Jul 2017 09:28:28 +0200 Subject: Add support for custom data storage in target::preprequisite_targets --- build2/algorithm.cxx | 40 +++++++++++++++++++++++++++++++++------- build2/algorithm.hxx | 15 +++++++++++---- build2/algorithm.ixx | 4 +++- build2/install/rule.cxx | 14 +++++++------- build2/target.hxx | 23 +++++++++++++++++++++-- build2/test/script/regex.hxx | 1 - build2/types.hxx | 1 + 7 files changed, 76 insertions(+), 22 deletions(-) diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx index 588980e..e702836 100644 --- a/build2/algorithm.cxx +++ b/build2/algorithm.cxx @@ -720,8 +720,9 @@ namespace build2 match_prerequisite_range (a, t, group_prerequisite_members (a, t), s); } + template void - match_members (action a, target& t, const target* ts[], size_t n) + match_members (action a, target& t, T ts[], size_t n) { // Pretty much identical to match_prerequisite_range() except we don't // search. @@ -753,6 +754,15 @@ namespace build2 } } + // Instantiate only for what we need. + // + template void + match_members (action, target&, const target*[], size_t); + + template void + match_members ( + action, target&, prerequisite_target[], size_t); + const fsdir* inject_fsdir (action a, target& t, bool parent) { @@ -1027,10 +1037,9 @@ namespace build2 // but what the hell. Note that this means we have to always "harvest" all // the targets to clear the mark. // + template target_state - straight_execute_members (action a, - const target& t, - const target* ts[], size_t n) + straight_execute_members (action a, const target& t, T ts[], size_t n) { target_state r (target_state::unchanged); @@ -1082,10 +1091,9 @@ namespace build2 return r; } + template target_state - reverse_execute_members (action a, - const target& t, - const target* ts[], size_t n) + reverse_execute_members (action a, const target& t, T ts[], size_t n) { // Pretty much as straight_execute_members() but in reverse order. // @@ -1132,6 +1140,24 @@ namespace build2 return r; } + // Instantiate only for what we need. + // + template target_state + straight_execute_members ( + action, const target&, const target*[], size_t); + + template target_state + reverse_execute_members ( + action, const target&, const target*[], size_t); + + template target_state + straight_execute_members ( + action, const target&, prerequisite_target[], size_t); + + template target_state + reverse_execute_members ( + action, const target&, prerequisite_target[], size_t); + pair, const target*> execute_prerequisites (const target_type* tt, action a, const target& t, diff --git a/build2/algorithm.hxx b/build2/algorithm.hxx index aef72cb..58bdf2f 100644 --- a/build2/algorithm.hxx +++ b/build2/algorithm.hxx @@ -208,8 +208,11 @@ namespace build2 // dependencies. Similar in semantics to match_prerequisites(). Any marked // target pointers are skipped. // + // T can only be const target* or prerequisite_target. + // + template void - match_members (action, target&, const target*[], size_t); + match_members (action, target&, T[], size_t); template inline void @@ -219,7 +222,7 @@ namespace build2 } inline void - match_members (action a, target& t, vector& ts, size_t start) + match_members (action a, target& t, prerequisite_targets& ts, size_t start) { match_members (a, t, ts.data () + start, ts.size () - start); } @@ -372,11 +375,15 @@ namespace build2 // Execute members of a group or similar prerequisite-like dependencies. // Similar in semantics to execute_prerequisites(). // + // T can only be const target* or prerequisite_target. + // + template target_state - straight_execute_members (action, const target&, const target*[], size_t); + straight_execute_members (action, const target&, T[], size_t); + template target_state - reverse_execute_members (action, const target&, const target*[], size_t); + reverse_execute_members (action, const target&, T[], size_t); // Call straight or reverse depending on the current mode. // diff --git a/build2/algorithm.ixx b/build2/algorithm.ixx index 5226af4..53501d3 100644 --- a/build2/algorithm.ixx +++ b/build2/algorithm.ixx @@ -355,7 +355,9 @@ namespace build2 execute_prerequisites (action a, const target& t) { auto& p (const_cast (t).prerequisite_targets); // MT-aware. - return execute_members (a, t, p.data (), p.size ()); + return current_mode == execution_mode::first + ? straight_execute_members (a, t, p.data (), p.size ()) + : reverse_execute_members (a, t, p.data (), p.size ()); } // If the first argument is NULL, then the result is treated as a boolean diff --git a/build2/install/rule.cxx b/build2/install/rule.cxx index 6b0905f..8611247 100644 --- a/build2/install/rule.cxx +++ b/build2/install/rule.cxx @@ -189,10 +189,10 @@ namespace build2 // Save the prerequisite targets that we found since the // call to match_delegate() below will wipe them out. // - target::prerequisite_targets_type p; + prerequisite_targets pts; if (!t.prerequisite_targets.empty ()) - p.swap (t.prerequisite_targets); + pts.swap (t.prerequisite_targets); // Find the "real" update rule, that is, the rule that would // have been found if we signalled that we do not match from @@ -203,24 +203,24 @@ namespace build2 // If we have no installable prerequisites, then simply redirect // to it. // - if (p.empty ()) + if (pts.empty ()) return d; // Ok, the worst case scenario: we need to cause update of // prerequisite targets and also delegate to the real update. // - return [pt = move (p), dr = move (d)] ( + return [pts = move (pts), d = move (d)] ( action a, const target& t) mutable -> target_state { // Do the target update first. // - target_state r (execute_delegate (dr, a, t)); + target_state r (execute_delegate (d, a, t)); // Swap our prerequisite targets back in and execute. // - t.prerequisite_targets.swap (pt); + t.prerequisite_targets.swap (pts); r |= straight_execute_prerequisites (a, t); - pt.swap (t.prerequisite_targets); // In case we get re-executed. + pts.swap (t.prerequisite_targets); // In case we get re-executed. return r; }; diff --git a/build2/target.hxx b/build2/target.hxx index b5863dc..92c5768 100644 --- a/build2/target.hxx +++ b/build2/target.hxx @@ -115,6 +115,26 @@ namespace build2 size_t count; }; + // List of prerequisites resolved to targets. Unless additional storage is + // needed, it can be used as just vector (which is what we + // used to have initially). + // + struct prerequisite_target + { + using target_type = build2::target; + + prerequisite_target (const target_type* t, uintptr_t d = 0) + : target (t), data (d) {} + + operator const target_type*& () {return target;} + operator const target_type* () const {return target;} + const target_type* operator-> () const {return target;} + + const target_type* target; + uintptr_t data; + }; + using prerequisite_targets = vector; + // Target. // class target @@ -552,8 +572,7 @@ namespace build2 // // Note that the recipe may modify this list. // - using prerequisite_targets_type = vector; - mutable prerequisite_targets_type prerequisite_targets; + mutable build2::prerequisite_targets prerequisite_targets; // Auxilary data storage. // diff --git a/build2/test/script/regex.hxx b/build2/test/script/regex.hxx index 801dc09..a375201 100644 --- a/build2/test/script/regex.hxx +++ b/build2/test/script/regex.hxx @@ -9,7 +9,6 @@ #include #include #include // basic_string -#include // uintptr_t #include // make_unsigned, enable_if, is_* #include diff --git a/build2/types.hxx b/build2/types.hxx index 8657ee6..374a3eb 100644 --- a/build2/types.hxx +++ b/build2/types.hxx @@ -53,6 +53,7 @@ namespace build2 using std::uint16_t; using std::uint32_t; using std::uint64_t; + using std::uintptr_t; using std::size_t; using std::nullptr_t; -- cgit v1.1