| Home | Libraries | People | FAQ | More

### Channels

Boost.Fiber provides a bounded and a unbounded channel suitable to synchonize fibers via message passing.

    typedef boost::fibers::unbounded_channel< int > channel_t;

    void send( channel_t & channel) {
        for ( int i = 0; i < 5; ++i) {
            channel.push( i);
        }
        channel.close();
    }

    void recv( channel_t & channel) {
        int i;
        while ( boost::fibers::channel_op_status::success == channel.pop(i) ) {
            std::cout << "received " << i << std::endl;
        }
    }

    channel_t channel;
    boost::fibers::fiber f1( std::bind( send, ref( channel) ) );
    boost::fibers::fiber f2( std::bind( recv, ref( channel) ) );

    f1.join();
    f2.join();

##### Enumeration `channel_op_status`

channel operations return the state of the channel.

    enum class channel_op_status {
        success,
        empty,
        full,
        closed,
        timeout
    };

##### `success`

Effects:

  Operation was successful.

##### `empty`

Effects:

  channel is empty, operation failed.

##### `full`

Effects:

  channel is full, operation failed.

##### `closed`

Effects:

  channel is closed, operation failed.

##### `timeout`

Effects:

  The operation did not become ready before specified timeout elapsed.

##### Template `unbounded_channel<>`

    #include <boost/fiber/unbounded_channel.hpp>

    namespace boost {
    namespace fibers {

    template< typename T, typename Allocator = std::allocator< T > >
    class unbounded_channel {
    public:
        typedef T   value_type;

        explicit unbounded_channel( Allocator const& alloc = Allocator() ) noexcept;

        unbounded_channel( unbounded_channel const& other) = delete;
        unbounded_channel & operator=( unbounded_channel const& other) = delete;

        void close() noexcept;

        channel_op_status push( value_type const& va);
        channel_op_status push( value_type && va);

        channel_op_status pop( value_type & va);
        value_type value_pop();
        channel_op_status try_pop( value_type & va);
        template< typename Rep, typename Period >
        channel_op_status pop_wait_for(
            value_type & va,
            std::chrono::duration< Rep, Period > const& timeout_duration);
        template< typename Clock, typename Duration >
        channel_op_status pop_wait_until(
            value_type & va,
            std::chrono::time_point< Clock, Duration > const& timeout_time);
    };

    }}

##### Constructor

    explicit unbounded_channel( Allocator const& alloc = Allocator() ) noexcept;

Effects:

  Constructs an object of class `unbounded_channel`. Internal nodes are allocated using `alloc` - C++11-allocators are supported.

Throws:

  Nothing.

See also:

  `Allocator` concept, `std::allocator< T >`

##### Member function `close`()

    void close() noexcept;

Effects:

  Deactivates the channel. No values can be put after calling `this->close()`. Fibers blocked in `this->pop()`, `this->pop_wait_for()` or `this->pop_wait_until()` will return `closed`. Fibers blocked in `this->value_pop()` will receive an exception.

Throws:

  Nothing.

Note:

  `close()` is like closing a pipe. It informs waiting consumers that no more values will arrive.

##### Member function `push`()

    channel_op_status push( value_type const& va);
    channel_op_status push( value_type && va);

Effects:

  If channel is closed, returns `closed`. Otherwise enqueues the value in the channel, wakes up a fiber blocked on `this->pop()`, `this->value_pop()`, `this->pop_wait_for()` or `this->pop_wait_until()` and returns `success`.

Throws:

  Exceptions thrown by memory allocation and copying or moving `va`.

##### Member function `pop`()

    channel_op_status pop( value_type & va);

Effects:

  Dequeues a value from the channel. If the channel is empty, the fiber gets suspended until at least one new item is `push()`ed (return value `success` and `va` contains dequeued value) or the channel gets `close()`d (return value `closed`).

Throws:

  Nothing

##### Member function `value_pop`()

    value_type value_pop();

