1[/ 2 (C) Copyright 2007-8 Anthony Williams. 3 (C) Copyright 2013 Oliver Kowalke. 4 Distributed under the Boost Software License, Version 1.0. 5 (See accompanying file LICENSE_1_0.txt or copy at 6 http://www.boost.org/LICENSE_1_0.txt). 7] 8 9[section:barriers Barriers] 10 11A barrier is a concept also known as a __rendezvous__, it is a synchronization 12point between multiple contexts of execution (fibers). The barrier is 13configured for a particular number of fibers (`n`), and as fibers reach the 14barrier they must wait until all `n` fibers have arrived. Once the `n`-th 15fiber has reached the barrier, all the waiting fibers can proceed, and the 16barrier is reset. 17 18The fact that the barrier automatically resets is significant. Consider a case 19in which you launch some number of fibers and want to wait only until the 20first of them has completed. You might be tempted to use a `barrier(2)` as the 21synchronization mechanism, making each new fiber call its [member_link 22barrier..wait] method, then calling `wait()` in the launching fiber to wait 23until the first other fiber completes. 24 25That will in fact unblock the launching fiber. The unfortunate part is that it 26will continue blocking the ['remaining] fibers. 27 28Consider the following scenario: 29 30# Fiber ["main] launches fibers A, B, C and D, then calls `barrier::wait()`. 31# Fiber C finishes first and likewise calls `barrier::wait()`. 32# Fiber ["main] is unblocked, as desired. 33# Fiber B calls `barrier::wait()`. Fiber B is ['blocked!] 34# Fiber A calls `barrier::wait()`. Fibers A and B are unblocked. 35# Fiber D calls `barrier::wait()`. Fiber D is blocked indefinitely. 36 37(See also [link wait_first_simple_section when_any, simple completion].) 38 39[note It is unwise to tie the lifespan of a barrier to any one of its 40participating fibers. Although conceptually all waiting fibers awaken 41["simultaneously,] because of the nature of fibers, in practice they will 42awaken one by one in indeterminate order.[footnote The current implementation 43wakes fibers in FIFO order: the first to call `wait()` wakes first, and so 44forth. But it is perilous to rely on the order in which the various fibers 45will reach the `wait()` call.] The rest of the waiting fibers will 46still be blocked in `wait()`, which must, before returning, access data 47members in the barrier object.] 48 49[class_heading barrier] 50 51 #include <boost/fiber/barrier.hpp> 52 53 namespace boost { 54 namespace fibers { 55 56 class barrier { 57 public: 58 explicit barrier( std::size_t); 59 60 barrier( barrier const&) = delete; 61 barrier & operator=( barrier const&) = delete; 62 63 bool wait(); 64 }; 65 66 }} 67 68 69Instances of __barrier__ are not copyable or movable. 70 71[heading Constructor] 72 73 explicit barrier( std::size_t initial); 74 75[variablelist 76[[Effects:] [Construct a barrier for `initial` fibers.]] 77[[Throws:] [`fiber_error`]] 78[[Error Conditions:] [ 79[*invalid_argument]: if `initial` is zero.]] 80] 81 82[member_heading barrier..wait] 83 84 bool wait(); 85 86[variablelist 87[[Effects:] [Block until `initial` fibers have called `wait` on `*this`. When 88the `initial`-th fiber calls `wait`, all waiting fibers are unblocked, and 89the barrier is reset. ]] 90[[Returns:] [`true` for exactly one fiber from each batch of waiting fibers, 91`false` otherwise.]] 92[[Throws:] [__fiber_error__]] 93] 94 95[endsect] 96