From a8c082e2adf9865636c0e0a6906c6fde3a7c3e69 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 5 Jun 2017 14:56:48 +0200 Subject: Remove implicit see-through iteration over ad hoc group members This can only be done MT-safely after a synchronous match. --- build2/algorithm.hxx | 2 +- build2/install/rule.cxx | 10 +--------- build2/target.hxx | 26 ++++++++++---------------- build2/target.ixx | 33 ++++----------------------------- 4 files changed, 16 insertions(+), 55 deletions(-) (limited to 'build2') 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 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::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::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). -- cgit v1.1