...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
A barrier is a concept also known as a rendezvous, it
is a synchronization point between multiple contexts of execution (fibers).
The barrier is configured for a particular number of fibers (n
), and as fibers reach the barrier they
must wait until all n
fibers
have arrived. Once the n
-th
fiber has reached the barrier, all the waiting fibers can proceed, and the
barrier is reset.
The fact that the barrier automatically resets is significant. Consider a
case in which you launch some number of fibers and want to wait only until
the first of them has completed. You might be tempted to use a barrier(2)
as the synchronization
mechanism, making each new fiber call its barrier::wait()
method,
then calling wait()
in the launching fiber to wait until the first other fiber completes.
That will in fact unblock the launching fiber. The unfortunate part is that it will continue blocking the remaining fibers.
Consider the following scenario:
barrier::wait()
.
barrier::wait()
.
barrier::wait()
. Fiber B is blocked!
barrier::wait()
. Fibers A and B are unblocked.
barrier::wait()
. Fiber D is blocked indefinitely.
(See also when_any, simple completion.)
Note | |
---|---|
It is unwise to tie the lifespan of a barrier to any one of its participating
fibers. Although conceptually all waiting fibers awaken “simultaneously,”
because of the nature of fibers, in practice they will awaken one by one
in indeterminate order.[1] The rest of the waiting fibers will still be blocked in |
barrier
#include <boost/fiber/barrier.hpp> namespace boost { namespace fibers { class barrier { public: explicit barrier( std::size_t); barrier( barrier const&) = delete; barrier & operator=( barrier const&) = delete; bool wait(); }; }}
Instances of barrier
are not copyable or movable.
explicit barrier( std::size_t initial);
Construct a barrier for initial
fibers.
fiber_error
invalid_argument: if initial
is zero.
wait
()
bool wait();
Block until initial
fibers have called wait
on *this
.
When the initial
-th
fiber calls wait
, all
waiting fibers are unblocked, and the barrier is reset.
true
for exactly one fiber
from each batch of waiting fibers, false
otherwise.
fiber_error
[1]
The current implementation wakes fibers in FIFO order: the first to call
wait()
wakes first, and so forth. But it is perilous to rely on the order in
which the various fibers will reach the wait()
call.