| Home | Libraries | People | FAQ | More

### 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 `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:

1. Fiber “main” launches fibers A, B, C and D, then calls `barrier::wait()`.
2. Fiber C finishes first and likewise calls `barrier::wait()`.
3. Fiber “main” is unblocked, as desired.
4. Fiber B calls `barrier::wait()`. Fiber B is blocked!
5. Fiber A calls `barrier::wait()`. Fibers A and B are unblocked.
6. Fiber D calls `barrier::wait()`. Fiber D is blocked indefinitely.

(See also 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.[1] The rest of the waiting fibers will still be blocked in `wait()`, which must, before returning, access data members in the barrier object.

##### Class `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.

##### Constructor

    explicit barrier( std::size_t initial);

Effects:

  Construct a barrier for `initial` fibers.

Throws:

  `fiber_error`

Error Conditions:

  invalid_argument: if `initial` is zero.

##### Member function `wait`()

    bool wait();

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`

[1] 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.