]> git.proxmox.com Git - ceph.git/blob - 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
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>
12 #include <boost/context/detail/config.hpp>
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
36 namespace boost {
37 namespace coroutines {
38 namespace detail {
39
40 struct 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
52 struct 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
64 template< typename PullCoro, typename R, typename Fn, typename StackAllocator >
65 class push_coroutine_object : private push_coroutine_context,
66 public push_coroutine_impl< R >
67 {
68 private:
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
86 public:
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 {}
131 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
132 catch ( abi::__forced_unwind const&)
133 { throw; }
134 #endif
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
151 template< typename PullCoro, typename R, typename Fn, typename StackAllocator >
152 class push_coroutine_object< PullCoro, R &, Fn, StackAllocator > : private push_coroutine_context,
153 public push_coroutine_impl< R & >
154 {
155 private:
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
173 public:
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 {}
218 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
219 catch ( abi::__forced_unwind const&)
220 { throw; }
221 #endif
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
238 template< typename PullCoro, typename Fn, typename StackAllocator >
239 class push_coroutine_object< PullCoro, void, Fn, StackAllocator > : private push_coroutine_context_void,
240 public push_coroutine_impl< void >
241 {
242 private:
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
260 public:
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 {}
305 #if defined( BOOST_CONTEXT_HAS_CXXABI_H )
306 catch ( abi::__forced_unwind const&)
307 { throw; }
308 #endif
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