Effects:

  Dequeues a value from the channel. If the channel is empty, the fiber gets suspended until at least one new item is `push()`ed or the channel gets `close()`d (which throws an exception).

Throws:

  `fiber_error` if `*this` is closed

Error conditions:

  `std::errc::operation_not_permitted`

##### Member function `try_pop`()

    channel_op_status try_pop( value_type & va);

Effects:

  If channel is empty, returns `empty`. If channel is closed, returns `closed`. Otherwise it returns `success` and `va` contains the dequeued value.

Throws:

  Exceptions thrown by copy- or move-operations.

##### Member function `pop_wait_for`()

    template< typename Rep, typename Period >
    channel_op_status pop_wait_for(
        value_type & va,
        std::chrono::duration< Rep, Period > const& timeout_duration)

Effects:

  Accepts `std::chrono::duration` and internally computes a timeout time as (system time + `timeout_duration`). If channel is not empty, immediately dequeues a value from the channel. Otherwise the fiber gets suspended until at least one new item is `push()`ed (return value `success` and `va` contains dequeued value), or the channel gets `close()`d (return value `closed`), or the system time reaches the computed timeout time (return value `timeout`).

Throws:

  timeout-related exceptions.

##### Member function `pop_wait_until`()

    template< typename Clock, typename Duration >
    channel_op_status pop_wait_until(
        value_type & va,
        std::chrono::time_point< Clock, Duration > const& timeout_time)

Effects:

  Accepts a `std::chrono::time_point< Clock, Duration >`. If channel is not empty, immediately dequeues a value from the channel. Otherwise the fiber gets suspended until at least one new item is `push()`ed (return value `success` and `va` contains dequeued value), or the channel gets `close()`d (return value `closed`), or the system time reaches the passed `time_point` (return value `timeout`).

Throws:

  timeout-related exceptions.

##### Template `bounded_channel<>`

    #include <boost/fiber/bounded_channel.hpp>

    namespace boost {
    namespace fibers {

    template< typename T, typename Allocator = std::allocator< T > >
    class bounded_channel {
    public:
        typedef T   value_type;

        bounded_channel( std::size_t wm, Allocator const& alloc = Allocator() );
        bounded_channel( std::size_t hwm, std::size_t lwm, Allocator const& alloc = Allocator() );

        bounded_channel( bounded_channel const& other) = delete;
        bounded_channel & operator=( bounded_channel const& other) = delete;

        std::size_t upper_bound() const noexcept;
        std::size_t lower_bound() const noexcept;

        void close() noexcept;

        channel_op_status push( value_type const& va);
        channel_op_status push( value_type && va);
        template< typename Rep, typename Period >
        channel_op_status push_wait_for(
            value_type const& va,
            std::chrono::duration< Rep, Period > const& timeout_duration);
        channel_op_status push_wait_for( value_type && va,
            std::chrono::duration< Rep, Period > const& timeout_duration);
        template< typename Clock, typename Duration >
        channel_op_status push_wait_until(
            value_type const& va,
            std::chrono::time_point< Clock, Duration > const& timeout_time);
        template< typename Clock, typename Duration >
        channel_op_status push_wait_until(
            value_type && va,
            std::chrono::time_point< Clock, Duration > const& timeout_time);
        channel_op_status try_push( value_type const& va);
        channel_op_status try_push( value_type && va);

        channel_op_status pop( value_type & va);
        value_type value_pop();
        template< typename Rep, typename Period >
        channel_op_status pop_wait_for(
            value_type & va,
            std::chrono::duration< Rep, Period > const& timeout_duration);
        template< typename Clock, typename Duration >
        channel_op_status pop_wait_until(
            value_type & va,
            std::chrono::time_point< Clock, Duration > const& timeout_time);
        channel_op_status try_pop( value_type & va);
    };

    }}

##### Constructor

    bounded_channel( std::size_t wm, Allocator const& alloc = Allocator() );
    bounded_channel( std::size_t hwm, std::size_t lwm, Allocator const& alloc = Allocator() );

