From ec024b246aae9963f2e623e39e3865dec0446453 Mon Sep 17 00:00:00 2001 From: "Antonio S. Musumeci" Date: Fri, 10 Apr 2026 12:06:51 -0400 Subject: [PATCH] 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) --- vendored/libfuse/include/thread_pool.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vendored/libfuse/include/thread_pool.hpp b/vendored/libfuse/include/thread_pool.hpp index 92a66648..790f5308 100644 --- a/vendored/libfuse/include/thread_pool.hpp +++ b/vendored/libfuse/include/thread_pool.hpp @@ -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; }