518 lines
22 KiB
Markdown
518 lines
22 KiB
Markdown
[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.2 Exceptions"))[.](#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.2 Mutex 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.2 Exceptions"))[.](#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.2 Mutex 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.3 Class 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.3 Class 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.3 Class 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.2 Template 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.2 Template 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.2 Template 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.2 Template 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.2 Template 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.2 Template 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.2 Exceptions"))[.](#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.2 Mutex 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.2 Exceptions"))[.](#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.2 Mutex 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.2 Exceptions"))[.](#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.2 Mutex 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*]
|