]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/context/execution_context_v2_void.ipp
Add patch for failing prerm scripts
[ceph.git] / ceph / src / boost / boost / context / execution_context_v2_void.ipp
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 namespace detail {
8
9 template< typename Ctx, typename Fn >
10 transfer_t ecv2_context_ontop_void( transfer_t);
11
12 template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
13 fcontext_t ecv2_context_create_void( StackAlloc &&, Fn &&, Params && ...);
14
15 template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
16 fcontext_t ecv2_context_create_void( preallocated, StackAlloc &&, Fn &&, Params && ...);
17
18 template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
19 class ecv2_record_void {
20 private:
21 typename std::decay< StackAlloc >::type salloc_;
22 stack_context sctx_;
23 typename std::decay< Fn >::type fn_;
24 std::tuple< typename std::decay< Params >::type ... > params_;
25
26 static void destroy( ecv2_record_void * p) noexcept {
27 typename std::decay< StackAlloc >::type salloc = std::move( p->salloc_);
28 stack_context sctx = p->sctx_;
29 // deallocate record
30 p->~ecv2_record_void();
31 // destroy stack with stack allocator
32 salloc.deallocate( sctx);
33 }
34
35 public:
36 ecv2_record_void( stack_context sctx, StackAlloc && salloc,
37 Fn && fn, Params && ... params) noexcept :
38 salloc_( std::forward< StackAlloc >( salloc) ),
39 sctx_( sctx),
40 fn_( std::forward< Fn >( fn) ),
41 params_( std::forward< Params >( params) ... ) {
42 }
43
44 ecv2_record_void( ecv2_record_void const&) = delete;
45 ecv2_record_void & operator=( ecv2_record_void const&) = delete;
46
47 void deallocate() noexcept {
48 destroy( this);
49 }
50
51 transfer_t run( transfer_t t) {
52 Ctx from{ t.fctx };
53 // invoke context-function
54 #if defined(BOOST_NO_CXX17_STD_APPLY)
55 Ctx cc = boost::context::detail::apply( fn_, std::tuple_cat( params_, std::forward_as_tuple( std::move( from) ) ) );
56 #else
57 Ctx cc = std::apply( fn_, std::tuple_cat( params_, std::forward_as_tuple( std::move( from) ) ) );
58 #endif
59 return { exchange( cc.fctx_, nullptr), nullptr };
60 }
61 };
62
63 }
64
65 inline namespace v2 {
66
67 template<>
68 class execution_context< void > {
69 private:
70 friend class ontop_error;
71
72 template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
73 friend class detail::ecv2_record_void;
74
75 template< typename Ctx, typename Fn >
76 friend detail::transfer_t detail::ecv2_context_ontop_void( detail::transfer_t);
77
78 detail::fcontext_t fctx_{ nullptr };
79
80 execution_context( detail::fcontext_t fctx) noexcept :
81 fctx_( fctx) {
82 }
83
84 public:
85 execution_context() noexcept = default;
86
87 #if defined(BOOST_USE_SEGMENTED_STACKS)
88 // segmented-stack requires to preserve the segments of the `current` context
89 // which is not possible (no global pointer to current context)
90 template< typename Fn, typename ... Params >
91 execution_context( std::allocator_arg_t, segmented_stack, Fn &&, Params && ...) = delete;
92
93 template< typename Fn, typename ... Params >
94 execution_context( std::allocator_arg_t, preallocated, segmented_stack, Fn &&, Params && ...) = delete;
95 #else
96 template< typename Fn,
97 typename ... Params,
98 typename = detail::disable_overload< execution_context, Fn >
99 >
100 execution_context( Fn && fn, Params && ... params) :
101 // deferred execution of fn and its arguments
102 // arguments are stored in std::tuple<>
103 // non-type template parameter pack via std::index_sequence_for<>
104 // preserves the number of arguments
105 // used to extract the function arguments from std::tuple<>
106 fctx_( detail::ecv2_context_create_void< execution_context >(
107 fixedsize_stack(),
108 std::forward< Fn >( fn),
109 std::forward< Params >( params) ... ) ) {
110 }
111
112 template< typename StackAlloc,
113 typename Fn,
114 typename ... Params
115 >
116 execution_context( std::allocator_arg_t, StackAlloc && salloc, Fn && fn, Params && ... params) :
117 // deferred execution of fn and its arguments
118 // arguments are stored in std::tuple<>
119 // non-type template parameter pack via std::index_sequence_for<>
120 // preserves the number of arguments
121 // used to extract the function arguments from std::tuple<>
122 fctx_( detail::ecv2_context_create_void< execution_context >(
123 std::forward< StackAlloc >( salloc),
124 std::forward< Fn >( fn),
125 std::forward< Params >( params) ... ) ) {
126 }
127
128 template< typename StackAlloc,
129 typename Fn,
130 typename ... Params
131 >
132 execution_context( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn, Params && ... params) :
133 // deferred execution of fn and its arguments
134 // arguments are stored in std::tuple<>
135 // non-type template parameter pack via std::index_sequence_for<>
136 // preserves the number of arguments
137 // used to extract the function arguments from std::tuple<>
138 fctx_( detail::ecv2_context_create_void< execution_context >(
139 palloc, std::forward< StackAlloc >( salloc),
140 std::forward< Fn >( fn),
141 std::forward< Params >( params) ... ) ) {
142 }
143 #endif
144
145 ~execution_context() {
146 if ( nullptr != fctx_) {
147 detail::ontop_fcontext( detail::exchange( fctx_, nullptr), nullptr, detail::ecv2_context_unwind);
148 }
149 }
150
151 execution_context( execution_context && other) noexcept :
152 fctx_( other.fctx_) {
153 other.fctx_ = nullptr;
154 }
155
156 execution_context & operator=( execution_context && other) noexcept {
157 if ( this != & other) {
158 execution_context tmp = std::move( other);
159 swap( tmp);
160 }
161 return * this;
162 }
163
164 execution_context( execution_context const& other) noexcept = delete;
165 execution_context & operator=( execution_context const& other) noexcept = delete;
166
167 execution_context operator()() {
168 BOOST_ASSERT( nullptr != fctx_);
169 detail::transfer_t t = detail::jump_fcontext( detail::exchange( fctx_, nullptr), nullptr);
170 if ( nullptr != t.data) {
171 std::exception_ptr * eptr = static_cast< std::exception_ptr * >( t.data);
172 try {
173 std::rethrow_exception( * eptr);
174 } catch (...) {
175 std::throw_with_nested( ontop_error{ t.fctx } );
176 }
177 }
178 return execution_context( t.fctx);
179 }
180
181 template< typename Fn >
182 execution_context operator()( exec_ontop_arg_t, Fn && fn) {
183 BOOST_ASSERT( nullptr != fctx_);
184 auto p = std::make_tuple( fn, std::exception_ptr{} );
185 detail::transfer_t t = detail::ontop_fcontext(
186 detail::exchange( fctx_, nullptr),
187 & p,
188 detail::ecv2_context_ontop_void< execution_context, Fn >);
189 if ( nullptr != t.data) {
190 std::exception_ptr * eptr = static_cast< std::exception_ptr * >( t.data);
191 try {
192 std::rethrow_exception( * eptr);
193 } catch (...) {
194 std::throw_with_nested( ontop_error{ t.fctx } );
195 }
196 }
197 return execution_context( t.fctx);
198 }
199
200 explicit operator bool() const noexcept {
201 return nullptr != fctx_;
202 }
203
204 bool operator!() const noexcept {
205 return nullptr == fctx_;
206 }
207
208 bool operator==( execution_context const& other) const noexcept {
209 return fctx_ == other.fctx_;
210 }
211
212 bool operator!=( execution_context const& other) const noexcept {
213 return fctx_ != other.fctx_;
214 }
215
216 bool operator<( execution_context const& other) const noexcept {
217 return fctx_ < other.fctx_;
218 }
219
220 bool operator>( execution_context const& other) const noexcept {
221 return other.fctx_ < fctx_;
222 }
223
224 bool operator<=( execution_context const& other) const noexcept {
225 return ! ( * this > other);
226 }
227
228 bool operator>=( execution_context const& other) const noexcept {
229 return ! ( * this < other);
230 }
231
232 template< typename charT, class traitsT >
233 friend std::basic_ostream< charT, traitsT > &
234 operator<<( std::basic_ostream< charT, traitsT > & os, execution_context const& other) {
235 if ( nullptr != other.fctx_) {
236 return os << other.fctx_;
237 } else {
238 return os << "{not-a-context}";
239 }
240 }
241
242 void swap( execution_context & other) noexcept {
243 std::swap( fctx_, other.fctx_);
244 }
245 };
246
247 }
248
249 namespace detail {
250
251 template< typename Ctx, typename Fn >
252 transfer_t ecv2_context_ontop_void( transfer_t t) {
253 auto p = static_cast< std::tuple< Fn, std::exception_ptr > * >( t.data);
254 BOOST_ASSERT( nullptr != p);
255 typename std::decay< Fn >::type fn = std::forward< Fn >( std::get< 0 >( * p) );
256 try {
257 // execute function
258 fn();
259 } catch (...) {
260 std::get< 1 >( * p) = std::current_exception();
261 return { t.fctx, & std::get< 1 >( * p ) };
262 }
263 return { exchange( t.fctx, nullptr), nullptr };
264 }
265
266 template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
267 fcontext_t ecv2_context_create_void( StackAlloc && salloc, Fn && fn, Params && ... params) {
268 typedef ecv2_record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
269
270 auto sctx = salloc.allocate();
271 // reserve space for control structure
272 #if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
273 const std::size_t size = sctx.size - sizeof( record_t);
274 void * sp = static_cast< char * >( sctx.sp) - sizeof( record_t);
275 #else
276 constexpr std::size_t func_alignment = 64; // alignof( record_t);
277 constexpr std::size_t func_size = sizeof( record_t);
278 // reserve space on stack
279 void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment;
280 // align sp pointer
281 std::size_t space = func_size + func_alignment;
282 sp = std::align( func_alignment, func_size, sp, space);
283 BOOST_ASSERT( nullptr != sp);
284 // calculate remaining size
285 const std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) );
286 #endif
287 // create fast-context
288 const fcontext_t fctx = make_fcontext( sp, size, & ecv2_context_etry< record_t >);
289 BOOST_ASSERT( nullptr != fctx);
290 // placment new for control structure on context-stack
291 auto rec = ::new ( sp) record_t{
292 sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn), std::forward< Params >( params) ... };
293 // transfer control structure to context-stack
294 return jump_fcontext( fctx, rec).fctx;
295 }
296
297 template< typename Ctx, typename StackAlloc, typename Fn, typename ... Params >
298 fcontext_t ecv2_context_create_void( preallocated palloc, StackAlloc && salloc, Fn && fn, Params && ... params) {
299 typedef ecv2_record_void< Ctx, StackAlloc, Fn, Params ... > record_t;
300
301 // reserve space for control structure
302 #if defined(BOOST_NO_CXX11_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN)
303 const std::size_t size = palloc.size - sizeof( record_t);
304 void * sp = static_cast< char * >( palloc.sp) - sizeof( record_t);
305 #else
306 constexpr std::size_t func_alignment = 64; // alignof( record_t);
307 constexpr std::size_t func_size = sizeof( record_t);
308 // reserve space on stack
309 void * sp = static_cast< char * >( palloc.sp) - func_size - func_alignment;
310 // align sp pointer
311 std::size_t space = func_size + func_alignment;
312 sp = std::align( func_alignment, func_size, sp, space);
313 BOOST_ASSERT( nullptr != sp);
314 // calculate remaining size
315 const std::size_t size = palloc.size - ( static_cast< char * >( palloc.sp) - static_cast< char * >( sp) );
316 #endif
317 // create fast-context
318 const fcontext_t fctx = make_fcontext( sp, size, & ecv2_context_etry< record_t >);
319 BOOST_ASSERT( nullptr != fctx);
320 // placment new for control structure on context-stack
321 auto rec = ::new ( sp) record_t{
322 palloc.sctx, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn), std::forward< Params >( params) ... };
323 // transfer control structure to context-stack
324 return jump_fcontext( fctx, rec).fctx;
325 }
326
327 }