Preconditions:

  `hwm > lwm`

Effects:

  Constructs an object of class `bounded_channel`. The constructor with two arguments constructs an object of class `bounded_channel` with a high-watermark of `hwm` and a low-watermark of `lwm` items. The constructor with one `std::size_t` argument is effectively the same as `bounded_channel(wm, (wm-1), alloc)`. Internal nodes are allocated using `alloc` - C++11-allocators are supported.

Throws:

  `fiber_error`

Error Conditions:

  invalid_argument: if `lwm >= hwm`.

Notes:

  Once the number of values in the channel reaches `hwm`, any call to `push()`, `push_wait_for()` or `push_wait_until()` will block until the number of values in the channel is at most `lwm`. That is, if `lwm < (hwm-1)`, the channel can be in a state in which `push()`, `push_wait_for()` or `push_wait_until()` calls will block (channel is full) even though the number of values in the channel is less than `hwm`.

See also:

  `Allocator` concept, `std::allocator< T >`

##### Member function `upper_bound`()

    std::size_t upper_bound() const noexcept;

Returns:

  the high-watermark with which `*this` was constructed.

Throws:

  Nothing.

##### Member function `lower_bound`()

    std::size_t lower_bound() const noexcept;

Returns:

  the low-watermark with which `*this` was constructed.

Throws:

  Nothing.

##### Member function `close`()

    void close() noexcept;

Effects:

  Deactivates the channel. No values can be put after calling `this->close()`. Fibers blocked in `this->pop()`, `this->pop_wait_for()` or `this->pop_wait_until()` will return `closed`. Fibers blocked in `this->value_pop()` will receive an exception.

Throws:

  Nothing.

Note:

  `close()` is like closing a pipe. It informs waiting consumers that no more values will arrive.

##### Member function `push`()

    channel_op_status push( value_type const& va);
    channel_op_status push( value_type && va);

Effects:

  If channel is closed, returns `closed`. If channel is not full, enqueues the value in the channel, wakes up a fiber blocked on `this->pop()`, `this->value_pop()`, `this->pop_wait_for()` or `this->pop_wait_until()` and returns `success`. Otherwise the calling fiber is suspended until the number of values in the channel drops to `lwm` (return value `success`)or the channel is `close()`d (return value `closed`).

Throws:

  exceptions thrown by memory allocation and copying or moving `va`.

##### Member function `push_wait_for`()

    template< typename Rep, typename Period >
    channel_op_status push_wait_for(
        value_type const& va,
        std::chrono::duration< Rep, Period > const& timeout_duration);

    template< typename Rep, typename Period >
    channel_op_status push_wait_for(
        value_type && va,
        std::chrono::duration< Rep, Period > const& timeout_duration);

Effects:

  Accepts `std::chrono::duration` and internally computes a time_point as (system time + `timeout_duration`). If channel is closed, returns `closed`. If channel is not full, enqueues the value in the channel, wakes up a fiber blocked on `this->pop()`, `this->value_pop()`, `this->pop_wait_for()` or `this->pop_wait_until()` and returns `success`. Otherwise the calling fiber is suspended until the number of values in the channel drops to `lwm` (return value `success`), the channel is `close()`d (return value `closed`), or the system time reaches the computed time_point (return value `timeout`).

Throws:

  exceptions thrown by memory allocation and copying or moving `va` or timeout-related exceptions.

##### Member function `push_wait_until`()

    template< typename Clock, typename Duration >
    channel_op_status push_wait_until(
        value_type const& va,
        std::chrono::time_point< Clock, Duration > const& timeout_time);

    template< typename Clock, typename Duration >
    channel_op_status push_wait_until(
        value_type && va,
        std::chrono::time_point< Clock, Duration > const& timeout_time);

