]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/coroutine/detail/pull_coroutine_impl.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / coroutine / detail / pull_coroutine_impl.hpp
1
2 // Copyright Oliver Kowalke 2009.
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_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
8 #define BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H
9
10 #include <boost/assert.hpp>
11 #include <boost/config.hpp>
12 #include <boost/exception_ptr.hpp>
13 #include <boost/throw_exception.hpp>
14 #include <boost/utility.hpp>
15
16 #include <boost/coroutine/detail/config.hpp>
17 #include <boost/coroutine/detail/coroutine_context.hpp>
18 #include <boost/coroutine/detail/flags.hpp>
19 #include <boost/coroutine/detail/parameters.hpp>
20 #include <boost/coroutine/detail/trampoline_pull.hpp>
21 #include <boost/coroutine/exceptions.hpp>
22
23 #ifdef BOOST_HAS_ABI_HEADERS
24 # include BOOST_ABI_PREFIX
25 #endif
26
27 namespace boost {
28 namespace coroutines {
29
30 struct stack_context;
31
32 namespace detail {
33
34 template< typename R >
35 class pull_coroutine_impl : private noncopyable
36 {
37 protected:
38 int flags_;
39 exception_ptr except_;
40 coroutine_context * caller_;
41 coroutine_context * callee_;
42 R * result_;
43
44 public:
45 typedef parameters< R > param_type;
46
47 pull_coroutine_impl( coroutine_context * caller,
48 coroutine_context * callee,
49 bool unwind) :
50 flags_( 0),
51 except_(),
52 caller_( caller),
53 callee_( callee),
54 result_( 0)
55 {
56 if ( unwind) flags_ |= flag_force_unwind;
57 }
58
59 pull_coroutine_impl( coroutine_context * caller,
60 coroutine_context * callee,
61 bool unwind,
62 R * result) :
63 flags_( 0),
64 except_(),
65 caller_( caller),
66 callee_( callee),
67 result_( result)
68 {
69 if ( unwind) flags_ |= flag_force_unwind;
70 }
71
72 virtual ~pull_coroutine_impl() {}
73
74 bool force_unwind() const BOOST_NOEXCEPT
75 { return 0 != ( flags_ & flag_force_unwind); }
76
77 bool unwind_requested() const BOOST_NOEXCEPT
78 { return 0 != ( flags_ & flag_unwind_stack); }
79
80 bool is_started() const BOOST_NOEXCEPT
81 { return 0 != ( flags_ & flag_started); }
82
83 bool is_running() const BOOST_NOEXCEPT
84 { return 0 != ( flags_ & flag_running); }
85
86 bool is_complete() const BOOST_NOEXCEPT
87 { return 0 != ( flags_ & flag_complete); }
88
89 void unwind_stack() BOOST_NOEXCEPT
90 {
91 if ( is_started() && ! is_complete() && force_unwind() )
92 {
93 flags_ |= flag_unwind_stack;
94 param_type to( unwind_t::force_unwind);
95 caller_->jump(
96 * callee_,
97 & to);
98 flags_ &= ~flag_unwind_stack;
99
100 BOOST_ASSERT( is_complete() );
101 }
102 }
103
104 void pull()
105 {
106 BOOST_ASSERT( ! is_running() );
107 BOOST_ASSERT( ! is_complete() );
108
109 flags_ |= flag_running;
110 param_type to( this);
111 param_type * from(
112 static_cast< param_type * >(
113 caller_->jump(
114 * callee_,
115 & to) ) );
116 flags_ &= ~flag_running;
117 result_ = from->data;
118 if ( from->do_unwind) throw forced_unwind();
119 if ( except_) rethrow_exception( except_);
120 }
121
122 bool has_result() const
123 { return 0 != result_; }
124
125 R get() const
126 {
127 if ( ! has_result() )
128 boost::throw_exception(
129 invalid_result() );
130 return * result_;
131 }
132
133 R * get_pointer() const
134 {
135 if ( ! has_result() )
136 boost::throw_exception(
137 invalid_result() );
138 return result_;
139 }
140
141 virtual void destroy() = 0;
142 };
143
144 template< typename R >
145 class pull_coroutine_impl< R & > : private noncopyable
146 {
147 protected:
148 int flags_;
149 exception_ptr except_;
150 coroutine_context * caller_;
151 coroutine_context * callee_;
152 R * result_;
153
154 public:
155 typedef parameters< R & > param_type;
156
157 pull_coroutine_impl( coroutine_context * caller,
158 coroutine_context * callee,
159 bool unwind) :
160 flags_( 0),
161 except_(),
162 caller_( caller),
163 callee_( callee),
164 result_( 0)
165 {
166 if ( unwind) flags_ |= flag_force_unwind;
167 }
168
169 pull_coroutine_impl( coroutine_context * caller,
170 coroutine_context * callee,
171 bool unwind,
172 R * result) :
173 flags_( 0),
174 except_(),
175 caller_( caller),
176 callee_( callee),
177 result_( result)
178 {
179 if ( unwind) flags_ |= flag_force_unwind;
180 }
181
182 virtual ~pull_coroutine_impl() {}
183
184 bool force_unwind() const BOOST_NOEXCEPT
185 { return 0 != ( flags_ & flag_force_unwind); }
186
187 bool unwind_requested() const BOOST_NOEXCEPT
188 { return 0 != ( flags_ & flag_unwind_stack); }
189
190 bool is_started() const BOOST_NOEXCEPT
191 { return 0 != ( flags_ & flag_started); }
192
193 bool is_running() const BOOST_NOEXCEPT
194 { return 0 != ( flags_ & flag_running); }
195
196 bool is_complete() const BOOST_NOEXCEPT
197 { return 0 != ( flags_ & flag_complete); }
198
199 void unwind_stack() BOOST_NOEXCEPT
200 {
201 if ( is_started() && ! is_complete() && force_unwind() )
202 {
203 flags_ |= flag_unwind_stack;
204 param_type to( unwind_t::force_unwind);
205 caller_->jump(
206 * callee_,
207 & to);
208 flags_ &= ~flag_unwind_stack;
209
210 BOOST_ASSERT( is_complete() );
211 }
212 }
213
214 void pull()
215 {
216 BOOST_ASSERT( ! is_running() );
217 BOOST_ASSERT( ! is_complete() );
218
219 flags_ |= flag_running;
220 param_type to( this);
221 param_type * from(
222 static_cast< param_type * >(
223 caller_->jump(
224 * callee_,
225 & to) ) );
226 flags_ &= ~flag_running;
227 result_ = from->data;
228 if ( from->do_unwind) throw forced_unwind();
229 if ( except_) rethrow_exception( except_);
230 }
231
232 bool has_result() const
233 { return 0 != result_; }
234
235 R & get() const
236 {
237 if ( ! has_result() )
238 boost::throw_exception(
239 invalid_result() );
240 return * result_;
241 }
242
243 R * get_pointer() const
244 {
245 if ( ! has_result() )
246 boost::throw_exception(
247 invalid_result() );
248 return result_;
249 }
250
251 virtual void destroy() = 0;
252 };
253
254 template<>
255 class pull_coroutine_impl< void > : private noncopyable
256 {
257 protected:
258 int flags_;
259 exception_ptr except_;
260 coroutine_context * caller_;
261 coroutine_context * callee_;
262
263 public:
264 typedef parameters< void > param_type;
265
266 pull_coroutine_impl( coroutine_context * caller,
267 coroutine_context * callee,
268 bool unwind) :
269 flags_( 0),
270 except_(),
271 caller_( caller),
272 callee_( callee)
273 {
274 if ( unwind) flags_ |= flag_force_unwind;
275 }
276
277 virtual ~pull_coroutine_impl() {}
278
279 inline bool force_unwind() const BOOST_NOEXCEPT
280 { return 0 != ( flags_ & flag_force_unwind); }
281
282 inline bool unwind_requested() const BOOST_NOEXCEPT
283 { return 0 != ( flags_ & flag_unwind_stack); }
284
285 inline bool is_started() const BOOST_NOEXCEPT
286 { return 0 != ( flags_ & flag_started); }
287
288 inline bool is_running() const BOOST_NOEXCEPT
289 { return 0 != ( flags_ & flag_running); }
290
291 inline bool is_complete() const BOOST_NOEXCEPT
292 { return 0 != ( flags_ & flag_complete); }
293
294 inline void unwind_stack() BOOST_NOEXCEPT
295 {
296 if ( is_started() && ! is_complete() && force_unwind() )
297 {
298 flags_ |= flag_unwind_stack;
299 param_type to( unwind_t::force_unwind);
300 caller_->jump(
301 * callee_,
302 & to);
303 flags_ &= ~flag_unwind_stack;
304
305 BOOST_ASSERT( is_complete() );
306 }
307 }
308
309 inline void pull()
310 {
311 BOOST_ASSERT( ! is_running() );
312 BOOST_ASSERT( ! is_complete() );
313
314 flags_ |= flag_running;
315 param_type to( this);
316 param_type * from(
317 static_cast< param_type * >(
318 caller_->jump(
319 * callee_,
320 & to) ) );
321 flags_ &= ~flag_running;
322 if ( from->do_unwind) throw forced_unwind();
323 if ( except_) rethrow_exception( except_);
324 }
325
326 virtual void destroy() = 0;
327 };
328
329 }}}
330
331 #ifdef BOOST_HAS_ABI_HEADERS
332 # include BOOST_ABI_SUFFIX
333 #endif
334
335 #endif // BOOST_COROUTINES_DETAIL_PULL_COROUTINE_IMPL_H