aboutsummaryrefslogtreecommitdiff
path: root/libbuild2
diff options
context:
space:
mode:
Diffstat (limited to 'libbuild2')
-rw-r--r--libbuild2/operation.cxx70
-rw-r--r--libbuild2/scheduler.cxx4
-rw-r--r--libbuild2/scheduler.hxx34
-rw-r--r--libbuild2/scheduler.txx9
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;
}
}