Effects:

  Accepts an absolute `timeout_time` in any supported time_point type. If channel is closed, returns `closed`. If channel is not full, enqueues the value in the channel, wakes up a fiber blocked on `this->pop()`, `this->value_pop()`, `this->pop_wait_for()` or `this->pop_wait_until()` and returns `success`. Otherwise the calling fiber is suspended until the number of values in the channel drops to `lwm` (return value `success`), the channel is `close()`d (return value `closed`), or the system time reaches the passed time_point (return value `timeout`).

Throws:

  exceptions thrown by memory allocation and copying or moving `va` or timeout-related exceptions.

##### Member function `try_push`()

    channel_op_status try_push( value_type const& va);
    channel_op_status try_push( value_type && va);

Effects:

  If channel is full, returns `full`. If channel is closed, returns `closed`. Otherwise enqueues the value in the channel, wakes up a fiber blocked on `this->pop()`, `this->value_pop()`, `this->pop_wait_for()` or `this->pop_wait_until()` and returns `success`.

Throws:

  Exceptions thrown by memory allocation and copying or moving `va`.

##### Member function `pop`()

    channel_op_status pop( value_type & va);

Effects:

  Dequeues a value from the channel. If the channel is empty, the fiber gets suspended until at least one new item is `push()`ed (return value `success` and `va` contains dequeued value) or the channel gets `close()`d (return value `closed`). Once the number of items remaining in the channel drops to `lwm`, any fibers blocked on `push()`, `push_wait_for()` or `push_wait_until()` may resume.

Throws:

  Nothing

##### Member function `value_pop`()

    value_type value_pop();

Effects:

  Dequeues a value from the channel. If the channel is empty, the fiber gets suspended until at least one new item is `push()`ed or the channel gets `close()`d (which throws an exception). Once the number of items remaining in the channel drops to `lwm`, any fibers blocked on `push()`, `push_wait_for()` or `push_wait_until()` may resume.

Throws:

  `fiber_error` if `*this` is closed

Error conditions:

  `std::errc::operation_not_permitted`

##### Member function `try_pop`()

    channel_op_status try_pop( value_type & va);

Effects:

  If channel is empty, returns `empty`. If channel is closed, returns `closed`. Otherwise it returns `success` and `va` contains the dequeued value. Once the number of items remaining in the channel drops to `lwm`, any fibers blocked on `push()`, `push_wait_for()` or `push_wait_until()` may resume.

Throws:

  Exceptions thrown by copy- or move-operations.

##### Member function `pop_wait_for`()

    template< typename Rep, typename Period >
    channel_op_status pop_wait_for(
        value_type & va,
        std::chrono::duration< Rep, Period > const& timeout_duration)

Effects:

  Accepts `std::chrono::duration` and internally computes a timeout time as (system time + `timeout_duration`). If channel is not empty, immediately dequeues a value from the channel. Otherwise the fiber gets suspended until at least one new item is `push()`ed (return value `success` and `va` contains dequeued value), or the channel gets `close()`d (return value `closed`), or the system time reaches the computed timeout time (return value `timeout`). Once the number of items remaining in the channel drops to `lwm`, any fibers blocked on `push()`, `push_wait_for()` or `push_wait_until()` may resume.

Throws:

  timeout-related exceptions.

##### Member function `pop_wait_until`()

    template< typename Clock, typename Duration >
    channel_op_status pop_wait_until(
        value_type & va,
        std::chrono::time_point< Clock, Duration > const& timeout_time)

Effects:

  Accepts a `std::chrono::time_point< Clock, Duration >`. If channel is not empty, immediately dequeues a value from the channel. Otherwise the fiber gets suspended until at least one new item is `push()`ed (return value `success` and `va` contains dequeued value), or the channel gets `close()`d (return value `closed`), or the system time reaches the passed `time_point` (return value `timeout`). Once the number of items remaining in the channel drops to `lwm`, any fibers blocked on `push()`, `push_wait_for()` or `push_wait_until()` may resume.

Throws:

  timeout-related exceptions.