+ IdleTime const& idleTimeout =
+ defaultIdleTimeout.load(std::memory_order_acquire),
+ size_t stackToRetain = kDefaultStackToRetain,
+ float timeoutVariationFrac = 0.5) {
+ FutexResult pre;
+ if (futexWaitPreIdle(
+ pre,
+ fut,
+ expected,
+ std::chrono::steady_clock::time_point::max(),
+ waitMask,
+ idleTimeout,
+ stackToRetain,
+ timeoutVariationFrac)) {
+ return pre;
+ }
+ return fut.futexWait(expected, waitMask);
+ }
+
+ /// Equivalent to fut.futexWaitUntil(expected, deadline, waitMask), but
+ /// calls flushLocalMallocCaches() and unmapUnusedStack(stackToRetain)
+ /// after idleTimeout has passed (if it has passed). Internally uses
+ /// fut.futexWaitUntil. The actual timeout will be pseudo-randomly
+ /// chosen to be between idleTimeout and idleTimeout *
+ /// (1 + timeoutVariationFraction), to smooth out the behavior in a
+ /// system with bursty requests. The default is to wait up to 50%
+ /// extra, so on average 25% extra.
+ template <
+ template <typename> class Atom,
+ typename Deadline,
+ typename IdleTime = std::chrono::steady_clock::duration>
+ static FutexResult futexWaitUntil(
+ Futex<Atom>& fut,
+ uint32_t expected,
+ Deadline const& deadline,
+ uint32_t waitMask = -1,
+ IdleTime const& idleTimeout =