unbuffered_channel.qbk 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. [/
  2. Copyright Oliver Kowalke 2013.
  3. Distributed under the Boost Software License, Version 1.0.
  4. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt
  6. ]
  7. [section:unbuffered_channel Unbuffered Channel]
  8. __boost_fiber__ provides template `unbuffered_channel` suitable to synchonize
  9. fibers (running on same or different threads) via synchronous message passing.
  10. A fiber waiting to consume an value will block until the value is produced.
  11. If a fiber attempts to send a value through an unbuffered channel and no fiber
  12. is waiting to receive the value, the channel will block the sending fiber.
  13. The unbuffered channel acts as an `rendezvous point`.
  14. typedef boost::fibers::unbuffered_channel< int > channel_t;
  15. void send( channel_t & chan) {
  16. for ( int i = 0; i < 5; ++i) {
  17. chan.push( i);
  18. }
  19. chan.close();
  20. }
  21. void recv( channel_t & chan) {
  22. int i;
  23. while ( boost::fibers::channel_op_status::success == chan.pop(i) ) {
  24. std::cout << "received " << i << std::endl;
  25. }
  26. }
  27. channel_t chan{ 1 };
  28. boost::fibers::fiber f1( std::bind( send, std::ref( chan) ) );
  29. boost::fibers::fiber f2( std::bind( recv, std::ref( chan) ) );
  30. f1.join();
  31. f2.join();
  32. Range-for syntax is supported:
  33. typedef boost::fibers::unbuffered_channel< int > channel_t;
  34. void foo( channel_t & chan) {
  35. chan.push( 1);
  36. chan.push( 1);
  37. chan.push( 2);
  38. chan.push( 3);
  39. chan.push( 5);
  40. chan.push( 8);
  41. chan.push( 12);
  42. chan.close();
  43. }
  44. void bar( channel_t & chan) {
  45. for ( unsigned int value : chan) {
  46. std::cout << value << " ";
  47. }
  48. std::cout << std::endl;
  49. }
  50. [template_heading unbuffered_channel]
  51. #include <boost/fiber/unbuffered_channel.hpp>
  52. namespace boost {
  53. namespace fibers {
  54. template< typename T >
  55. class unbuffered_channel {
  56. public:
  57. typedef T value_type;
  58. class iterator;
  59. unbuffered_channel();
  60. unbuffered_channel( unbuffered_channel const& other) = delete;
  61. unbuffered_channel & operator=( unbuffered_channel const& other) = delete;
  62. void close() noexcept;
  63. channel_op_status push( value_type const& va);
  64. channel_op_status push( value_type && va);
  65. template< typename Rep, typename Period >
  66. channel_op_status push_wait_for(
  67. value_type const& va,
  68. std::chrono::duration< Rep, Period > const& timeout_duration);
  69. channel_op_status push_wait_for( value_type && va,
  70. std::chrono::duration< Rep, Period > const& timeout_duration);
  71. template< typename Clock, typename Duration >
  72. channel_op_status push_wait_until(
  73. value_type const& va,
  74. std::chrono::time_point< Clock, Duration > const& timeout_time);
  75. template< typename Clock, typename Duration >
  76. channel_op_status push_wait_until(
  77. value_type && va,
  78. std::chrono::time_point< Clock, Duration > const& timeout_time);
  79. channel_op_status pop( value_type & va);
  80. value_type value_pop();
  81. template< typename Rep, typename Period >
  82. channel_op_status pop_wait_for(
  83. value_type & va,
  84. std::chrono::duration< Rep, Period > const& timeout_duration);
  85. template< typename Clock, typename Duration >
  86. channel_op_status pop_wait_until(
  87. value_type & va,
  88. std::chrono::time_point< Clock, Duration > const& timeout_time);
  89. };
  90. template< typename T >
  91. unbuffered_channel< T >::iterator begin( unbuffered_channel< T > & chan);
  92. template< typename T >
  93. unbuffered_channel< T >::iterator end( unbuffered_channel< T > & chan);
  94. }}
  95. [heading Constructor]
  96. unbuffered_channel();
  97. [variablelist
  98. [[Effects:] [The constructor constructs an object of class `unbuffered_channel`.]]
  99. ]
  100. [member_heading unbuffered_channel..close]
  101. void close() noexcept;
  102. [variablelist
  103. [[Effects:] [Deactivates the channel. No values can be put after calling
  104. `this->close()`. Fibers blocked in `this->pop()`, `this->pop_wait_for()`
  105. or `this->pop_wait_until()` will return `closed`. Fibers blocked in
  106. `this->value_pop()` will receive an exception.]]
  107. [[Throws:] [Nothing.]]
  108. [[Note:] [`close()` is like closing a pipe. It informs waiting consumers
  109. that no more values will arrive.]]
  110. ]
  111. [template unbuffered_channel_push_effects[enqueues] If channel is closed, returns
  112. `closed`. [enqueues] the value in the channel, wakes up a fiber
  113. blocked on `this->pop()`, `this->value_pop()`, `this->pop_wait_for()` or
  114. `this->pop_wait_until()` and returns `success`.]
  115. [member_heading unbuffered_channel..push]
  116. channel_op_status push( value_type const& va);
  117. channel_op_status push( value_type && va);
  118. [variablelist
  119. [[Effects:] [[unbuffered_channel_push_effects Otherwise enqueues]]]
  120. [[Throws:] [Exceptions thrown by copy- or move-operations.]]
  121. ]
  122. [template unbuffered_channel_pop[cls unblocking]
  123. [member_heading [cls]..pop]
  124. channel_op_status pop( value_type & va);
  125. [variablelist
  126. [[Effects:] [Dequeues a value from the channel. If the channel is empty, the
  127. fiber gets suspended until at least one new item is `push()`ed (return value
  128. `success` and `va` contains dequeued value) or the channel gets `close()`d
  129. (return value `closed`)[unblocking]]]
  130. [[Throws:] [Exceptions thrown by copy- or move-operations.]]
  131. ]
  132. ]
  133. [unbuffered_channel_pop unbuffered_channel .]
  134. [template unbuffered_channel_value_pop[cls unblocking]
  135. [member_heading [cls]..value_pop]
  136. value_type value_pop();
  137. [variablelist
  138. [[Effects:] [Dequeues a value from the channel. If the channel is empty, the
  139. fiber gets suspended until at least one new item is `push()`ed or the channel
  140. gets `close()`d (which throws an exception)[unblocking]]]
  141. [[Throws:] [`fiber_error` if `*this` is closed or by copy- or move-operations.]]
  142. [[Error conditions:] [`std::errc::operation_not_permitted`]]
  143. ]
  144. ]
  145. [unbuffered_channel_value_pop unbuffered_channel .]
  146. [template unbuffered_channel_pop_wait_until_effects[endtime unblocking] If channel
  147. is not empty, immediately dequeues a value from the channel. Otherwise
  148. the fiber gets suspended until at least one new item is `push()`ed (return
  149. value `success` and `va` contains dequeued value), or the channel gets
  150. `close()`d (return value `closed`), or the system time reaches [endtime]
  151. (return value `timeout`)[unblocking]]
  152. [template unbuffered_channel_pop_wait_for[cls unblocking]
  153. [member_heading [cls]..pop_wait_for]
  154. template< typename Rep, typename Period >
  155. channel_op_status pop_wait_for(
  156. value_type & va,
  157. std::chrono::duration< Rep, Period > const& timeout_duration)
  158. [variablelist
  159. [[Effects:] [Accepts `std::chrono::duration` and internally computes a timeout
  160. time as (system time + `timeout_duration`).
  161. [unbuffered_channel_pop_wait_until_effects the computed timeout time..[unblocking]]]]
  162. [[Throws:] [timeout-related exceptions or by copy- or move-operations.]]
  163. ]
  164. ]
  165. [unbuffered_channel_pop_wait_for unbuffered_channel .]
  166. [template unbuffered_channel_pop_wait_until[cls unblocking]
  167. [member_heading [cls]..pop_wait_until]
  168. template< typename Clock, typename Duration >
  169. channel_op_status pop_wait_until(
  170. value_type & va,
  171. std::chrono::time_point< Clock, Duration > const& timeout_time)
  172. [variablelist
  173. [[Effects:] [Accepts a `std::chrono::time_point< Clock, Duration >`.
  174. [unbuffered_channel_pop_wait_until_effects the passed `time_point`..[unblocking]]]]
  175. [[Throws:] [timeout-related exceptions or by copy- or move-operations.]]
  176. ]
  177. ]
  178. [unbuffered_channel_pop_wait_until unbuffered_channel .]
  179. [heading Non-member function `begin( unbuffered_channel< T > &)`]
  180. template< typename T >
  181. unbuffered_channel< T >::iterator begin( unbuffered_channel< T > &);
  182. [variablelist
  183. [[Returns:] [Returns a range-iterator (input-iterator).]]
  184. ]
  185. [heading Non-member function `end( unbuffered_channel< T > &)`]
  186. template< typename T >
  187. unbuffered_channel< R >::iterator end( unbuffered_channel< T > &);
  188. [variablelist
  189. [[Returns:] [Returns an end range-iterator (input-iterator).]]
  190. ]
  191. [endsect]