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