1
2// Copyright Oliver Kowalke 2014.
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#ifndef BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_HPP
8#define BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_HPP
9
10#include <iterator>
11#include <type_traits>
12
13#include <boost/assert.hpp>
14#include <boost/config.hpp>
15
16#include <boost/coroutine2/detail/config.hpp>
17#include <boost/coroutine2/detail/disable_overload.hpp>
18
19#ifdef BOOST_HAS_ABI_HEADERS
20# include BOOST_ABI_PREFIX
21#endif
22
23namespace boost {
24namespace coroutines2 {
25namespace detail {
26
27template< typename T >
28class pull_coroutine {
29private:
30 template< typename X >
31 friend class push_coroutine;
32
33 struct control_block;
34
35 control_block * cb_;
36
37 explicit pull_coroutine( control_block *) noexcept;
38
39 bool has_result_() const noexcept;
40
41public:
42 template< typename Fn,
43 typename = detail::disable_overload< pull_coroutine, Fn >
44 >
45 explicit pull_coroutine( Fn &&);
46
47 template< typename StackAllocator, typename Fn >
48 pull_coroutine( StackAllocator &&, Fn &&);
49
50 ~pull_coroutine();
51
52 pull_coroutine( pull_coroutine const&) = delete;
53 pull_coroutine & operator=( pull_coroutine const&) = delete;
54
55 pull_coroutine( pull_coroutine &&) noexcept;
56
57 pull_coroutine & operator=( pull_coroutine && other) noexcept {
58 std::swap( cb_, other.cb_);
59 return * this;
60 }
61
62 pull_coroutine & operator()();
63
64 explicit operator bool() const noexcept;
65
66 bool operator!() const noexcept;
67
68 T get() noexcept;
69
70 class iterator {
71 private:
72 pull_coroutine< T > * c_{ nullptr };
73
74 void fetch_() noexcept {
75 BOOST_ASSERT( nullptr != c_);
76 if ( ! ( * c_) ) {
77 c_ = nullptr;
78 return;
79 }
80 }
81
82 void increment_() {
83 BOOST_ASSERT( nullptr != c_);
84 BOOST_ASSERT( * c_);
85 ( * c_)();
86 fetch_();
87 }
88
89 public:
90 typedef std::input_iterator_tag iterator_category;
91 typedef typename std::remove_reference< T >::type value_type;
92 typedef std::ptrdiff_t difference_type;
93 typedef value_type * pointer;
94 typedef value_type & reference;
95
96 typedef pointer pointer_t;
97 typedef reference reference_t;
98
99 iterator() noexcept = default;
100
101 explicit iterator( pull_coroutine< T > * c) noexcept :
102 c_{ c } {
103 fetch_();
104 }
105
106 bool operator==( iterator const& other) const noexcept {
107 return other.c_ == c_;
108 }
109
110 bool operator!=( iterator const& other) const noexcept {
111 return other.c_ != c_;
112 }
113
114 iterator & operator++() {
115 increment_();
116 return * this;
117 }
118
119 void operator++( int) {
120 increment_();
121 }
122
123 reference_t operator*() const noexcept {
124 return c_->cb_->get();
125 }
126
127 pointer_t operator->() const noexcept {
128 return std::addressof( c_->cb_->get() );
129 }
130 };
131
132 friend class iterator;
133
134 iterator begin() { return iterator (this); }
135 iterator end() { return iterator(); }
136};
137
138template< typename T >
139class pull_coroutine< T & > {
140private:
141 template< typename X >
142 friend class push_coroutine;
143
144 struct control_block;
145
146 control_block * cb_;
147
148 explicit pull_coroutine( control_block *) noexcept;
149
150 bool has_result_() const noexcept;
151
152public:
153 template< typename Fn,
154 typename = detail::disable_overload< pull_coroutine, Fn >
155 >
156 explicit pull_coroutine( Fn &&);
157
158 template< typename StackAllocator, typename Fn >
159 pull_coroutine( StackAllocator &&, Fn &&);
160
161 ~pull_coroutine();
162
163 pull_coroutine( pull_coroutine const&) = delete;
164 pull_coroutine & operator=( pull_coroutine const&) = delete;
165
166 pull_coroutine( pull_coroutine &&) noexcept;
167
168 pull_coroutine & operator=( pull_coroutine && other) noexcept {
169 std::swap( cb_, other.cb_);
170 return * this;
171 }
172
173 pull_coroutine & operator()();
174
175 explicit operator bool() const noexcept;
176
177 bool operator!() const noexcept;
178
179 T & get() noexcept;
180
181 class iterator {
182 private:
183 pull_coroutine< T & > * c_{ nullptr };
184
185 void fetch_() noexcept {
186 BOOST_ASSERT( nullptr != c_);
187 if ( ! ( * c_) ) {
188 c_ = nullptr;
189 return;
190 }
191 }
192
193 void increment_() {
194 BOOST_ASSERT( nullptr != c_);
195 BOOST_ASSERT( * c_);
196 ( * c_)();
197 fetch_();
198 }
199
200 public:
201 typedef std::input_iterator_tag iterator_category;
202 typedef typename std::remove_reference< T >::type value_type;
203 typedef std::ptrdiff_t difference_type;
204 typedef value_type * pointer;
205 typedef value_type & reference;
206
207 typedef pointer pointer_t;
208 typedef reference reference_t;
209
210 iterator() noexcept = default;
211
212 explicit iterator( pull_coroutine< T & > * c) noexcept :
213 c_{ c } {
214 fetch_();
215 }
216
217 bool operator==( iterator const& other) const noexcept {
218 return other.c_ == c_;
219 }
220
221 bool operator!=( iterator const& other) const noexcept {
222 return other.c_ != c_;
223 }
224
225 iterator & operator++() {
226 increment_();
227 return * this;
228 }
229
230 void operator++( int) {
231 increment_();
232 }
233
234 reference_t operator*() const noexcept {
235 return c_->cb_->get();
236 }
237
238 pointer_t operator->() const noexcept {
239 return std::addressof( c_->cb_->get() );
240 }
241 };
242
243 friend class iterator;
244
245 iterator begin() { return iterator (this); }
246 iterator end() { return iterator(); }
247};
248
249template<>
250class pull_coroutine< void > {
251private:
252 template< typename X >
253 friend class push_coroutine;
254
255 struct control_block;
256
257 control_block * cb_;
258
259 explicit pull_coroutine( control_block *) noexcept;
260
261public:
262 template< typename Fn,
263 typename = detail::disable_overload< pull_coroutine, Fn >
264 >
265 explicit pull_coroutine( Fn &&);
266
267 template< typename StackAllocator, typename Fn >
268 pull_coroutine( StackAllocator &&, Fn &&);
269
270 ~pull_coroutine();
271
272 pull_coroutine( pull_coroutine const&) = delete;
273 pull_coroutine & operator=( pull_coroutine const&) = delete;
274
275 pull_coroutine( pull_coroutine &&) noexcept;
276
277 pull_coroutine & operator=( pull_coroutine && other) noexcept {
278 std::swap( a&: cb_, b&: other.cb_);
279 return * this;
280 }
281
282 pull_coroutine & operator()();
283
284 explicit operator bool() const noexcept;
285
286 bool operator!() const noexcept;
287
288
289};
290
291template< typename T >
292typename pull_coroutine< T >::iterator
293begin( pull_coroutine< T > & c) {
294 return typename pull_coroutine< T >::iterator( & c);
295}
296
297template< typename T >
298typename pull_coroutine< T >::iterator
299end( pull_coroutine< T > &) {
300 return typename pull_coroutine< T >::iterator();
301}
302
303}}}
304
305#ifdef BOOST_HAS_ABI_HEADERS
306# include BOOST_ABI_SUFFIX
307#endif
308
309#endif // BOOST_COROUTINES2_DETAIL_PULL_COROUTINE_HPP
310

source code of boost/libs/coroutine2/include/boost/coroutine2/detail/pull_coroutine.hpp