[thread.sema.cnt]

# 32 Concurrency support library [[thread]](./#thread)

## 32.8 Semaphore [[thread.sema]](thread.sema#cnt)

### 32.8.3 Class template counting_semaphore [thread.sema.cnt]

namespace std {template<ptrdiff_t least_max_value = *implementation-defined*>class counting_semaphore {public:static constexpr ptrdiff_t max() noexcept; constexpr explicit counting_semaphore(ptrdiff_t desired); ~counting_semaphore();

 counting_semaphore(const counting_semaphore&) = delete;
 counting_semaphore& operator=(const counting_semaphore&) = delete; void release(ptrdiff_t update = 1); void acquire(); bool try_acquire() noexcept; template<class Rep, class Period>bool try_acquire_for(const chrono::duration<Rep, Period>& rel_time); template<class Clock, class Duration>bool try_acquire_until(const chrono::time_point<Clock, Duration>& abs_time); private: ptrdiff_t counter; // *exposition only*};}

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10490)

Class template counting_semaphore maintains an internal counter
that is initialized when the semaphore is created[.](#1.sentence-1)

The counter is decremented when a thread acquires the semaphore, and
is incremented when a thread releases the semaphore[.](#1.sentence-2)

If a thread tries to acquire the semaphore when the counter is zero,
the thread will block
until another thread increments the counter by releasing the semaphore[.](#1.sentence-3)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10500)

least_max_value shall be non-negative; otherwise the program is ill-formed[.](#2.sentence-1)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10503)

Concurrent invocations of the member functions of counting_semaphore,
other than its destructor, do not introduce data races[.](#3.sentence-1)

[ð](#lib:max,counting_semaphore)

`static constexpr ptrdiff_t max() noexcept;
`

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10513)

*Returns*: The maximum value of counter[.](#4.sentence-1)

This value is greater than or equal to least_max_value[.](#4.sentence-2)

[ð](#lib:counting_semaphore,constructor)

`constexpr explicit counting_semaphore(ptrdiff_t desired);
`

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10525)

*Preconditions*: desired >= 0 is true, anddesired <= max() is true[.](#5.sentence-1)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10530)

*Effects*: Initializes counter with desired[.](#6.sentence-1)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10534)

*Throws*: Nothing[.](#7.sentence-1)

[ð](#lib:release,counting_semaphore)

`void release(ptrdiff_t update = 1);
`

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10545)

*Preconditions*: update >= 0 is true, andupdate <= max() - counter is true[.](#8.sentence-1)

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10550)

*Effects*: Atomically execute counter += update[.](#9.sentence-1)

Then, unblocks any threads
that are waiting for counter to be greater than zero[.](#9.sentence-2)

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10556)

*Synchronization*: Strongly happens before invocations of try_acquire that observe the result of the effects[.](#10.sentence-1)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10561)

*Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#11.sentence-1)

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10565)

*Error conditions*: Any of the error conditions
allowed for mutex types ([[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2 Mutex types"))[.](#12.sentence-1)

[ð](#lib:try_acquire,counting_semaphore)

`bool try_acquire() noexcept;
`

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10577)

*Effects*: Attempts to atomically decrement counter if it is positive,
without blocking[.](#13.sentence-1)

If counter is not decremented, there is no effect andtry_acquire immediately returns[.](#13.sentence-2)

An implementation may fail to decrement counter even if it is positive[.](#13.sentence-3)

[*Note [1](#note-1)*:

This spurious failure is normally uncommon, but
allows interesting implementations
based on a simple compare and exchange ([[atomics]](atomics "32.5 Atomic operations"))[.](#13.sentence-4)

â *end note*]

An implementation should ensure that try_acquire does not consistently return false in the absence of contending semaphore operations[.](#13.sentence-5)

[14](#14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10594)

*Returns*: true if counter was decremented, otherwise false[.](#14.sentence-1)

[ð](#lib:acquire,counting_semaphore)

`void acquire();
`

[15](#15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10605)

*Effects*: Repeatedly performs the following steps, in order:

- [(15.1)](#15.1)

  Evaluates try_acquire()[.](#15.1.sentence-1)
  If the result is true, returns[.](#15.1.sentence-2)

- [(15.2)](#15.2)

  Blocks on *this until counter is greater than zero[.](#15.2.sentence-1)

[16](#16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10615)

*Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#16.sentence-1)

[17](#17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10619)

*Error conditions*: Any of the error conditions
allowed for mutex types ([[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2 Mutex types"))[.](#17.sentence-1)

[ð](#lib:try_acquire_for,counting_semaphore)

`template<class Rep, class Period>
  bool try_acquire_for(const chrono::duration<Rep, Period>& rel_time);
template<class Clock, class Duration>
  bool try_acquire_until(const chrono::time_point<Clock, Duration>& abs_time);
`

[18](#18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10635)

*Effects*: Repeatedly performs the following steps, in order:

- [(18.1)](#18.1)

  Evaluates try_acquire()[.](#18.1.sentence-1)
  If the result is true, returns true[.](#18.1.sentence-2)

- [(18.2)](#18.2)

   Blocks on *this until counter is greater than zero or until the timeout expires[.](#18.2.sentence-1)
  If it is unblocked by the timeout expiring, returns false[.](#18.2.sentence-2)

The timeout expires ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications"))
when the current time is after abs_time (for try_acquire_until)
or when at least rel_time has passed
from the start of the function (for try_acquire_for)[.](#18.sentence-2)

[19](#19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10653)

*Throws*: Timeout-related exceptions ([[thread.req.timing]](thread.req.timing "32.2.4 Timing specifications")), or system_error when a non-timeout-related exception is required ([[thread.req.exception]](thread.req.exception "32.2.2 Exceptions"))[.](#19.sentence-1)

[20](#20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10658)

*Error conditions*: Any of the error conditions
allowed for mutex types ([[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2 Mutex types"))[.](#20.sentence-1)
