]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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() noexcept; | |
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 | constexpr 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( 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() noexcept; | |
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 | constexpr 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( 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() noexcept; | |
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 |