This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

221
cppdraft/thread/sema/cnt.md Normal file
View File

@@ -0,0 +1,221 @@
[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.2Exceptions"))[.](#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.2Mutex 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.5Atomic 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.2Exceptions"))[.](#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.2Mutex 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.4Timing 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.4Timing specifications")), or system_error when a non-timeout-related exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#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.2Mutex types"))[.](#20.sentence-1)

View File

@@ -0,0 +1,29 @@
[thread.sema.general]
# 32 Concurrency support library [[thread]](./#thread)
## 32.8 Semaphore [[thread.sema]](thread.sema#general)
### 32.8.1 General [thread.sema.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10435)
Semaphores are lightweight synchronization primitives
used to constrain concurrent access to a shared resource[.](#1.sentence-1)
They are widely used to implement other synchronization primitives and,
whenever both are applicable, can be more efficient than condition variables[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10441)
A counting semaphore is a semaphore object
that models a non-negative resource count[.](#2.sentence-1)
A binary semaphore is a semaphore object that has only two states[.](#2.sentence-2)
A binary semaphore should be more efficient than
the default implementation of a counting semaphore with a unit resource count[.](#2.sentence-3)