Load completed before enqueued in tasks_pending to bias low

The previous ordering (enqueued first, then completed) meant a
task completing between the two loads would inflate the pending
count.  For scaling heuristics, over-reporting pressure is worse
than under-reporting: it can trigger unnecessary thread creation.

Swap the load order so completed is read first.  A completion
between the two loads now reduces the delta toward zero, which
is the safer direction for autoscale decisions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Antonio S. Musumeci 2026-04-10 12:06:51 -04:00
parent 80af7ffcc0
commit ec024b246a

View file

@ -1067,14 +1067,16 @@ ThreadPool::tasks_completed() const
}
// Approximate: the two counters are loaded non-atomically with
// relaxed ordering, so the result may momentarily read zero (or
// a lower value) while tasks complete between the two loads.
// relaxed ordering. Loading completed first biases the result
// toward zero (a completion between the two loads lowers the
// delta), which is safer for scaling heuristics than over-
// reporting pressure.
// Suitable for monitoring and heuristics, not for synchronization.
inline
std::uint64_t
ThreadPool::tasks_pending() const
{
auto e = _tasks_enqueued.load(std::memory_order_relaxed);
auto c = _tasks_completed.load(std::memory_order_relaxed);
auto e = _tasks_enqueued.load(std::memory_order_relaxed);
return (e > c) ? (e - c) : 0;
}