[/ Copyright Oliver Kowalke 2013. 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:unbuffered_channel Unbuffered Channel] __boost_fiber__ provides template `unbuffered_channel` suitable to synchonize fibers (running on same or different threads) via synchronous message passing. A fiber waiting to consume an value will block until the value is produced. If a fiber attempts to send a value through an unbuffered channel and no fiber is waiting to receive the value, the channel will block the sending fiber. The unbuffered channel acts as an `rendezvous point`. typedef boost::fibers::unbuffered_channel< int > channel_t; void send( channel_t & chan) { for ( int i = 0; i < 5; ++i) { chan.push( i); } chan.close(); } void recv( channel_t & chan) { int i; while ( boost::fibers::channel_op_status::success == chan.pop(i) ) { std::cout << "received " << i << std::endl; } } channel_t chan{ 1 }; boost::fibers::fiber f1( std::bind( send, std::ref( chan) ) ); boost::fibers::fiber f2( std::bind( recv, std::ref( chan) ) ); f1.join(); f2.join(); Range-for syntax is supported: typedef boost::fibers::unbuffered_channel< int > channel_t; void foo( channel_t & chan) { chan.push( 1); chan.push( 1); chan.push( 2); chan.push( 3); chan.push( 5); chan.push( 8); chan.push( 12); chan.close(); } void bar( channel_t & chan) { for ( unsigned int value : chan) { std::cout << value << " "; } std::cout << std::endl; } [template_heading unbuffered_channel] #include namespace boost { namespace fibers { template< typename T > class unbuffered_channel { public: typedef T value_type; class iterator; unbuffered_channel(); unbuffered_channel( unbuffered_channel const& other) = delete; unbuffered_channel & operator=( unbuffered_channel const& other) = delete; 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 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); }; template< typename T > unbuffered_channel< T >::iterator begin( unbuffered_channel< T > & chan); template< typename T > unbuffered_channel< T >::iterator end( unbuffered_channel< T > & chan); }} [heading Constructor] unbuffered_channel(); [variablelist [[Effects:] [The constructor constructs an object of class `unbuffered_channel`.]] ] [member_heading unbuffered_channel..close] void close() noexcept; [variablelist [[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.]] ] [template unbuffered_channel_push_effects[enqueues] If channel is closed, returns `closed`. [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`.] [member_heading unbuffered_channel..push] channel_op_status push( value_type const& va); channel_op_status push( value_type && va); [variablelist [[Effects:] [[unbuffered_channel_push_effects Otherwise enqueues]]] [[Throws:] [Exceptions thrown by copy- or move-operations.]] ] [template unbuffered_channel_pop[cls unblocking] [member_heading [cls]..pop] channel_op_status pop( value_type & va); [variablelist [[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`)[unblocking]]] [[Throws:] [Exceptions thrown by copy- or move-operations.]] ] ] [unbuffered_channel_pop unbuffered_channel .] [template unbuffered_channel_value_pop[cls unblocking] [member_heading [cls]..value_pop] value_type value_pop(); [variablelist [[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)[unblocking]]] [[Throws:] [`fiber_error` if `*this` is closed or by copy- or move-operations.]] [[Error conditions:] [`std::errc::operation_not_permitted`]] ] ] [unbuffered_channel_value_pop unbuffered_channel .] [template unbuffered_channel_pop_wait_until_effects[endtime unblocking] 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 [endtime] (return value `timeout`)[unblocking]] [template unbuffered_channel_pop_wait_for[cls unblocking] [member_heading [cls]..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) [variablelist [[Effects:] [Accepts `std::chrono::duration` and internally computes a timeout time as (system time + `timeout_duration`). [unbuffered_channel_pop_wait_until_effects the computed timeout time..[unblocking]]]] [[Throws:] [timeout-related exceptions or by copy- or move-operations.]] ] ] [unbuffered_channel_pop_wait_for unbuffered_channel .] [template unbuffered_channel_pop_wait_until[cls unblocking] [member_heading [cls]..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) [variablelist [[Effects:] [Accepts a `std::chrono::time_point< Clock, Duration >`. [unbuffered_channel_pop_wait_until_effects the passed `time_point`..[unblocking]]]] [[Throws:] [timeout-related exceptions or by copy- or move-operations.]] ] ] [unbuffered_channel_pop_wait_until unbuffered_channel .] [heading Non-member function `begin( unbuffered_channel< T > &)`] template< typename T > unbuffered_channel< T >::iterator begin( unbuffered_channel< T > &); [variablelist [[Returns:] [Returns a range-iterator (input-iterator).]] ] [heading Non-member function `end( unbuffered_channel< T > &)`] template< typename T > unbuffered_channel< R >::iterator end( unbuffered_channel< T > &); [variablelist [[Returns:] [Returns an end range-iterator (input-iterator).]] ] [endsect]