aboutsummaryrefslogtreecommitdiff
path: root/build2
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-06-05 14:56:48 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-06-05 14:56:48 +0200
commita8c082e2adf9865636c0e0a6906c6fde3a7c3e69 (patch)
tree5fc32141aa91a8cdaa629fc6c5a8975127f6e39f /build2
parente3a6b031d0ee4bd56b2a2296d5faeaff142e3569 (diff)
Remove implicit see-through iteration over ad hoc group members
This can only be done MT-safely after a synchronous match.
Diffstat (limited to 'build2')
-rw-r--r--build2/algorithm.hxx2
-rw-r--r--build2/install/rule.cxx10
-rw-r--r--build2/target.hxx26
-rw-r--r--build2/target.ixx33
4 files changed, 16 insertions, 55 deletions
diff --git a/build2/algorithm.hxx b/build2/algorithm.hxx
index d002e23..7bb3a59 100644
--- a/build2/algorithm.hxx
+++ b/build2/algorithm.hxx
@@ -427,7 +427,7 @@ namespace build2
// followed by the ad hoc group member, then target itself, and, finally,
// the prerequisites in the reverse order.
//
- // You can also clean extra files derived from adhoc group members.
+ // You can also clean extra files derived from ad hoc group members.
//
target_state
clean_extra (action, const file&,
diff --git a/build2/install/rule.cxx b/build2/install/rule.cxx
index 3a56480..6b0905f 100644
--- a/build2/install/rule.cxx
+++ b/build2/install/rule.cxx
@@ -150,11 +150,8 @@ namespace build2
// run standard search_and_match()? Will need an indicator
// that it was forced (e.g., [install]) for filter() below.
//
- auto r (group_prerequisite_members (a, t));
- for (auto i (r.begin ()); i != r.end (); ++i)
+ for (prerequisite_member p: group_prerequisite_members (a, t))
{
- prerequisite_member p (*i);
-
// Ignore unresolved targets that are imported from other projects.
// We are definitely not installing those.
//
@@ -181,11 +178,6 @@ namespace build2
//
if (!build2::match (a, *pt, unmatch::unchanged))
t.prerequisite_targets.push_back (pt);
-
- // Skip members of ad hoc groups. We handle them explicitly below.
- //
- if (pt->adhoc_group ())
- i.leave_group ();
}
// This is where we diverge depending on the operation. In the
diff --git a/build2/target.hxx b/build2/target.hxx
index d4def6e..847e421 100644
--- a/build2/target.hxx
+++ b/build2/target.hxx
@@ -222,8 +222,8 @@ namespace build2
//
// - Members don't have prerequisites.
//
- // - Ad hoc group cannot have sub group (of any kind) though an ad hoc
- // group can be a sub-group of a normal group.
+ // - Ad hoc group cannot have sub groups (of any kind) though an ad hoc
+ // group can be a sub group of a normal group.
//
// - Member variable lookup skips the ad hoc group (since the group is
// the first member, this is normally what we want).
@@ -919,9 +919,10 @@ namespace build2
// group_prerequisites()) as a sequence of prerequisite_member's. For each
// group prerequisite you will "see" either the prerequisite itself or all
// its members, depending on the default iteration mode of the target group
- // type (ad hoc groups are always see through). You can skip the rest of the
- // group members with leave_group() and you can force iteration over the
- // members with enter_group(). Usage:
+ // type (ad hoc groups are never implicitly see through since one can only
+ // safely access members after a synchronous match). You can skip the
+ // rest of the group members with leave_group() and you can force iteration
+ // over the members with enter_group(). Usage:
//
// for (prerequisite_member pm: prerequisite_members (a, ...))
//
@@ -942,8 +943,8 @@ namespace build2
template <typename R>
class prerequisite_members_range;
- // See-through/ad hoc group members iteration mode. Unless the mode is never,
- // ad hoc members are always iterated over.
+ // See-through group members iteration mode. Ad hoc members must always
+ // be entered explicitly.
//
enum class members_mode
{
@@ -995,7 +996,7 @@ namespace build2
// Skip iterating over the rest of this group's members, if any. Note
// that the only valid operation after this call is to increment the
- // iterator. Note that it can be used on ad hoc groups.
+ // iterator.
//
void
leave_group ();
@@ -1003,8 +1004,7 @@ namespace build2
// Iterate over this group's members. Return false if the member
// information is not available. Similar to leave_group(), you should
// increment the iterator after calling this function (provided it
- // returned true). Note that it cannot be used on ad hoc groups (which
- // will be always entered).
+ // returned true).
//
bool
enter_group ();
@@ -1046,12 +1046,6 @@ namespace build2
// hoc group (k_). Then we have iteration over a normal group (g_ and
// j_). Finally, at the outer level, we have the range itself (i_).
//
- // The ad hoc iteration is peculiar in that we only switch to this mode
- // once the caller tries to increment past the group itself (which is
- // the primary/first member). The reason for this is that the members
- // will normally only be known once the caller searched and matched
- // the group.
- //
// Also, the enter/leave group support is full of ugly, special cases.
//
private:
diff --git a/build2/target.ixx b/build2/target.ixx
index 6a754d6..a213f16 100644
--- a/build2/target.ixx
+++ b/build2/target.ixx
@@ -205,19 +205,6 @@ namespace build2
{
if (k_ != nullptr) // Iterating over an ad hoc group.
k_ = k_->member;
- else if (r_->mode_ != members_mode::never)
- {
- // Get the target if one has been resolved and see if it's an ad hoc
- // group. If so, switch to the ad hoc mode.
- //
- const target* t (
- g_.count != 0
- ? j_ != 0 ? g_.members[j_ - 1] : nullptr // enter_group()
- : i_->target.load (memory_order_consume));
-
- if (t != nullptr && t->member != nullptr)
- k_ = t->member;
- }
if (k_ == nullptr && g_.count != 0) // Iterating over a normal group.
{
@@ -243,15 +230,16 @@ namespace build2
inline bool prerequisite_members_range<T>::iterator::
enter_group ()
{
- // First see if we are about to enter an ad hoc group (the same code as in
- // operator++() above).
+ assert (k_ == nullptr); // No nested ad hoc group entering.
+
+ // First see if we are about to enter an ad hoc group.
//
const target* t (g_.count != 0
? j_ != 0 ? g_.members[j_ - 1] : nullptr
: i_->target.load (memory_order_consume));
if (t != nullptr && t->member != nullptr)
- k_ = t->member;
+ k_ = t; // Increment that follows will make it t->member.
else
{
// Otherwise assume it is a normal group.
@@ -268,7 +256,6 @@ namespace build2
j_ = 0; // Account for the increment that will follow.
}
-
return true;
}
@@ -276,18 +263,6 @@ namespace build2
inline void prerequisite_members_range<T>::iterator::
leave_group ()
{
- // First see if we are about to enter an ad hoc group (the same code as in
- // operator++() above).
- //
- if (k_ == nullptr)
- {
- const target* t (g_.count != 0
- ? j_ != 0 ? g_.members[j_ - 1] : nullptr
- : i_->target.load (memory_order_consume));
- if (t != nullptr && t->member != nullptr)
- k_ = t->member;
- }
-
if (k_ != nullptr)
{
// Skip until the last element (next increment will reach the end).