File indexing completed on 2025-01-18 09:30:33
0001
0002
0003
0004
0005
0006
0007 #ifndef BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_HPP
0008 #define BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_HPP
0009
0010 #include <iterator>
0011 #include <type_traits>
0012
0013 #include <boost/assert.hpp>
0014 #include <boost/config.hpp>
0015
0016 #include <boost/coroutine2/detail/config.hpp>
0017 #include <boost/coroutine2/detail/disable_overload.hpp>
0018
0019 #ifdef BOOST_HAS_ABI_HEADERS
0020 # include BOOST_ABI_PREFIX
0021 #endif
0022
0023 namespace boost {
0024 namespace coroutines2 {
0025 namespace detail {
0026
0027 template< typename T >
0028 class pull_coroutine {
0029 private:
0030 template< typename X >
0031 friend class push_coroutine;
0032
0033 struct control_block;
0034
0035 control_block * cb_;
0036
0037 explicit pull_coroutine( control_block *) noexcept;
0038
0039 bool has_result_() const noexcept;
0040
0041 public:
0042 template< typename Fn,
0043 typename = detail::disable_overload< pull_coroutine, Fn >
0044 >
0045 explicit pull_coroutine( Fn &&);
0046
0047 template< typename StackAllocator, typename Fn >
0048 pull_coroutine( StackAllocator &&, Fn &&);
0049
0050 ~pull_coroutine();
0051
0052 pull_coroutine( pull_coroutine const&) = delete;
0053 pull_coroutine & operator=( pull_coroutine const&) = delete;
0054
0055 pull_coroutine( pull_coroutine &&) noexcept;
0056
0057 pull_coroutine & operator=( pull_coroutine && other) noexcept {
0058 std::swap( cb_, other.cb_);
0059 return * this;
0060 }
0061
0062 pull_coroutine & operator()();
0063
0064 explicit operator bool() const noexcept;
0065
0066 bool operator!() const noexcept;
0067
0068 T get() noexcept;
0069
0070 class iterator {
0071 private:
0072 pull_coroutine< T > * c_{ nullptr };
0073
0074 void fetch_() noexcept {
0075 BOOST_ASSERT( nullptr != c_);
0076 if ( ! ( * c_) ) {
0077 c_ = nullptr;
0078 return;
0079 }
0080 }
0081
0082 void increment_() {
0083 BOOST_ASSERT( nullptr != c_);
0084 BOOST_ASSERT( * c_);
0085 ( * c_)();
0086 fetch_();
0087 }
0088
0089 public:
0090 typedef std::input_iterator_tag iterator_category;
0091 typedef typename std::remove_reference< T >::type value_type;
0092 typedef std::ptrdiff_t difference_type;
0093 typedef value_type * pointer;
0094 typedef value_type & reference;
0095
0096 typedef pointer pointer_t;
0097 typedef reference reference_t;
0098
0099 iterator() noexcept = default;
0100
0101 explicit iterator( pull_coroutine< T > * c) noexcept :
0102 c_{ c } {
0103 fetch_();
0104 }
0105
0106 bool operator==( iterator const& other) const noexcept {
0107 return other.c_ == c_;
0108 }
0109
0110 bool operator!=( iterator const& other) const noexcept {
0111 return other.c_ != c_;
0112 }
0113
0114 iterator & operator++() {
0115 increment_();
0116 return * this;
0117 }
0118
0119 void operator++( int) {
0120 increment_();
0121 }
0122
0123 reference_t operator*() const noexcept {
0124 return c_->cb_->get();
0125 }
0126
0127 pointer_t operator->() const noexcept {
0128 return std::addressof( c_->cb_->get() );
0129 }
0130 };
0131
0132 friend class iterator;
0133
0134 iterator begin() { return iterator (this); }
0135 iterator end() { return iterator(); }
0136 };
0137
0138 template< typename T >
0139 class pull_coroutine< T & > {
0140 private:
0141 template< typename X >
0142 friend class push_coroutine;
0143
0144 struct control_block;
0145
0146 control_block * cb_;
0147
0148 explicit pull_coroutine( control_block *) noexcept;
0149
0150 bool has_result_() const noexcept;
0151
0152 public:
0153 template< typename Fn,
0154 typename = detail::disable_overload< pull_coroutine, Fn >
0155 >
0156 explicit pull_coroutine( Fn &&);
0157
0158 template< typename StackAllocator, typename Fn >
0159 pull_coroutine( StackAllocator &&, Fn &&);
0160
0161 ~pull_coroutine();
0162
0163 pull_coroutine( pull_coroutine const&) = delete;
0164 pull_coroutine & operator=( pull_coroutine const&) = delete;
0165
0166 pull_coroutine( pull_coroutine &&) noexcept;
0167
0168 pull_coroutine & operator=( pull_coroutine && other) noexcept {
0169 std::swap( cb_, other.cb_);
0170 return * this;
0171 }
0172
0173 pull_coroutine & operator()();
0174
0175 explicit operator bool() const noexcept;
0176
0177 bool operator!() const noexcept;
0178
0179 T & get() noexcept;
0180
0181 class iterator {
0182 private:
0183 pull_coroutine< T & > * c_{ nullptr };
0184
0185 void fetch_() noexcept {
0186 BOOST_ASSERT( nullptr != c_);
0187 if ( ! ( * c_) ) {
0188 c_ = nullptr;
0189 return;
0190 }
0191 }
0192
0193 void increment_() {
0194 BOOST_ASSERT( nullptr != c_);
0195 BOOST_ASSERT( * c_);
0196 ( * c_)();
0197 fetch_();
0198 }
0199
0200 public:
0201 typedef std::input_iterator_tag iterator_category;
0202 typedef typename std::remove_reference< T >::type value_type;
0203 typedef std::ptrdiff_t difference_type;
0204 typedef value_type * pointer;
0205 typedef value_type & reference;
0206
0207 typedef pointer pointer_t;
0208 typedef reference reference_t;
0209
0210 iterator() noexcept = default;
0211
0212 explicit iterator( pull_coroutine< T & > * c) noexcept :
0213 c_{ c } {
0214 fetch_();
0215 }
0216
0217 bool operator==( iterator const& other) const noexcept {
0218 return other.c_ == c_;
0219 }
0220
0221 bool operator!=( iterator const& other) const noexcept {
0222 return other.c_ != c_;
0223 }
0224
0225 iterator & operator++() {
0226 increment_();
0227 return * this;
0228 }
0229
0230 void operator++( int) {
0231 increment_();
0232 }
0233
0234 reference_t operator*() const noexcept {
0235 return c_->cb_->get();
0236 }
0237
0238 pointer_t operator->() const noexcept {
0239 return std::addressof( c_->cb_->get() );
0240 }
0241 };
0242
0243 friend class iterator;
0244
0245 iterator begin() { return iterator (this); }
0246 iterator end() { return iterator(); }
0247 };
0248
0249 template<>
0250 class pull_coroutine< void > {
0251 private:
0252 template< typename X >
0253 friend class push_coroutine;
0254
0255 struct control_block;
0256
0257 control_block * cb_;
0258
0259 explicit pull_coroutine( control_block *) noexcept;
0260
0261 public:
0262 template< typename Fn,
0263 typename = detail::disable_overload< pull_coroutine, Fn >
0264 >
0265 explicit pull_coroutine( Fn &&);
0266
0267 template< typename StackAllocator, typename Fn >
0268 pull_coroutine( StackAllocator &&, Fn &&);
0269
0270 ~pull_coroutine();
0271
0272 pull_coroutine( pull_coroutine const&) = delete;
0273 pull_coroutine & operator=( pull_coroutine const&) = delete;
0274
0275 pull_coroutine( pull_coroutine &&) noexcept;
0276
0277 pull_coroutine & operator=( pull_coroutine && other) noexcept {
0278 std::swap( cb_, other.cb_);
0279 return * this;
0280 }
0281
0282 pull_coroutine & operator()();
0283
0284 explicit operator bool() const noexcept;
0285
0286 bool operator!() const noexcept;
0287
0288
0289 };
0290
0291 template< typename T >
0292 typename pull_coroutine< T >::iterator
0293 begin( pull_coroutine< T > & c) {
0294 return typename pull_coroutine< T >::iterator( & c);
0295 }
0296
0297 template< typename T >
0298 typename pull_coroutine< T >::iterator
0299 end( pull_coroutine< T > &) {
0300 return typename pull_coroutine< T >::iterator();
0301 }
0302
0303 }}}
0304
0305 #ifdef BOOST_HAS_ABI_HEADERS
0306 # include BOOST_ABI_SUFFIX
0307 #endif
0308
0309 #endif