Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / coroutine2 / detail / push_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_PUSH_COROUTINE_HPP
8 #define BOOST_COROUTINES2_DETAIL_PUSH_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 push_coroutine {
29 private:
30     template< typename X >
31     friend class pull_coroutine;
32
33     struct control_block;
34
35     control_block   *   cb_;
36
37     explicit push_coroutine( control_block *) noexcept;
38
39 public:
40     template< typename Fn,
41               typename = detail::disable_overload< push_coroutine, Fn >
42     >
43     explicit push_coroutine( Fn &&);
44
45     template< typename StackAllocator, typename Fn >
46     push_coroutine( StackAllocator, Fn &&);
47
48     ~push_coroutine();
49
50     push_coroutine( push_coroutine const&) = delete;
51     push_coroutine & operator=( push_coroutine const&) = delete;
52
53     push_coroutine( push_coroutine &&) noexcept;
54
55     push_coroutine & operator=( push_coroutine && other) noexcept {
56         if ( this == & other) return * this;
57         cb_ = other.cb_;
58         other.cb_ = nullptr;
59         return * this;
60     }
61
62     push_coroutine & operator()( T const&);
63
64     push_coroutine & operator()( T &&);
65
66     explicit operator bool() const noexcept;
67
68     bool operator!() const noexcept;
69
70     class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > {
71     private:
72         push_coroutine< T > *   c_{ nullptr };
73
74     public:
75         iterator() noexcept = default;
76
77         explicit iterator( push_coroutine< T > * c) noexcept :
78             c_{ c } {
79         }
80
81         iterator & operator=( T t) {
82             BOOST_ASSERT( nullptr != c_);
83             if ( ! ( * c_)( t) ) {
84                 c_ = nullptr;
85             }
86             return * this;
87         }
88
89         bool operator==( iterator const& other) const noexcept {
90             return other.c_ == c_;
91         }
92
93         bool operator!=( iterator const& other) const noexcept {
94             return other.c_ != c_;
95         }
96
97         iterator & operator*() noexcept {
98             return * this;
99         }
100
101         iterator & operator++() noexcept {
102             return * this;
103         }
104     };
105 };
106
107 template< typename T >
108 class push_coroutine< T & > {
109 private:
110     template< typename X >
111     friend class pull_coroutine;
112
113     struct control_block;
114
115     control_block   *   cb_;
116
117     explicit push_coroutine( control_block *) noexcept;
118
119 public:
120     template< typename Fn,
121               typename = detail::disable_overload< push_coroutine, Fn >
122     >
123     explicit push_coroutine( Fn &&);
124
125     template< typename StackAllocator, typename Fn >
126     push_coroutine( StackAllocator, Fn &&);
127
128     ~push_coroutine();
129
130     push_coroutine( push_coroutine const&) = delete;
131     push_coroutine & operator=( push_coroutine const&) = delete;
132
133     push_coroutine( push_coroutine &&) noexcept;
134
135     push_coroutine & operator=( push_coroutine && other) noexcept {
136         if ( this == & other) return * this;
137         cb_ = other.cb_;
138         other.cb_ = nullptr;
139         return * this;
140     }
141
142     push_coroutine & operator()( T &);
143
144     explicit operator bool() const noexcept;
145
146     bool operator!() const noexcept;
147
148     class iterator : public std::iterator< std::output_iterator_tag, void, void, void, void > {
149     private:
150         push_coroutine< T & >   *   c_{ nullptr };
151
152     public:
153         iterator() noexcept = default;
154
155         explicit iterator( push_coroutine< T & > * c) noexcept :
156             c_{ c } {
157         }
158
159         iterator & operator=( T & t) {
160             BOOST_ASSERT( nullptr != c_);
161             if ( ! ( * c_)( t) ) {
162                 c_ = nullptr;
163             }
164             return * this;
165         }
166
167         bool operator==( iterator const& other) const noexcept {
168             return other.c_ == c_;
169         }
170
171         bool operator!=( iterator const& other) const noexcept {
172             return other.c_ != c_;
173         }
174
175         iterator & operator*() noexcept {
176             return * this;
177         }
178
179         iterator & operator++() noexcept {
180             return * this;
181         }
182     };
183 };
184
185 template<>
186 class push_coroutine< void > {
187 private:
188     template< typename X >
189     friend class pull_coroutine;
190
191     struct control_block;
192
193     control_block   *   cb_;
194
195     explicit push_coroutine( control_block *) noexcept;
196
197 public:
198     template< typename Fn,
199               typename = detail::disable_overload< push_coroutine, Fn >
200     >
201     explicit push_coroutine( Fn &&);
202
203     template< typename StackAllocator, typename Fn >
204     push_coroutine( StackAllocator, Fn &&);
205
206     ~push_coroutine();
207
208     push_coroutine( push_coroutine const&) = delete;
209     push_coroutine & operator=( push_coroutine const&) = delete;
210
211     push_coroutine( push_coroutine &&) noexcept;
212
213     push_coroutine & operator=( push_coroutine && other) noexcept {
214         if ( this == & other) return * this;
215         cb_ = other.cb_;
216         other.cb_ = nullptr;
217         return * this;
218     }
219
220     push_coroutine & operator()();
221
222     explicit operator bool() const noexcept;
223
224     bool operator!() const noexcept;
225 };
226
227 template< typename T >
228 typename push_coroutine< T >::iterator
229 begin( push_coroutine< T > & c) {
230     return typename push_coroutine< T >::iterator( & c);
231 }
232
233 template< typename T >
234 typename push_coroutine< T >::iterator
235 end( push_coroutine< T > &) {
236     return typename push_coroutine< T >::iterator();
237 }
238
239 }}}
240
241 #ifdef BOOST_HAS_ABI_HEADERS
242 #  include BOOST_ABI_SUFFIX
243 #endif
244
245 #endif // BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_HPP