Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

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


PrevUpHomeNext