Imported Upstream version 1.64.0
[platform/upstream/boost.git] / 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();
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         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();
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         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();
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