aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2019-05-15 08:22:16 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2019-05-15 08:22:16 +0200
commit43dccfeb195d9f739ac78f6d1cd79fd16fc2cef4 (patch)
tree9043db34c32cc929c0e3aa591310c581b79537d8
parent33111a31562f364e496b8c8bba47693babecdbc0 (diff)
Redo ad hoc group member matching
-rw-r--r--build2/algorithm.cxx92
1 files changed, 38 insertions, 54 deletions
diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx
index 2e3fe83..10f1cdf 100644
--- a/build2/algorithm.cxx
+++ b/build2/algorithm.cxx
@@ -416,6 +416,44 @@ namespace build2
target& t (*l.target);
target::opstate& s (t[a]);
+ // Intercept and handle matching an ad hoc group member.
+ //
+ if (t.adhoc_member ())
+ {
+ assert (!step);
+
+ const target& g (*t.group);
+
+ // It feels natural to "convert" this call to the one for the group,
+ // including the try_match part. Semantically, we want to achieve the
+ // following:
+ //
+ // [try_]match (a, g);
+ // match_recipe (l, group_recipe);
+ //
+ auto df = make_diag_frame (
+ [a, &t](const diag_record& dr)
+ {
+ if (verb != 0)
+ dr << info << "while matching group rule to " << diag_do (a, t);
+ });
+
+ pair<bool, target_state> r (match (a, g, 0, nullptr, try_match));
+
+ if (r.first)
+ {
+ if (r.second != target_state::failed)
+ {
+ match_inc_dependens (a, g);
+ match_recipe (l, group_recipe);
+ }
+ }
+ else
+ l.offset = target::offset_tried;
+
+ return r; // Group state.
+ }
+
try
{
// Continue from where the target has been left off.
@@ -530,55 +568,6 @@ namespace build2
if (try_match && l.offset == target::offset_tried)
return make_pair (false, target_state::unknown);
- // Handle matching ad hoc group member.
- //
- if (ct.adhoc_member ())
- {
- const target& g (*ct.group);
-
- // It feels natural to "convert" this call to the one for the group,
- // including the try_match and async parts. However, that async part
- // is tricky: we will be called again to finish the match (the else-
- // block below) where we need to perform the equivalent conversion.
- // Semantically, we want to achieve the following:
- //
- // match (a, g); | match_async (a, g);
- // | match (a, g);
- // match_recipe (l, group_recipe); | match_recipe (l, group_recipe);
- //
- // We also have to "unstack" this lock to avoid racing with stack
- // modifications by the asynchronous match (see below). Since an ad
- // hoc member doesn't have any prerequisites of its own (and thus
- // cannot depend on the group), skipping this link during the cycle
- // detection feels harmless (note that the other way around is
- // possible and still works).
- //
- l.unstack ();
-
-
-#if 0 // The same story as with the lock stack. I think the only way to
- // make this work is to somehow pass the member down to match_impl().
- auto df = make_diag_frame (
- [a, &ct](const diag_record& dr)
- {
- if (verb != 0)
- dr << info << "while matching rule group to " << diag_do (a, ct);
- });
-#endif
-
- auto r (match (a, g, start_count, task_count, try_match));
-
- if (r.first)
- {
- match_inc_dependens (a, g);
- match_recipe (l, group_recipe);
- }
- else
- l.offset = target::offset_tried;
-
- return r; // Group state.
- }
-
if (task_count == nullptr)
return match_impl (l, false /* step */, try_match);
@@ -627,11 +616,6 @@ namespace build2
if (l.offset >= target::offset_busy)
return make_pair (true, target_state::busy);
- // Handle matching ad hoc group member (the finish part; see above).
- //
- if (ct.adhoc_member ())
- return match (a, *ct.group, 0, nullptr);
-
// Fall through.
}