push_coroutine.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. // Copyright Oliver Kowalke 2014.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_HPP
  6. #define BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_HPP
  7. #include <iterator>
  8. #include <type_traits>
  9. #include <boost/assert.hpp>
  10. #include <boost/config.hpp>
  11. #include <boost/coroutine2/detail/config.hpp>
  12. #include <boost/coroutine2/detail/disable_overload.hpp>
  13. #ifdef BOOST_HAS_ABI_HEADERS
  14. # include BOOST_ABI_PREFIX
  15. #endif
  16. namespace boost {
  17. namespace coroutines2 {
  18. namespace detail {
  19. template< typename T >
  20. class push_coroutine {
  21. private:
  22. template< typename X >
  23. friend class pull_coroutine;
  24. struct control_block;
  25. control_block * cb_;
  26. explicit push_coroutine( control_block *) noexcept;
  27. public:
  28. template< typename Fn,
  29. typename = detail::disable_overload< push_coroutine, Fn >
  30. >
  31. explicit push_coroutine( Fn &&);
  32. template< typename StackAllocator, typename Fn >
  33. push_coroutine( StackAllocator &&, Fn &&);
  34. ~push_coroutine();
  35. push_coroutine( push_coroutine const&) = delete;
  36. push_coroutine & operator=( push_coroutine const&) = delete;
  37. push_coroutine( push_coroutine &&) noexcept;
  38. push_coroutine & operator=( push_coroutine && other) noexcept {
  39. if ( this == & other) return * this;
  40. std::swap( cb_, other.cb_);
  41. return * this;
  42. }
  43. push_coroutine & operator()( T const&);
  44. push_coroutine & operator()( T &&);
  45. explicit operator bool() const noexcept;
  46. bool operator!() const noexcept;
  47. class iterator {
  48. private:
  49. push_coroutine< T > * c_{ nullptr };
  50. public:
  51. typedef std::output_iterator_tag iterator_category;
  52. typedef void value_type;
  53. typedef void difference_type;
  54. typedef void pointer;
  55. typedef void reference;
  56. iterator() noexcept = default;
  57. explicit iterator( push_coroutine< T > * c) noexcept :
  58. c_{ c } {
  59. }
  60. iterator & operator=( T t) {
  61. BOOST_ASSERT( nullptr != c_);
  62. if ( ! ( * c_)( t) ) {
  63. c_ = nullptr;
  64. }
  65. return * this;
  66. }
  67. bool operator==( iterator const& other) const noexcept {
  68. return other.c_ == c_;
  69. }
  70. bool operator!=( iterator const& other) const noexcept {
  71. return other.c_ != c_;
  72. }
  73. iterator & operator*() noexcept {
  74. return * this;
  75. }
  76. iterator & operator++() noexcept {
  77. return * this;
  78. }
  79. };
  80. };
  81. template< typename T >
  82. class push_coroutine< T & > {
  83. private:
  84. template< typename X >
  85. friend class pull_coroutine;
  86. struct control_block;
  87. control_block * cb_;
  88. explicit push_coroutine( control_block *) noexcept;
  89. public:
  90. template< typename Fn,
  91. typename = detail::disable_overload< push_coroutine, Fn >
  92. >
  93. explicit push_coroutine( Fn &&);
  94. template< typename StackAllocator, typename Fn >
  95. push_coroutine( StackAllocator &&, Fn &&);
  96. ~push_coroutine();
  97. push_coroutine( push_coroutine const&) = delete;
  98. push_coroutine & operator=( push_coroutine const&) = delete;
  99. push_coroutine( push_coroutine &&) noexcept;
  100. push_coroutine & operator=( push_coroutine && other) noexcept {
  101. if ( this == & other) return * this;
  102. std::swap( cb_, other.cb_);
  103. return * this;
  104. }
  105. push_coroutine & operator()( T &);
  106. explicit operator bool() const noexcept;
  107. bool operator!() const noexcept;
  108. class iterator {
  109. private:
  110. push_coroutine< T & > * c_{ nullptr };
  111. public:
  112. typedef std::output_iterator_tag iterator_category;
  113. typedef void value_type;
  114. typedef void difference_type;
  115. typedef void pointer;
  116. typedef void reference;
  117. iterator() noexcept = default;
  118. explicit iterator( push_coroutine< T & > * c) noexcept :
  119. c_{ c } {
  120. }
  121. iterator & operator=( T & t) {
  122. BOOST_ASSERT( nullptr != c_);
  123. if ( ! ( * c_)( t) ) {
  124. c_ = nullptr;
  125. }
  126. return * this;
  127. }
  128. bool operator==( iterator const& other) const noexcept {
  129. return other.c_ == c_;
  130. }
  131. bool operator!=( iterator const& other) const noexcept {
  132. return other.c_ != c_;
  133. }
  134. iterator & operator*() noexcept {
  135. return * this;
  136. }
  137. iterator & operator++() noexcept {
  138. return * this;
  139. }
  140. };
  141. };
  142. template<>
  143. class push_coroutine< void > {
  144. private:
  145. template< typename X >
  146. friend class pull_coroutine;
  147. struct control_block;
  148. control_block * cb_;
  149. explicit push_coroutine( control_block *) noexcept;
  150. public:
  151. template< typename Fn,
  152. typename = detail::disable_overload< push_coroutine, Fn >
  153. >
  154. explicit push_coroutine( Fn &&);
  155. template< typename StackAllocator, typename Fn >
  156. push_coroutine( StackAllocator &&, Fn &&);
  157. ~push_coroutine();
  158. push_coroutine( push_coroutine const&) = delete;
  159. push_coroutine & operator=( push_coroutine const&) = delete;
  160. push_coroutine( push_coroutine &&) noexcept;
  161. push_coroutine & operator=( push_coroutine && other) noexcept {
  162. if ( this == & other) return * this;
  163. std::swap( cb_, other.cb_);
  164. return * this;
  165. }
  166. push_coroutine & operator()();
  167. explicit operator bool() const noexcept;
  168. bool operator!() const noexcept;
  169. };
  170. template< typename T >
  171. typename push_coroutine< T >::iterator
  172. begin( push_coroutine< T > & c) {
  173. return typename push_coroutine< T >::iterator( & c);
  174. }
  175. template< typename T >
  176. typename push_coroutine< T >::iterator
  177. end( push_coroutine< T > &) {
  178. return typename push_coroutine< T >::iterator();
  179. }
  180. }}}
  181. #ifdef BOOST_HAS_ABI_HEADERS
  182. # include BOOST_ABI_SUFFIX
  183. #endif
  184. #endif // BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_HPP