diff --git a/emper/sleep_strategy/PipeSleepStrategy.hpp b/emper/sleep_strategy/PipeSleepStrategy.hpp index 6a67cf984956de3043be0660124513e0809e22bf..3a57e551e874603ac41b385da56eda1ca96ce21c 100644 --- a/emper/sleep_strategy/PipeSleepStrategy.hpp +++ b/emper/sleep_strategy/PipeSleepStrategy.hpp @@ -188,24 +188,32 @@ class PipeSleepStrategy : AbstractWorkerSleepStrategy<PipeSleepStrategy>, // by making the sleepers count negative and thus preventing at least count // sleep attempts. + int64_t newSleeping; do { // We already prevent enough sleep attempts if (sleeping <= -count) { LOGD("notifyFromAnywhere sleeper count already preventing enough sleep attempts"); return; } - } while (!sleepers.compare_exchange_weak(sleeping, sleeping - count, std::memory_order_release, + // Don't decrease the sleeper count in the CAS loop further than -count, + // which is the threshold we need to ensure that the notifications will be + // observed. + // Decreasing it further than this threshold is not faulty it just + // results in unnecessary skipped sleeps. + newSleeping = std::max(-count, sleeping - count); + } while (!sleepers.compare_exchange_weak(sleeping, newSleeping, std::memory_order_release, std::memory_order_acquire)); stats.incNotify(); - int64_t toWakeup = std::min(sleeping, count); - if (sleeping > 0) { + // To wakeup should not be negative but could be if sleeping was already negative + int64_t toWakeup = std::max(std::min(sleeping, count), 0L); + if (toWakeup > 0) { writeNotifications(hint, toWakeup); } LOGD("notifyFromAnywhere written " - << toWakeup << " notifications and set sleepers count to: " << sleeping - count); + << toWakeup << " notifications and set sleepers count to: " << newSleeping); } template <CallerEnvironment callerEnvironment>