folly::SaturatingSemaphore

SaturatingSemaphore is a flag that allows concurrent posting by multiple posters and concurrent non-destructive waiting by multiple waiters.

Synopsis

Declared in <folly/synchronization/SaturatingSemaphore.h>

template<
    bool MayBlock = true,
    template<typename> typename Atom = atomic>
class SaturatingSemaphore;

Description

A SaturatingSemaphore allows one or more waiter threads to check, spin, or block, indefinitely or with timeout, for a flag to be set by one or more poster threads. By setting the flag, posters announce to waiters (that may be already waiting or will check the flag in the future) that some condition is true. Posts to an already set flag are idempotent.

SaturatingSemaphore is called so because it behaves like a hybrid binary/counted semaphore with values zero and infinity, and post() and wait() functions. It is called saturating because one post() is enough to set it to infinity and to satisfy any number of wait()-s. Once set (to infinity) it remains unchanged by subsequent post()-s and wait()-s, until it is reset() back to zero.

The implementation of SaturatingSemaphore is based on that of Baton. It includes no internal padding, and is only 4 bytes in size. Any alignment or padding to avoid false sharing is up to the user. SaturatingSemaphore differs from Baton as follows:

  • Baton allows at most one call to post(); this allows any number and concurrently.

  • Baton allows at most one successful call to any wait variant; this allows any number and concurrently.

Template parameter:

  • bool MayBlock: If false, waiting operations spin only. If true, timed and wait operations may block; adds an atomic instruction to the critical path of posters.

Wait options: WaitOptions contains optional per call setting for spin-max duration: Calls to wait(), try_wait_until(), and try_wait_for() block only after the passage of the spin-max period. The default spin-max duration is 10 usec. The spin-max option is applicable only if MayBlock is true.

Functions: bool ready(): Returns true if the flag is set by a call to post, otherwise false. Equivalent to try_wait, but available on const receivers. void reset(); Clears the flag. void post(); Sets the flag and wakes all current waiters, i.e., causes all concurrent calls to wait, try_wait_for, and try_wait_until to return. void wait( WaitOptions opt = wait_options()); Waits for the flag to be set by a call to post. bool try_wait(); Returns true if the flag is set by a call to post, otherwise false. bool try_wait_until( time_point& deadline, WaitOptions& = wait_options()); Returns true if the flag is set by a call to post before the deadline, otherwise false. bool try_wait_for( duration&, WaitOptions& = wait_options()); Returns true if the flag is set by a call to post before the expiration of the specified duration, otherwise false.

Usage:


SaturatingSemaphore<> f;
ASSERT_FALSE(f.try_wait());
ASSERT_FALSE(f.try_wait_until(
    std::chrono::steady_clock::now() + std::chrono::microseconds(1)));
ASSERT_FALSE(f.try_wait_until(
    std::chrono::steady_clock::now() + std::chrono::microseconds(1),
    f.wait_options().spin_max(std::chrono::microseconds(1))));
f.post();
f.post();
f.wait();
f.wait(f.wait_options().spin_max(std::chrono::nanoseconds(100)));
ASSERT_TRUE(f.try_wait());
ASSERT_TRUE(f.try_wait_until(
    std::chrono::steady_clock::now() + std::chrono::microseconds(1)));
f.wait();
f.reset();
ASSERT_FALSE(f.try_wait());

Member Functions

NameDescription
SaturatingSemaphore [constructor]constructor
~SaturatingSemaphore [destructor]destructor
post post
ready Checks whether the semaphore has been posted.
reset reset
try_wait Checks readiness without blocking.
try_wait_for Waits until the semaphore is ready or the timeout elapses.
try_wait_until Waits until the semaphore is ready or the deadline expires.
wait Blocks until the semaphore becomes ready.

Static Member Functions

NameDescription
wait_options Returns the default wait options used by the blocking calls.