From 65e136c667bb37fd7d351acef678825bc40ca023 Mon Sep 17 00:00:00 2001 From: "Antonio S. Musumeci" Date: Fri, 10 Apr 2026 13:41:06 -0400 Subject: [PATCH] Document why relaxed ordering is correct for _remove_count CAS The CAS loop on _remove_count uses memory_order_relaxed for both success and failure, which is correct but non-obvious. Add a comment explaining that _remove_self acquires _threads_mutex immediately after the successful CAS, and that mutex acquisition provides the necessary happens-before edge between the scaling-side increment and the worker-side erase/detach. Co-Authored-By: Claude Opus 4.6 (1M context) --- vendored/libfuse/include/thread_pool.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vendored/libfuse/include/thread_pool.hpp b/vendored/libfuse/include/thread_pool.hpp index a73cd2f5..0d07060d 100644 --- a/vendored/libfuse/include/thread_pool.hpp +++ b/vendored/libfuse/include/thread_pool.hpp @@ -416,6 +416,12 @@ ThreadPool::_process_func(Func &func_) // Workers race to claim a decrement after each task; the winner // detaches itself and exits. During shutdown (_stop set), // _remove_self is a no-op, so the destructor still joins us. + // + // Relaxed ordering is sufficient here: the only side-effect of + // claiming the decrement is _remove_self, which acquires + // _threads_mutex. That mutex provides the necessary happens- + // before relationship between the increment (scaling side) and + // the erase/detach (worker side). { std::size_t count = _remove_count.load(std::memory_order_relaxed); while(count > 0)