From 58e495733d402bb4e97238ae6c8e8344eb4b2161 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Mon, 19 Sep 2022 14:17:10 +0200 Subject: Add target_lock::first to distinguish first lock of target --- libbuild2/algorithm.cxx | 16 +++++++++------- libbuild2/algorithm.hxx | 4 +++- libbuild2/algorithm.ixx | 6 +++--- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/libbuild2/algorithm.cxx b/libbuild2/algorithm.cxx index 76f7c4c..696a09d 100644 --- a/libbuild2/algorithm.cxx +++ b/libbuild2/algorithm.cxx @@ -256,7 +256,7 @@ namespace build2 fail << "dependency cycle detected involving target " << ct; if (!wq) - return target_lock {a, nullptr, e - b}; + return target_lock {a, nullptr, e - b, false}; // We also unlock the phase for the duration of the wait. Why? // Consider this scenario: we are trying to match a dir{} target whose @@ -272,7 +272,7 @@ namespace build2 // We don't lock already applied or executed targets. // if (e >= appl) - return target_lock {a, nullptr, e - b}; + return target_lock {a, nullptr, e - b, false}; } // We now have the lock. Analyze the old value and decide what to do. @@ -281,7 +281,8 @@ namespace build2 target::opstate& s (t[a]); size_t offset; - if (e <= b) + bool first; + if ((first = (e <= b))) { // First lock for this operation. // @@ -298,7 +299,7 @@ namespace build2 offset == target::offset_matched); } - return target_lock {a, &t, offset}; + return target_lock {a, &t, offset, first}; } void @@ -991,7 +992,7 @@ namespace build2 *task_count, [a, try_match] (const diag_frame* ds, const target_lock* ls, - target& t, size_t offset) + target& t, size_t offset, bool first) { // Switch to caller's diag and lock stacks. // @@ -1002,7 +1003,7 @@ namespace build2 { phase_lock pl (t.ctx, run_phase::match); // Throws. { - target_lock l {a, &t, offset}; // Reassemble. + target_lock l {a, &t, offset, first}; // Reassemble. match_impl (l, false /* step */, try_match); // Unlock within the match phase. } @@ -1012,7 +1013,8 @@ namespace build2 diag_frame::stack (), target_lock::stack (), ref (*ld.target), - ld.offset)) + ld.offset, + ld.first)) return make_pair (true, target_state::postponed); // Queued. // Matched synchronously, fall through. diff --git a/libbuild2/algorithm.hxx b/libbuild2/algorithm.hxx index b7f6809..e558d3a 100644 --- a/libbuild2/algorithm.hxx +++ b/libbuild2/algorithm.hxx @@ -191,6 +191,7 @@ namespace build2 action_type action; target_type* target = nullptr; size_t offset = 0; + bool first; explicit operator bool () const {return target != nullptr;} @@ -209,13 +210,14 @@ namespace build2 // Implementation details. // ~target_lock (); - target_lock (action_type, target_type*, size_t); + target_lock (action_type, target_type*, size_t, bool); struct data { action_type action; target_type* target; size_t offset; + bool first; }; data diff --git a/libbuild2/algorithm.ixx b/libbuild2/algorithm.ixx index 8fc5390..417a10e 100644 --- a/libbuild2/algorithm.ixx +++ b/libbuild2/algorithm.ixx @@ -220,8 +220,8 @@ namespace build2 unlock_impl (action, target&, size_t); inline target_lock:: - target_lock (action_type a, target_type* t, size_t o) - : action (a), target (t), offset (o) + target_lock (action_type a, target_type* t, size_t o, bool f) + : action (a), target (t), offset (o), first (f) { if (target != nullptr) prev = stack (this); @@ -260,7 +260,7 @@ namespace build2 inline auto target_lock:: release () -> data { - data r {action, target, offset}; + data r {action, target, offset, first}; if (target != nullptr) { -- cgit v1.1