1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- [/
- (C) Copyright 2007-8 Anthony Williams.
- (C) Copyright 2013 Oliver Kowalke.
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE_1_0.txt or copy at
- http://www.boost.org/LICENSE_1_0.txt).
- ]
- [section:barriers Barriers]
- 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 [member_link
- 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:
- # Fiber ["main] launches fibers A, B, C and D, then calls `barrier::wait()`.
- # Fiber C finishes first and likewise calls `barrier::wait()`.
- # Fiber ["main] is unblocked, as desired.
- # Fiber B calls `barrier::wait()`. Fiber B is ['blocked!]
- # Fiber A calls `barrier::wait()`. Fibers A and B are unblocked.
- # Fiber D calls `barrier::wait()`. Fiber D is blocked indefinitely.
- (See also [link wait_first_simple_section 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.[footnote 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.] The rest of the waiting fibers will
- still be blocked in `wait()`, which must, before returning, access data
- members in the barrier object.]
- [class_heading 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.
- [heading Constructor]
- explicit barrier( std::size_t initial);
- [variablelist
- [[Effects:] [Construct a barrier for `initial` fibers.]]
- [[Throws:] [`fiber_error`]]
- [[Error Conditions:] [
- [*invalid_argument]: if `initial` is zero.]]
- ]
- [member_heading barrier..wait]
- bool wait();
- [variablelist
- [[Effects:] [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. ]]
- [[Returns:] [`true` for exactly one fiber from each batch of waiting fibers,
- `false` otherwise.]]
- [[Throws:] [__fiber_error__]]
- ]
- [endsect]
|