Skip to content

Semaphore

A counting semaphore can be used to limit access to a shared resource.

Basic example:

#include <semaphore>
#include <thread>

struct SomeData {} someData;
std::counting_semaphore<1> signalPrepared(0); // initially semaphore is not available, i.e. data are not yet prepared
// is same as: std::binary_semaphore s(0);

void PrepareData()
{
    // do something with someData

    // Signal that preparation is ready
    signalPrepared.release(); // => count increments to one
}

void ProcessData()
{
    // wait until data are prepared
    signalPrepared.acquire(); // blocks if count = 0; if count > 0 decrements and returns

    // do something with prepared data
}

// PrepareData and ProcessData are called from different threads
  • The max number of parallel accesses (NUM) is specified within the template param std::counting_semaphore<NUM>
  • The initial counter value is given within constructor (in example above 0)
  • To get access to the resource the client has to call acquire(). As long as the counter is greater 0 the access is granted and the call returns. If counter is 0 then no access is possible and the function blocks and waits until some other thread has released the semaphore and thus incremented the counter.
  • Instead of waiting infinitely you can use try_acquire or try_acquire_for(relTime)
  • A std::mutex is bound to a thread, a std::counting_semaphore is not bound to a thread and additionally within release member function a delta to decrement can be specified
  • for more info see https://en.cppreference.com/w/cpp/thread/counting_semaphore