• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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