fiber/doc/barrier.qbk
Oliver Kowalke 310f3ce2f2 move sched_algorithm to algo::algorithm
- new namesapce algo
- shared_round_robin with shared ready queue
2016-05-13 20:14:48 +02:00

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]