diff options
-rw-r--r-- | libbuild2/operation.cxx | 70 | ||||
-rw-r--r-- | libbuild2/scheduler.cxx | 4 | ||||
-rw-r--r-- | libbuild2/scheduler.hxx | 34 | ||||
-rw-r--r-- | libbuild2/scheduler.txx | 9 |
4 files changed, 74 insertions, 43 deletions
diff --git a/libbuild2/operation.cxx b/libbuild2/operation.cxx index 6f88e38..d7b5b92 100644 --- a/libbuild2/operation.cxx +++ b/libbuild2/operation.cxx @@ -271,9 +271,12 @@ namespace build2 struct monitor_data { size_t incr; - string what; - atomic<timestamp::rep> time {timestamp_nonexistent_rep}; + string what1; + string what2; + size_t exec = 0; // Number of targets executed during match. + timestamp time = timestamp_nonexistent; } md; // Note: must outlive monitor_guard. + scheduler::monitor_guard mg; if (prog && show_progress (2 /* max_verb */)) @@ -282,36 +285,53 @@ namespace build2 // the up-to-date check on some projects (e.g., Boost). So we jump // through a few hoops to make sure we don't overindulge. // + // Note also that the higher the increment, the less accurate our + // executed during match number will be. + // md.incr = stderr_term // Scale depending on output type. ? (ctx.sched->serial () ? 1 : 5) : 100; - md.what = " targets to " + diag_do (ctx, a); + md.what1 = " targets to " + diag_do (ctx, a); + md.what2 = ' ' + diag_did (ctx, a) + " during match)"; mg = ctx.sched->monitor ( ctx.target_count, md.incr, - [&md] (size_t c) -> size_t + [&md, &ctx] (size_t p, size_t c) -> size_t { - size_t r (c + md.incr); + if (p > c) + md.exec += p - c; if (stderr_term) { - timestamp o (duration (md.time.load (memory_order_consume))); timestamp n (system_clock::now ()); - if (n - o < chrono::milliseconds (80)) - return r; + if (n - md.time < chrono::milliseconds (80)) + return md.incr; - md.time.store (n.time_since_epoch ().count (), - memory_order_release); + md.time = n; } diag_progress_lock pl; diag_progress = ' '; diag_progress += to_string (c); - diag_progress += md.what; + diag_progress += md.what1; + + if (md.exec != 0) + { + // Offset by the number of targets skipped. + // + size_t s (ctx.skip_count.load (memory_order_relaxed)); + + if (md.exec > s) + { + diag_progress += " ("; + diag_progress += to_string (md.exec - s); + diag_progress += md.what2; + } + } - return r; + return md.incr; }); } @@ -612,30 +632,36 @@ namespace build2 // Setup progress reporting if requested. // - string what; // Note: must outlive monitor_guard. + struct monitor_data + { + size_t init; + size_t incr; + string what; + } md; // Note: must outlive monitor_guard. + scheduler::monitor_guard mg; if (prog && show_progress (1 /* max_verb */)) { - size_t init (ctx.target_count.load (memory_order_relaxed)); - size_t incr (init > 100 ? init / 100 : 1); // 1%. + md.init = ctx.target_count.load (memory_order_relaxed); + md.incr = md.init > 100 ? md.init / 100 : 1; // 1%. - if (init != incr) + if (md.init != md.incr) { - what = "% of targets " + diag_did (ctx, a); + md.what = "% of targets " + diag_did (ctx, a); mg = ctx.sched->monitor ( ctx.target_count, - init - incr, - [init, incr, &what, &ctx] (size_t c) -> size_t + md.incr, + [&md, &ctx] (size_t, size_t c) -> size_t { - size_t p ((init - c) * 100 / init); + size_t p ((md.init - c) * 100 / md.init); size_t s (ctx.skip_count.load (memory_order_relaxed)); diag_progress_lock pl; diag_progress = ' '; diag_progress += to_string (p); - diag_progress += what; + diag_progress += md.what; if (s != 0) { @@ -644,7 +670,7 @@ namespace build2 diag_progress += " skipped)"; } - return c - incr; + return md.incr; }); } } diff --git a/libbuild2/scheduler.cxx b/libbuild2/scheduler.cxx index 69673e6..ebb38e4 100644 --- a/libbuild2/scheduler.cxx +++ b/libbuild2/scheduler.cxx @@ -701,7 +701,7 @@ namespace build2 } scheduler::monitor_guard scheduler:: - monitor (atomic_count& c, size_t t, function<size_t (size_t)> f) + monitor (atomic_count& c, size_t t, function<size_t (size_t, size_t)> f) { assert (monitor_count_ == nullptr && t != 0); @@ -713,7 +713,7 @@ namespace build2 monitor_count_ = &c; monitor_tshold_.store (t, memory_order_relaxed); - monitor_init_ = c.load (memory_order_relaxed); + monitor_prev_ = c.load (memory_order_relaxed); monitor_func_ = move (f); return monitor_guard (this); diff --git a/libbuild2/scheduler.hxx b/libbuild2/scheduler.hxx index 3cc206e..2d4d189 100644 --- a/libbuild2/scheduler.hxx +++ b/libbuild2/scheduler.hxx @@ -452,9 +452,11 @@ namespace build2 // should be set before any tasks are queued and cleared after all of // them have completed. // - // The counter must go in one direction, either increasing or decreasing, - // and should contain the initial value during the call. Zero threshold - // value is reserved. + // The counter can go in either direction and should contain the initial + // value during the call. The callback function is called when the current + // value differs form the previous/initial by at least the specified + // threshold. The callback returns the new threshold. Zero threshold value + // is reserved. The callback calls are serialized and synchronized. // struct monitor_guard { @@ -488,7 +490,9 @@ namespace build2 }; monitor_guard - monitor (atomic_count&, size_t threshold, function<size_t (size_t)>); + monitor (atomic_count&, + size_t threshold, + function<size_t (size_t previous, size_t current)>); // If initially active thread(s) (besides the one that calls startup()) // exist before the call to startup(), then they must call join() before @@ -598,10 +602,10 @@ namespace build2 // Monitor. // - atomic_count* monitor_count_ = nullptr; // NULL if not used. - atomic_count monitor_tshold_; // 0 means locked. - size_t monitor_init_; // Initial count. - function<size_t (size_t)> monitor_func_; + atomic_count* monitor_count_ = nullptr; // NULL if not used. + atomic_count monitor_tshold_; // 0 means locked. + size_t monitor_prev_; // Previous values. + function<size_t (size_t, size_t)> monitor_func_; build2::mutex mutex_; bool shutdown_ = true; // Shutdown flag. @@ -914,19 +918,19 @@ namespace build2 if (monitor_tshold_.compare_exchange_strong ( t, 0, - memory_order_release, + memory_order_acq_rel, // Synchronize on success. memory_order_relaxed)) { - // Now we are the only ones messing with this. + // Now we are the only ones messing with this and everything + // is synchronized. // + size_t p (monitor_prev_); size_t v (monitor_count_->load (memory_order_relaxed)); - if (v != monitor_init_) + if ((p > v ? p - v : p < v ? v - p : 0) >= t) { - // See which direction we are going. - // - if (v > monitor_init_ ? (v >= t) : (v <= t)) - t = monitor_func_ (v); + t = monitor_func_ (p, v); + monitor_prev_= v; } monitor_tshold_.store (t, memory_order_release); diff --git a/libbuild2/scheduler.txx b/libbuild2/scheduler.txx index 87c9384..15fefcc 100644 --- a/libbuild2/scheduler.txx +++ b/libbuild2/scheduler.txx @@ -29,12 +29,13 @@ namespace build2 // if (monitor_count_ != nullptr) { + size_t t (monitor_tshold_.load (memory_order_relaxed)); + size_t p (monitor_prev_); size_t v (monitor_count_->load (memory_order_relaxed)); - if (v != monitor_init_) + if ((p > v ? p - v : p < v ? v - p : 0) >= t) { - size_t t (monitor_tshold_.load (memory_order_relaxed)); - if (v > monitor_init_ ? (v >= t) : (v <= t)) - monitor_tshold_.store (monitor_func_ (v), memory_order_relaxed); + monitor_tshold_.store (monitor_func_ (p, v), memory_order_relaxed); + monitor_prev_ = v; } } |