diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2019-05-15 08:22:16 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2019-05-15 08:22:16 +0200 |
commit | 43dccfeb195d9f739ac78f6d1cd79fd16fc2cef4 (patch) | |
tree | 9043db34c32cc929c0e3aa591310c581b79537d8 | |
parent | 33111a31562f364e496b8c8bba47693babecdbc0 (diff) |
Redo ad hoc group member matching
-rw-r--r-- | build2/algorithm.cxx | 92 |
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. } |