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
operator =(push_coroutine && other)55 push_coroutine & operator=( push_coroutine && other) noexcept {
56 if ( this == & other) return * this;
57 std::swap( cb_, other.cb_);
58 return * this;
59 }
60
61 push_coroutine & operator()( T const&);
62
63 push_coroutine & operator()( T &&);
64
65 explicit operator bool() const noexcept;
66
67 bool operator!() const noexcept;
68
69 class iterator {
70 private:
71 push_coroutine< T > * c_{ nullptr };
72
73 public:
74 typedef std::output_iterator_tag iterator_category;
75 typedef void value_type;
76 typedef void difference_type;
77 typedef void pointer;
78 typedef void reference;
79
80 iterator() noexcept = default;
81
iterator(push_coroutine<T> * c)82 explicit iterator( push_coroutine< T > * c) noexcept :
83 c_{ c } {
84 }
85
operator =(T t)86 iterator & operator=( T t) {
87 BOOST_ASSERT( nullptr != c_);
88 if ( ! ( * c_)( t) ) {
89 c_ = nullptr;
90 }
91 return * this;
92 }
93
operator ==(iterator const & other) const94 bool operator==( iterator const& other) const noexcept {
95 return other.c_ == c_;
96 }
97
operator !=(iterator const & other) const98 bool operator!=( iterator const& other) const noexcept {
99 return other.c_ != c_;
100 }
101
operator *()102 iterator & operator*() noexcept {
103 return * this;
104 }
105
operator ++()106 iterator & operator++() noexcept {
107 return * this;
108 }
109 };
110 };
111
112 template< typename T >
113 class push_coroutine< T & > {
114 private:
115 template< typename X >
116 friend class pull_coroutine;
117
118 struct control_block;
119
120 control_block * cb_;
121
122 explicit push_coroutine( control_block *) noexcept;
123
124 public:
125 template< typename Fn,
126 typename = detail::disable_overload< push_coroutine, Fn >
127 >
128 explicit push_coroutine( Fn &&);
129
130 template< typename StackAllocator, typename Fn >
131 push_coroutine( StackAllocator &&, Fn &&);
132
133 ~push_coroutine();
134
135 push_coroutine( push_coroutine const&) = delete;
136 push_coroutine & operator=( push_coroutine const&) = delete;
137
138 push_coroutine( push_coroutine &&) noexcept;
139
operator =(push_coroutine && other)140 push_coroutine & operator=( push_coroutine && other) noexcept {
141 if ( this == & other) return * this;
142 std::swap( cb_, other.cb_);
143 return * this;
144 }
145
146 push_coroutine & operator()( T &);
147
148 explicit operator bool() const noexcept;
149
150 bool operator!() const noexcept;
151
152 class iterator {
153 private:
154 push_coroutine< T & > * c_{ nullptr };
155
156 public:
157 typedef std::output_iterator_tag iterator_category;
158 typedef void value_type;
159 typedef void difference_type;
160 typedef void pointer;
161 typedef void reference;
162
163 iterator() noexcept = default;
164
iterator(push_coroutine<T &> * c)165 explicit iterator( push_coroutine< T & > * c) noexcept :
166 c_{ c } {
167 }
168
operator =(T & t)169 iterator & operator=( T & t) {
170 BOOST_ASSERT( nullptr != c_);
171 if ( ! ( * c_)( t) ) {
172 c_ = nullptr;
173 }
174 return * this;
175 }
176
operator ==(iterator const & other) const177 bool operator==( iterator const& other) const noexcept {
178 return other.c_ == c_;
179 }
180
operator !=(iterator const & other) const181 bool operator!=( iterator const& other) const noexcept {
182 return other.c_ != c_;
183 }
184
operator *()185 iterator & operator*() noexcept {
186 return * this;
187 }
188
operator ++()189 iterator & operator++() noexcept {
190 return * this;
191 }
192 };
193 };
194
195 template<>
196 class push_coroutine< void > {
197 private:
198 template< typename X >
199 friend class pull_coroutine;
200
201 struct control_block;
202
203 control_block * cb_;
204
205 explicit push_coroutine( control_block *) noexcept;
206
207 public:
208 template< typename Fn,
209 typename = detail::disable_overload< push_coroutine, Fn >
210 >
211 explicit push_coroutine( Fn &&);
212
213 template< typename StackAllocator, typename Fn >
214 push_coroutine( StackAllocator &&, Fn &&);
215
216 ~push_coroutine();
217
218 push_coroutine( push_coroutine const&) = delete;
219 push_coroutine & operator=( push_coroutine const&) = delete;
220
221 push_coroutine( push_coroutine &&) noexcept;
222
operator =(push_coroutine && other)223 push_coroutine & operator=( push_coroutine && other) noexcept {
224 if ( this == & other) return * this;
225 std::swap( cb_, other.cb_);
226 return * this;
227 }
228
229 push_coroutine & operator()();
230
231 explicit operator bool() const noexcept;
232
233 bool operator!() const noexcept;
234 };
235
236 template< typename T >
237 typename push_coroutine< T >::iterator
begin(push_coroutine<T> & c)238 begin( push_coroutine< T > & c) {
239 return typename push_coroutine< T >::iterator( & c);
240 }
241
242 template< typename T >
243 typename push_coroutine< T >::iterator
end(push_coroutine<T> &)244 end( push_coroutine< T > &) {
245 return typename push_coroutine< T >::iterator();
246 }
247
248 }}}
249
250 #ifdef BOOST_HAS_ABI_HEADERS
251 # include BOOST_ABI_SUFFIX
252 #endif
253
254 #endif // BOOST_COROUTINES2_DETAIL_PUSH_COROUTINE_HPP
255