thread_pool: fast-path _process_func when no removal is pending

Every task completion called _try_claim_and_remove_self, which
acquires _scaling_mutex and _threads_mutex even when _remove_count
is zero (the steady-state common case).  Short tasks paid full
mutex overhead per completion.  Add a relaxed _remove_count.load
before the locks; if it reads zero, skip the claim entirely.  A stale
zero just defers the claim to a later completion on any worker,
matching the existing design where the claim is a cooperative race.
This commit is contained in:
Antonio S. Musumeci 2026-04-18 17:52:23 -04:00
parent f7a9fbd0cf
commit 0f319ee93c

View file

@ -546,7 +546,13 @@ ThreadPool::_process_func(Func &func_)
// prevent the TOCTOU race with set_threads. During shutdown
// (_stop set), _try_claim_and_remove_self returns false, so
// the destructor still joins us.
if(_try_claim_and_remove_self(pthread_self()))
//
// Fast path: most tasks complete with no shrink pending, so avoid
// the double-lock acquisition in _try_claim_and_remove_self unless
// _remove_count looks non-zero. A stale zero read just defers the
// claim by one task — a later completion on any worker picks it up.
if(_remove_count.load(std::memory_order_relaxed) != 0 &&
_try_claim_and_remove_self(pthread_self()))
return EXIT;
return CONTINUE;