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