335 lines
14 KiB
Markdown
335 lines
14 KiB
Markdown
[thread.barrier]
|
||
|
||
# 32 Concurrency support library [[thread]](./#thread)
|
||
|
||
## 32.9 Coordination types [[thread.coord]](thread.coord#thread.barrier)
|
||
|
||
### 32.9.3 Barriers [thread.barrier]
|
||
|
||
#### [32.9.3.1](#general) General [[thread.barrier.general]](thread.barrier.general)
|
||
|
||
[1](#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[.](#general-1.sentence-1)
|
||
|
||
[*Note [1](#general-note-1)*:
|
||
|
||
A barrier is useful for managing repeated tasks
|
||
that are handled by multiple threads[.](#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](#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](#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)](#class-1.1)
|
||
|
||
The expected count is decremented
|
||
by each call to arrive or arrive_and_drop[.](#class-1.1.sentence-1)
|
||
|
||
- [(1.2)](#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[.](#class-1.2.sentence-1)
|
||
|
||
- [(1.3)](#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[.](#class-1.3.sentence-1)
|
||
|
||
[2](#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]")[.](#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[.](#class-2.sentence-2)
|
||
|
||
[3](#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)](#class-3.1)
|
||
|
||
Invokes the completion function, equivalent to completion()[.](#class-3.1.sentence-1)
|
||
|
||
- [(3.2)](#class-3.2)
|
||
|
||
Unblocks all threads that are blocked on the phase synchronization point[.](#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[.](#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[.](#class-3.sentence-3)
|
||
|
||
[4](#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[.](#class-4.sentence-1)
|
||
|
||
The member functions arrive and arrive_and_drop execute atomically[.](#class-4.sentence-2)
|
||
|
||
[5](#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[.](#class-5.sentence-1)
|
||
|
||
is_nothrow_invocable_v<CompletionFunction&> shall be true[.](#class-5.sentence-2)
|
||
|
||
[6](#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[.](#class-6.sentence-1)
|
||
|
||
[7](#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[.](#class-7.sentence-1)
|
||
|
||
[ð](#lib:max,barrier)
|
||
|
||
`static constexpr ptrdiff_t max() noexcept;
|
||
`
|
||
|
||
[8](#class-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10970)
|
||
|
||
*Returns*: The maximum expected count that the implementation supports[.](#class-8.sentence-1)
|
||
|
||
[ð](#lib:barrier,constructor)
|
||
|
||
`constexpr explicit barrier(ptrdiff_t expected,
|
||
CompletionFunction f = CompletionFunction());
|
||
`
|
||
|
||
[9](#class-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10982)
|
||
|
||
*Preconditions*: expected >= 0 is true andexpected <= max() is true[.](#class-9.sentence-1)
|
||
|
||
[10](#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[.](#class-10.sentence-1)
|
||
|
||
Initializes completion with std::move(f)[.](#class-10.sentence-2)
|
||
|
||
Starts the first phase[.](#class-10.sentence-3)
|
||
|
||
[*Note [1](#class-note-1)*:
|
||
|
||
If expected is 0 this object can only be destroyed[.](#class-10.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[11](#class-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L10997)
|
||
|
||
*Throws*: Any exception thrown by CompletionFunction's move constructor[.](#class-11.sentence-1)
|
||
|
||
[ð](#lib:arrive,barrier)
|
||
|
||
`arrival_token arrive(ptrdiff_t update = 1);
|
||
`
|
||
|
||
[12](#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[.](#class-12.sentence-1)
|
||
|
||
[13](#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[.](#class-13.sentence-1)
|
||
|
||
Then, decrements the expected count by update[.](#class-13.sentence-2)
|
||
|
||
[14](#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[.](#class-14.sentence-1)
|
||
|
||
[15](#class-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11025)
|
||
|
||
*Returns*: The constructed arrival_token object[.](#class-15.sentence-1)
|
||
|
||
[16](#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"))[.](#class-16.sentence-1)
|
||
|
||
[17](#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"))[.](#class-17.sentence-1)
|
||
|
||
[18](#class-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11038)
|
||
|
||
[*Note [2](#class-note-2)*:
|
||
|
||
This call can cause the completion step for the current phase to start[.](#class-18.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:wait,barrier)
|
||
|
||
`void wait(arrival_token&& arrival) const;
|
||
`
|
||
|
||
[19](#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[.](#class-19.sentence-1)
|
||
|
||
[20](#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[.](#class-20.sentence-1)
|
||
|
||
[*Note [3](#class-note-3)*:
|
||
|
||
If arrival is associated with the synchronization point
|
||
for a previous phase, the call returns immediately[.](#class-20.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[21](#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"))[.](#class-21.sentence-1)
|
||
|
||
[22](#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"))[.](#class-22.sentence-1)
|
||
|
||
[ð](#lib:arrive_and_wait,barrier)
|
||
|
||
`void arrive_and_wait();
|
||
`
|
||
|
||
[23](#class-23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11082)
|
||
|
||
*Effects*: Equivalent to: wait(arrive())[.](#class-23.sentence-1)
|
||
|
||
[ð](#lib:arrive_and_drop,barrier)
|
||
|
||
`void arrive_and_drop();
|
||
`
|
||
|
||
[24](#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[.](#class-24.sentence-1)
|
||
|
||
[25](#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[.](#class-25.sentence-1)
|
||
|
||
Then decrements the expected count for the current phase by one[.](#class-25.sentence-2)
|
||
|
||
[26](#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[.](#class-26.sentence-1)
|
||
|
||
[27](#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"))[.](#class-27.sentence-1)
|
||
|
||
[28](#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"))[.](#class-28.sentence-1)
|
||
|
||
[29](#class-29)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/threads.tex#L11116)
|
||
|
||
[*Note [4](#class-note-4)*:
|
||
|
||
This call can cause the completion step for the current phase to start[.](#class-29.sentence-1)
|
||
|
||
â *end note*]
|