310f3ce2f2
- new namesapce algo - shared_round_robin with shared ready queue
96 lines
3.3 KiB
Plaintext
96 lines
3.3 KiB
Plaintext
[/
|
|
(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]
|