]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/coroutine/detail/push_coroutine_object.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / coroutine / detail / push_coroutine_object.hpp
CommitLineData
7c673cae
FG
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_PUSH_COROUTINE_OBJECT_H
8#define BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H
9
10#include <boost/assert.hpp>
11#include <boost/config.hpp>
92f5a8d4 12#include <boost/context/detail/config.hpp>
7c673cae
FG
13#include <boost/cstdint.hpp>
14#include <boost/exception_ptr.hpp>
15#include <boost/move/move.hpp>
16
17#include <boost/coroutine/detail/config.hpp>
18#include <boost/coroutine/detail/coroutine_context.hpp>
19#include <boost/coroutine/detail/flags.hpp>
20#include <boost/coroutine/detail/preallocated.hpp>
21#include <boost/coroutine/detail/push_coroutine_impl.hpp>
22#include <boost/coroutine/detail/trampoline_push.hpp>
23#include <boost/coroutine/exceptions.hpp>
24#include <boost/coroutine/flags.hpp>
25#include <boost/coroutine/stack_context.hpp>
26
27#ifdef BOOST_HAS_ABI_HEADERS
28# include BOOST_ABI_PREFIX
29#endif
30
31#if defined(BOOST_MSVC)
32# pragma warning(push)
33# pragma warning(disable:4355)
34#endif
35
36namespace boost {
37namespace coroutines {
38namespace detail {
39
40struct push_coroutine_context
41{
42 coroutine_context caller;
43 coroutine_context callee;
44
45 template< typename Coro >
46 push_coroutine_context( preallocated const& palloc, Coro *) :
47 caller(),
48 callee( trampoline_push< Coro >, palloc)
49 {}
50};
51
52struct push_coroutine_context_void
53{
54 coroutine_context caller;
55 coroutine_context callee;
56
57 template< typename Coro >
58 push_coroutine_context_void( preallocated const& palloc, Coro *) :
59 caller(),
60 callee( trampoline_push_void< Coro >, palloc)
61 {}
62};
63
64template< typename PullCoro, typename R, typename Fn, typename StackAllocator >
65class push_coroutine_object : private push_coroutine_context,
66 public push_coroutine_impl< R >
67{
68private:
69 typedef push_coroutine_context ctx_t;
70 typedef push_coroutine_impl< R > base_t;
71 typedef push_coroutine_object< PullCoro, R, Fn, StackAllocator > obj_t;
72
73 Fn fn_;
74 stack_context stack_ctx_;
75 StackAllocator stack_alloc_;
76
77 static void deallocate_( obj_t * obj)
78 {
79 stack_context stack_ctx( obj->stack_ctx_);
80 StackAllocator stack_alloc( obj->stack_alloc_);
81 obj->unwind_stack();
82 obj->~obj_t();
83 stack_alloc.deallocate( stack_ctx);
84 }
85
86public:
87#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
88 push_coroutine_object( Fn fn, attributes const& attrs,
89 preallocated const& palloc,
90 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
91 ctx_t( palloc, this),
92 base_t( & this->caller,
93 & this->callee,
94 stack_unwind == attrs.do_unwind),
95 fn_( fn),
96 stack_ctx_( palloc.sctx),
97 stack_alloc_( stack_alloc)
98 {}
99#endif
100
101 push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
102 preallocated const& palloc,
103 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
104 ctx_t( palloc, this),
105 base_t( & this->caller,
106 & this->callee,
107 stack_unwind == attrs.do_unwind),
108#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
109 fn_( fn),
110#else
111 fn_( boost::forward< Fn >( fn) ),
112#endif
113 stack_ctx_( palloc.sctx),
114 stack_alloc_( stack_alloc)
115 {}
116
117 void run( R * result)
118 {
119 BOOST_ASSERT( ! base_t::unwind_requested() );
120
121 base_t::flags_ |= flag_started;
122 base_t::flags_ |= flag_running;
123
124 // create push_coroutine
125 typename PullCoro::synth_type b( & this->callee, & this->caller, false, result);
126 PullCoro pull_coro( synthesized_t::syntesized, b);
127 try
128 { fn_( pull_coro); }
129 catch ( forced_unwind const&)
130 {}
92f5a8d4
TL
131#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
132 catch ( abi::__forced_unwind const&)
133 { throw; }
134#endif
7c673cae
FG
135 catch (...)
136 { base_t::except_ = current_exception(); }
137
138 base_t::flags_ |= flag_complete;
139 base_t::flags_ &= ~flag_running;
140 typename base_t::param_type to;
141 this->callee.jump(
142 this->caller,
143 & to);
144 BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
145 }
146
147 void destroy()
148 { deallocate_( this); }
149};
150
151template< typename PullCoro, typename R, typename Fn, typename StackAllocator >
152class push_coroutine_object< PullCoro, R &, Fn, StackAllocator > : private push_coroutine_context,
153 public push_coroutine_impl< R & >
154{
155private:
156 typedef push_coroutine_context ctx_t;
157 typedef push_coroutine_impl< R & > base_t;
158 typedef push_coroutine_object< PullCoro, R &, Fn, StackAllocator > obj_t;
159
160 Fn fn_;
161 stack_context stack_ctx_;
162 StackAllocator stack_alloc_;
163
164 static void deallocate_( obj_t * obj)
165 {
166 stack_context stack_ctx( obj->stack_ctx_);
167 StackAllocator stack_alloc( obj->stack_alloc_);
168 obj->unwind_stack();
169 obj->~obj_t();
170 stack_alloc.deallocate( stack_ctx);
171 }
172
173public:
174#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
175 push_coroutine_object( Fn fn, attributes const& attrs,
176 preallocated const& palloc,
177 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
178 ctx_t( palloc, this),
179 base_t( & this->caller,
180 & this->callee,
181 stack_unwind == attrs.do_unwind),
182 fn_( fn),
183 stack_ctx_( palloc.sctx),
184 stack_alloc_( stack_alloc)
185 {}
186#endif
187
188 push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
189 preallocated const& palloc,
190 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
191 ctx_t( palloc, this),
192 base_t( & this->caller,
193 & this->callee,
194 stack_unwind == attrs.do_unwind),
195#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
196 fn_( fn),
197#else
198 fn_( boost::forward< Fn >( fn) ),
199#endif
200 stack_ctx_( palloc.sctx),
201 stack_alloc_( stack_alloc)
202 {}
203
204 void run( R * result)
205 {
206 BOOST_ASSERT( ! base_t::unwind_requested() );
207
208 base_t::flags_ |= flag_started;
209 base_t::flags_ |= flag_running;
210
211 // create push_coroutine
212 typename PullCoro::synth_type b( & this->callee, & this->caller, false, result);
213 PullCoro push_coro( synthesized_t::syntesized, b);
214 try
215 { fn_( push_coro); }
216 catch ( forced_unwind const&)
217 {}
92f5a8d4
TL
218#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
219 catch ( abi::__forced_unwind const&)
220 { throw; }
221#endif
7c673cae
FG
222 catch (...)
223 { base_t::except_ = current_exception(); }
224
225 base_t::flags_ |= flag_complete;
226 base_t::flags_ &= ~flag_running;
227 typename base_t::param_type to;
228 this->callee.jump(
229 this->caller,
230 & to);
231 BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
232 }
233
234 void destroy()
235 { deallocate_( this); }
236};
237
238template< typename PullCoro, typename Fn, typename StackAllocator >
239class push_coroutine_object< PullCoro, void, Fn, StackAllocator > : private push_coroutine_context_void,
240 public push_coroutine_impl< void >
241{
242private:
243 typedef push_coroutine_context_void ctx_t;
244 typedef push_coroutine_impl< void > base_t;
245 typedef push_coroutine_object< PullCoro, void, Fn, StackAllocator > obj_t;
246
247 Fn fn_;
248 stack_context stack_ctx_;
249 StackAllocator stack_alloc_;
250
251 static void deallocate_( obj_t * obj)
252 {
253 stack_context stack_ctx( obj->stack_ctx_);
254 StackAllocator stack_alloc( obj->stack_alloc_);
255 obj->unwind_stack();
256 obj->~obj_t();
257 stack_alloc.deallocate( stack_ctx);
258 }
259
260public:
261#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
262 push_coroutine_object( Fn fn, attributes const& attrs,
263 preallocated const& palloc,
264 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
265 ctx_t( palloc, this),
266 base_t( & this->caller,
267 & this->callee,
268 stack_unwind == attrs.do_unwind),
269 fn_( fn),
270 stack_ctx_( palloc.sctx),
271 stack_alloc_( stack_alloc)
272 {}
273#endif
274
275 push_coroutine_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
276 preallocated const& palloc,
277 StackAllocator const& stack_alloc) BOOST_NOEXCEPT :
278 ctx_t( palloc, this),
279 base_t( & this->caller,
280 & this->callee,
281 stack_unwind == attrs.do_unwind),
282#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
283 fn_( fn),
284#else
285 fn_( boost::forward< Fn >( fn) ),
286#endif
287 stack_ctx_( palloc.sctx),
288 stack_alloc_( stack_alloc)
289 {}
290
291 void run()
292 {
293 BOOST_ASSERT( ! base_t::unwind_requested() );
294
295 base_t::flags_ |= flag_started;
296 base_t::flags_ |= flag_running;
297
298 // create push_coroutine
299 typename PullCoro::synth_type b( & this->callee, & this->caller, false);
300 PullCoro push_coro( synthesized_t::syntesized, b);
301 try
302 { fn_( push_coro); }
303 catch ( forced_unwind const&)
304 {}
92f5a8d4
TL
305#if defined( BOOST_CONTEXT_HAS_CXXABI_H )
306 catch ( abi::__forced_unwind const&)
307 { throw; }
308#endif
7c673cae
FG
309 catch (...)
310 { base_t::except_ = current_exception(); }
311
312 base_t::flags_ |= flag_complete;
313 base_t::flags_ &= ~flag_running;
314 typename base_t::param_type to;
315 this->callee.jump(
316 this->caller,
317 & to);
318 BOOST_ASSERT_MSG( false, "pull_coroutine is complete");
319 }
320
321 void destroy()
322 { deallocate_( this); }
323};
324
325}}}
326
327#if defined(BOOST_MSVC)
328# pragma warning(pop)
329#endif
330
331#ifdef BOOST_HAS_ABI_HEADERS
332# include BOOST_ABI_SUFFIX
333#endif
334
335#endif // BOOST_COROUTINES_DETAIL_PUSH_COROUTINE_OBJECT_H