Files
2025-10-25 03:02:53 +03:00

518 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[thread.coord]
# 32 Concurrency support library [[thread]](./#thread)
## 32.9 Coordination types [thread.coord]
### [32.9.1](#general) General [[thread.coord.general]](thread.coord.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10668)
Subclause [thread.coord] describes various concepts related to thread coordination, and
defines the coordination types latch and barrier[.](#general-1.sentence-1)
These types facilitate concurrent computation performed by a number of threads[.](#general-1.sentence-2)
### [32.9.2](#thread.latch) Latches [[thread.latch]](thread.latch)
#### [32.9.2.1](#thread.latch.general) General [[thread.latch.general]](thread.latch.general)
[1](#thread.latch.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10677)
A latch is a thread coordination mechanism
that allows any number of threads to block
until an expected number of threads arrive at the latch
(via the count_down function)[.](#thread.latch.general-1.sentence-1)
The expected count is set when the latch is created[.](#thread.latch.general-1.sentence-2)
An individual latch is a single-use object;
once the expected count has been reached, the latch cannot be reused[.](#thread.latch.general-1.sentence-3)
#### [32.9.2.2](#latch.syn) Header <latch> synopsis [[latch.syn]](latch.syn)
[🔗](#header:%3clatch%3e)
namespace std {class latch;}
#### [32.9.2.3](#thread.latch.class) Class latch [[thread.latch.class]](thread.latch.class)
namespace std {class latch {public:static constexpr ptrdiff_t max() noexcept; constexpr explicit latch(ptrdiff_t expected); ~latch();
latch(const latch&) = delete;
latch& operator=(const latch&) = delete; void count_down(ptrdiff_t update = 1); bool try_wait() const noexcept; void wait() const; void arrive_and_wait(ptrdiff_t update = 1); private: ptrdiff_t counter; // *exposition only*};}
[1](#thread.latch.class-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10720)
A latch maintains an internal counter
that is initialized when the latch is created[.](#thread.latch.class-1.sentence-1)
Threads can block on the latch object,
waiting for counter to be decremented to zero[.](#thread.latch.class-1.sentence-2)
[2](#thread.latch.class-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10726)
Concurrent invocations of the member functions of latch,
other than its destructor, do not introduce data races[.](#thread.latch.class-2.sentence-1)
[🔗](#lib:max,latch)
`static constexpr ptrdiff_t max() noexcept;
`
[3](#thread.latch.class-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10736)
*Returns*: The maximum value of counter that the implementation supports[.](#thread.latch.class-3.sentence-1)
[🔗](#lib:latch,constructor)
`constexpr explicit latch(ptrdiff_t expected);
`
[4](#thread.latch.class-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10747)
*Preconditions*: expected >= 0 is true andexpected <= max() is true[.](#thread.latch.class-4.sentence-1)
[5](#thread.latch.class-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10752)
*Effects*: Initializes counter with expected[.](#thread.latch.class-5.sentence-1)
[6](#thread.latch.class-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10756)
*Throws*: Nothing[.](#thread.latch.class-6.sentence-1)
[🔗](#lib:count_down,latch)
`void count_down(ptrdiff_t update = 1);
`
[7](#thread.latch.class-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10767)
*Preconditions*: update >= 0 is true, andupdate <= counter is true[.](#thread.latch.class-7.sentence-1)
[8](#thread.latch.class-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10772)
*Effects*: Atomically decrements counter by update[.](#thread.latch.class-8.sentence-1)
If counter is equal to zero,
unblocks all threads blocked on *this[.](#thread.latch.class-8.sentence-2)
[9](#thread.latch.class-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10778)
*Synchronization*: Strongly happens before the returns from all calls that are unblocked[.](#thread.latch.class-9.sentence-1)
[10](#thread.latch.class-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10782)
*Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#thread.latch.class-10.sentence-1)
[11](#thread.latch.class-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10786)
*Error conditions*: Any of the error conditions
allowed for mutex types ([[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2Mutex types"))[.](#thread.latch.class-11.sentence-1)
[🔗](#lib:try_wait,latch)
`bool try_wait() const noexcept;
`
[12](#thread.latch.class-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10798)
*Returns*: With very low probability false[.](#thread.latch.class-12.sentence-1)
Otherwise counter == 0[.](#thread.latch.class-12.sentence-2)
[🔗](#lib:wait,latch)
`void wait() const;
`
[13](#thread.latch.class-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10809)
*Effects*: If counter equals zero, returns immediately[.](#thread.latch.class-13.sentence-1)
Otherwise, blocks on *this until a call to count_down that decrements counter to zero[.](#thread.latch.class-13.sentence-2)
[14](#thread.latch.class-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10816)
*Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#thread.latch.class-14.sentence-1)
[15](#thread.latch.class-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10820)
*Error conditions*: Any of the error conditions
allowed for mutex types ([[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2Mutex types"))[.](#thread.latch.class-15.sentence-1)
[🔗](#lib:arrive_and_wait,latch)
`void arrive_and_wait(ptrdiff_t update = 1);
`
[16](#thread.latch.class-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10832)
*Effects*: Equivalent to:count_down(update);
wait();
### [32.9.3](#thread.barrier) Barriers [[thread.barrier]](thread.barrier)
#### [32.9.3.1](#thread.barrier.general) General [[thread.barrier.general]](thread.barrier.general)
[1](#thread.barrier.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10845)
A barrier is a thread coordination mechanism
whose lifetime consists of a sequence of barrier phases,
where each phase allows at most an expected number of threads to block
until the expected number of threads arrive at the barrier[.](#thread.barrier.general-1.sentence-1)
[*Note [1](#thread.barrier.general-note-1)*:
A barrier is useful for managing repeated tasks
that are handled by multiple threads[.](#thread.barrier.general-1.sentence-2)
— *end note*]
#### [32.9.3.2](#barrier.syn) Header <barrier> synopsis [[barrier.syn]](barrier.syn)
[🔗](#header:%3cbarrier%3e)
namespace std {template<class CompletionFunction = *see below*>class barrier;}
#### [32.9.3.3](#thread.barrier.class) Class template barrier [[thread.barrier.class]](thread.barrier.class)
namespace std {template<class CompletionFunction = *see below*>class barrier {public:using arrival_token = *see below*; static constexpr ptrdiff_t max() noexcept; constexpr explicit barrier(ptrdiff_t expected,
CompletionFunction f = CompletionFunction()); ~barrier();
barrier(const barrier&) = delete;
barrier& operator=(const barrier&) = delete;
arrival_token arrive(ptrdiff_t update = 1); void wait(arrival_token&& arrival) const; void arrive_and_wait(); void arrive_and_drop(); private: CompletionFunction completion; // *exposition only*};}
[1](#thread.barrier.class-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10895)
Each [*barrier phase*](#def:barrier_phase "32.9.3.3Class template barrier[thread.barrier.class]") consists of the following steps:
- [(1.1)](#thread.barrier.class-1.1)
The expected count is decremented
by each call to arrive or arrive_and_drop[.](#thread.barrier.class-1.1.sentence-1)
- [(1.2)](#thread.barrier.class-1.2)
Exactly once after the expected count reaches zero, a thread
executes the completion step during its call
to arrive, arrive_and_drop, or wait,
except that it is implementation-defined
whether the step executes if no thread calls wait[.](#thread.barrier.class-1.2.sentence-1)
- [(1.3)](#thread.barrier.class-1.3)
When the completion step finishes,
the expected count is reset
to what was specified by the expected argument to the constructor,
possibly adjusted by calls to arrive_and_drop, and
the next phase starts[.](#thread.barrier.class-1.3.sentence-1)
[2](#thread.barrier.class-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10916)
Each phase defines a [*phase synchronization point*](#def:barrier,phase_synchronization_point "32.9.3.3Class template barrier[thread.barrier.class]")[.](#thread.barrier.class-2.sentence-1)
Threads that arrive at the barrier during the phase
can block on the phase synchronization point by calling wait, and
will remain blocked until the phase completion step is run[.](#thread.barrier.class-2.sentence-2)
[3](#thread.barrier.class-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10923)
The [*phase completion step*](#def:phase_completion_step "32.9.3.3Class template barrier[thread.barrier.class]") that is executed at the end of each phase has the following effects:
- [(3.1)](#thread.barrier.class-3.1)
Invokes the completion function, equivalent to completion()[.](#thread.barrier.class-3.1.sentence-1)
- [(3.2)](#thread.barrier.class-3.2)
Unblocks all threads that are blocked on the phase synchronization point[.](#thread.barrier.class-3.2.sentence-1)
The end of the completion step strongly happens before
the returns from all calls that were unblocked by the completion step[.](#thread.barrier.class-3.sentence-2)
For specializations that do not have
the default value of the CompletionFunction template parameter,
the behavior is undefined if any of the barrier object's member functions
other than wait are called while the completion step is in progress[.](#thread.barrier.class-3.sentence-3)
[4](#thread.barrier.class-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10937)
Concurrent invocations of the member functions of barrier,
other than its destructor, do not introduce data races[.](#thread.barrier.class-4.sentence-1)
The member functions arrive and arrive_and_drop execute atomically[.](#thread.barrier.class-4.sentence-2)
[5](#thread.barrier.class-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10943)
CompletionFunction shall meet the[*Cpp17MoveConstructible*](utility.arg.requirements#:Cpp17MoveConstructible "16.4.4.2Template argument requirements[utility.arg.requirements]") (Table [31](utility.arg.requirements#tab:cpp17.moveconstructible "Table 31: Cpp17MoveConstructible requirements")) and[*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2Template argument requirements[utility.arg.requirements]") (Table [35](utility.arg.requirements#tab:cpp17.destructible "Table 35: Cpp17Destructible requirements")) requirements[.](#thread.barrier.class-5.sentence-1)
is_nothrow_invocable_v<CompletionFunction&> shall be true[.](#thread.barrier.class-5.sentence-2)
[6](#thread.barrier.class-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10949)
The default value of the CompletionFunction template parameter is
an unspecified type, such that,
in addition to satisfying the requirements of CompletionFunction,
it meets the [*Cpp17DefaultConstructible*](utility.arg.requirements#:Cpp17DefaultConstructible "16.4.4.2Template argument requirements[utility.arg.requirements]") requirements (Table [30](utility.arg.requirements#tab:cpp17.defaultconstructible "Table 30: Cpp17DefaultConstructible requirements")) andcompletion() has no effects[.](#thread.barrier.class-6.sentence-1)
[7](#thread.barrier.class-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10957)
barrier::arrival_token is an unspecified type,
such that it meets the[*Cpp17MoveConstructible*](utility.arg.requirements#:Cpp17MoveConstructible "16.4.4.2Template argument requirements[utility.arg.requirements]") (Table [31](utility.arg.requirements#tab:cpp17.moveconstructible "Table 31: Cpp17MoveConstructible requirements")),[*Cpp17MoveAssignable*](utility.arg.requirements#:Cpp17MoveAssignable "16.4.4.2Template argument requirements[utility.arg.requirements]") (Table [33](utility.arg.requirements#tab:cpp17.moveassignable "Table 33: Cpp17MoveAssignable requirements")), and[*Cpp17Destructible*](utility.arg.requirements#:Cpp17Destructible "16.4.4.2Template argument requirements[utility.arg.requirements]") (Table [35](utility.arg.requirements#tab:cpp17.destructible "Table 35: Cpp17Destructible requirements")) requirements[.](#thread.barrier.class-7.sentence-1)
[🔗](#lib:max,barrier)
`static constexpr ptrdiff_t max() noexcept;
`
[8](#thread.barrier.class-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10970)
*Returns*: The maximum expected count that the implementation supports[.](#thread.barrier.class-8.sentence-1)
[🔗](#lib:barrier,constructor)
`constexpr explicit barrier(ptrdiff_t expected,
CompletionFunction f = CompletionFunction());
`
[9](#thread.barrier.class-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10982)
*Preconditions*: expected >= 0 is true andexpected <= max() is true[.](#thread.barrier.class-9.sentence-1)
[10](#thread.barrier.class-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10987)
*Effects*: Sets both the initial expected count for each barrier phase and
the current expected count for the first phase to expected[.](#thread.barrier.class-10.sentence-1)
Initializes completion with std::move(f)[.](#thread.barrier.class-10.sentence-2)
Starts the first phase[.](#thread.barrier.class-10.sentence-3)
[*Note [1](#thread.barrier.class-note-1)*:
If expected is 0 this object can only be destroyed[.](#thread.barrier.class-10.sentence-4)
— *end note*]
[11](#thread.barrier.class-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10997)
*Throws*: Any exception thrown by CompletionFunction's move constructor[.](#thread.barrier.class-11.sentence-1)
[🔗](#lib:arrive,barrier)
`arrival_token arrive(ptrdiff_t update = 1);
`
[12](#thread.barrier.class-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11008)
*Preconditions*: update > 0 is true, andupdate is less than or equal to
the expected count for the current barrier phase[.](#thread.barrier.class-12.sentence-1)
[13](#thread.barrier.class-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11014)
*Effects*: Constructs an object of type arrival_token that is associated with the phase synchronization point for the current phase[.](#thread.barrier.class-13.sentence-1)
Then, decrements the expected count by update[.](#thread.barrier.class-13.sentence-2)
[14](#thread.barrier.class-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11020)
*Synchronization*: The call to arrive strongly happens before
the start of the phase completion step for the current phase[.](#thread.barrier.class-14.sentence-1)
[15](#thread.barrier.class-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11025)
*Returns*: The constructed arrival_token object[.](#thread.barrier.class-15.sentence-1)
[16](#thread.barrier.class-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11029)
*Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#thread.barrier.class-16.sentence-1)
[17](#thread.barrier.class-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11033)
*Error conditions*: Any of the error conditions
allowed for mutex types ([[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2Mutex types"))[.](#thread.barrier.class-17.sentence-1)
[18](#thread.barrier.class-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11038)
[*Note [2](#thread.barrier.class-note-2)*:
This call can cause the completion step for the current phase to start[.](#thread.barrier.class-18.sentence-1)
— *end note*]
[🔗](#lib:wait,barrier)
`void wait(arrival_token&& arrival) const;
`
[19](#thread.barrier.class-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11050)
*Preconditions*: arrival is associated with
the phase synchronization point for the current phase or
the immediately preceding phase of the same barrier object[.](#thread.barrier.class-19.sentence-1)
[20](#thread.barrier.class-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11056)
*Effects*: Blocks at the synchronization point associated with std::move(arrival) until the phase completion step of the synchronization point's phase is run[.](#thread.barrier.class-20.sentence-1)
[*Note [3](#thread.barrier.class-note-3)*:
If arrival is associated with the synchronization point
for a previous phase, the call returns immediately[.](#thread.barrier.class-20.sentence-2)
— *end note*]
[21](#thread.barrier.class-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11066)
*Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#thread.barrier.class-21.sentence-1)
[22](#thread.barrier.class-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11070)
*Error conditions*: Any of the error conditions
allowed for mutex types ([[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2Mutex types"))[.](#thread.barrier.class-22.sentence-1)
[🔗](#lib:arrive_and_wait,barrier)
`void arrive_and_wait();
`
[23](#thread.barrier.class-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11082)
*Effects*: Equivalent to: wait(arrive())[.](#thread.barrier.class-23.sentence-1)
[🔗](#lib:arrive_and_drop,barrier)
`void arrive_and_drop();
`
[24](#thread.barrier.class-24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11093)
*Preconditions*: The expected count for the current barrier phase is greater than zero[.](#thread.barrier.class-24.sentence-1)
[25](#thread.barrier.class-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11097)
*Effects*: Decrements the initial expected count for all subsequent phases by one[.](#thread.barrier.class-25.sentence-1)
Then decrements the expected count for the current phase by one[.](#thread.barrier.class-25.sentence-2)
[26](#thread.barrier.class-26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11102)
*Synchronization*: The call to arrive_and_drop strongly happens before
the start of the phase completion step for the current phase[.](#thread.barrier.class-26.sentence-1)
[27](#thread.barrier.class-27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11107)
*Throws*: system_error when an exception is required ([[thread.req.exception]](thread.req.exception "32.2.2Exceptions"))[.](#thread.barrier.class-27.sentence-1)
[28](#thread.barrier.class-28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11111)
*Error conditions*: Any of the error conditions
allowed for mutex types ([[thread.mutex.requirements.mutex]](thread.mutex.requirements.mutex "32.6.4.2Mutex types"))[.](#thread.barrier.class-28.sentence-1)
[29](#thread.barrier.class-29)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11116)
[*Note [4](#thread.barrier.class-note-4)*:
This call can cause the completion step for the current phase to start[.](#thread.barrier.class-29.sentence-1)
— *end note*]