aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-07-28 09:28:28 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-07-28 09:28:28 +0200
commite84eedc54348e268ca95200b70caede9884076ea (patch)
tree47adec094b24d8cb6934bbf28434e746ad9f564f
parent566bcb8c4c36d12e398f00349c5f27cae06fa7a9 (diff)
Add support for custom data storage in target::preprequisite_targets
-rw-r--r--build2/algorithm.cxx40
-rw-r--r--build2/algorithm.hxx15
-rw-r--r--build2/algorithm.ixx4
-rw-r--r--build2/install/rule.cxx14
-rw-r--r--build2/target.hxx23
-rw-r--r--build2/test/script/regex.hxx1
-rw-r--r--build2/types.hxx1
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 <typename T>
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<const target*> (action, target&, const target*[], size_t);
+
+ template void
+ match_members<prerequisite_target> (
+ 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 <typename T>
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 <typename T>
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<const target*> (
+ action, const target&, const target*[], size_t);
+
+ template target_state
+ reverse_execute_members<const target*> (
+ action, const target&, const target*[], size_t);
+
+ template target_state
+ straight_execute_members<prerequisite_target> (
+ action, const target&, prerequisite_target[], size_t);
+
+ template target_state
+ reverse_execute_members<prerequisite_target> (
+ action, const target&, prerequisite_target[], size_t);
+
pair<optional<target_state>, 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 <typename T>
void
- match_members (action, target&, const target*[], size_t);
+ match_members (action, target&, T[], size_t);
template <size_t N>
inline void
@@ -219,7 +222,7 @@ namespace build2
}
inline void
- match_members (action a, target& t, vector<const target*>& 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 <typename T>
target_state
- straight_execute_members (action, const target&, const target*[], size_t);
+ straight_execute_members (action, const target&, T[], size_t);
+ template <typename T>
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<target&> (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<const target*> (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<prerequisite_target>;
+
// Target.
//
class target
@@ -552,8 +572,7 @@ namespace build2
//
// Note that the recipe may modify this list.
//
- using prerequisite_targets_type = vector<const target*>;
- 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 <regex>
#include <locale>
#include <string> // basic_string
-#include <cstdint> // uintptr_t
#include <type_traits> // make_unsigned, enable_if, is_*
#include <unordered_set>
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;