[/ (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 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]