Semaphore
A semaphore is a Sychronization primitive that controls access to a shared resource by maintaining a counter. It tracks how many "permits" are available, hands them off to threads that want access, and blocks threads when none are left.
An important distinction from mutex is that semaphore is about counting permits, not Ownership. With a mutex, the thread that locks it must also unlock it. With a semaphore, any thread can call release, even if it never called acquire. They are for signaling between threads, not just mutual exclusion.
std::counting_semaphore<BUFFER_SIZE> emptySlots{BUFFER_SIZE}; // starts full of empty slots std::counting_semaphore<BUFFER_SIZE> filledSlots{0}; // starts with nothing to consume // Producer emptySlots.acquire(); // wait for an empty slot (blocks if buffer full) buffer.push(item); filledSlots.release(); // signal that an item is available // Consumer filledSlots.acquire(); // wait for an item (blocks if buffer empty) item = buffer.pop(); emptySlots.release(); // signal that a slot freed up