]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/fiber/future/detail/task_object.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / fiber / future / detail / task_object.hpp
1
2 // Copyright Oliver Kowalke 2013.
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_FIBERS_DETAIL_TASK_OBJECT_H
8 #define BOOST_FIBERS_DETAIL_TASK_OBJECT_H
9
10 #include <exception>
11 #include <memory>
12 #include <tuple>
13 #include <utility>
14
15 #include <boost/config.hpp>
16 #include <boost/context/detail/config.hpp>
17 #if defined(BOOST_NO_CXX17_STD_APPLY)
18 #include <boost/context/detail/apply.hpp>
19 #endif
20 #include <boost/core/pointer_traits.hpp>
21
22 #include <boost/fiber/detail/config.hpp>
23 #include <boost/fiber/future/detail/task_base.hpp>
24
25 #ifdef BOOST_HAS_ABI_HEADERS
26 # include BOOST_ABI_PREFIX
27 #endif
28
29 namespace boost {
30 namespace fibers {
31 namespace detail {
32
33 template< typename Fn, typename Allocator, typename R, typename ... Args >
34 class task_object : public task_base< R, Args ... > {
35 private:
36 typedef task_base< R, Args ... > base_type;
37 typedef std::allocator_traits< Allocator > allocator_traits;
38
39 public:
40 typedef typename allocator_traits::template rebind_alloc<
41 task_object
42 > allocator_type;
43
44 task_object( allocator_type const& alloc, Fn const& fn) :
45 base_type{},
46 fn_{ fn },
47 alloc_{ alloc } {
48 }
49
50 task_object( allocator_type const& alloc, Fn && fn) :
51 base_type{},
52 fn_{ std::move( fn) },
53 alloc_{ alloc } {
54 }
55
56 void run( Args && ... args) override final {
57 try {
58 this->set_value(
59 #if defined(BOOST_NO_CXX17_STD_APPLY)
60 boost::context::detail::apply(
61 fn_, std::make_tuple( std::forward< Args >( args) ... ) )
62 #else
63 std::apply(
64 fn_, std::make_tuple( std::forward< Args >( args) ... ) )
65 #endif
66 );
67 #if defined(BOOST_CONTEXT_HAS_CXXABI_H)
68 } catch ( abi::__forced_unwind const&) {
69 throw;
70 #endif
71 } catch (...) {
72 this->set_exception( std::current_exception() );
73 }
74 }
75
76 typename base_type::ptr_type reset() override final {
77 typedef std::allocator_traits< allocator_type > traity_type;
78 typedef pointer_traits< typename traity_type::pointer> ptrait_type;
79
80 typename traity_type::pointer ptr{ traity_type::allocate( alloc_, 1) };
81 typename ptrait_type::element_type* p = boost::to_address(ptr);
82 try {
83 traity_type::construct( alloc_, p, alloc_, std::move( fn_) );
84 } catch (...) {
85 traity_type::deallocate( alloc_, ptr, 1);
86 throw;
87 }
88 return { p };
89 }
90
91 protected:
92 void deallocate_future() noexcept override final {
93 destroy_( alloc_, this);
94 }
95
96 private:
97 Fn fn_;
98 allocator_type alloc_;
99
100 static void destroy_( allocator_type const& alloc, task_object * p) noexcept {
101 allocator_type a{ alloc };
102 typedef std::allocator_traits< allocator_type > traity_type;
103 traity_type::destroy( a, p);
104 traity_type::deallocate( a, p, 1);
105 }
106 };
107
108 template< typename Fn, typename Allocator, typename ... Args >
109 class task_object< Fn, Allocator, void, Args ... > : public task_base< void, Args ... > {
110 private:
111 typedef task_base< void, Args ... > base_type;
112 typedef std::allocator_traits< Allocator > allocator_traits;
113
114 public:
115 typedef typename allocator_traits::template rebind_alloc<
116 task_object< Fn, Allocator, void, Args ... >
117 > allocator_type;
118
119 task_object( allocator_type const& alloc, Fn const& fn) :
120 base_type{},
121 fn_{ fn },
122 alloc_{ alloc } {
123 }
124
125 task_object( allocator_type const& alloc, Fn && fn) :
126 base_type{},
127 fn_{ std::move( fn) },
128 alloc_{ alloc } {
129 }
130
131 void run( Args && ... args) override final {
132 try {
133 #if defined(BOOST_NO_CXX17_STD_APPLY)
134 boost::context::detail::apply(
135 fn_, std::make_tuple( std::forward< Args >( args) ... ) );
136 #else
137 std::apply(
138 fn_, std::make_tuple( std::forward< Args >( args) ... ) );
139 #endif
140 this->set_value();
141 #if defined(BOOST_CONTEXT_HAS_CXXABI_H)
142 } catch ( abi::__forced_unwind const&) {
143 throw;
144 #endif
145 } catch (...) {
146 this->set_exception( std::current_exception() );
147 }
148 }
149
150 typename base_type::ptr_type reset() override final {
151 typedef std::allocator_traits< allocator_type > traity_type;
152 typedef pointer_traits< typename traity_type::pointer> ptrait_type;
153
154 typename traity_type::pointer ptr{ traity_type::allocate( alloc_, 1) };
155 typename ptrait_type::element_type* p = boost::to_address(ptr);
156 try {
157 traity_type::construct( alloc_, p, alloc_, std::move( fn_) );
158 } catch (...) {
159 traity_type::deallocate( alloc_, ptr, 1);
160 throw;
161 }
162 return { p };
163 }
164
165 protected:
166 void deallocate_future() noexcept override final {
167 destroy_( alloc_, this);
168 }
169
170 private:
171 Fn fn_;
172 allocator_type alloc_;
173
174 static void destroy_( allocator_type const& alloc, task_object * p) noexcept {
175 allocator_type a{ alloc };
176 typedef std::allocator_traits< allocator_type > traity_type;
177 traity_type::destroy( a, p);
178 traity_type::deallocate( a, p, 1);
179 }
180 };
181
182 }}}
183
184 #ifdef BOOST_HAS_ABI_HEADERS
185 # include BOOST_ABI_SUFFIX
186 #endif
187
188 #endif // BOOST_FIBERS_DETAIL_TASK_OBJECT_H