]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/detail/executor_function.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / asio / detail / executor_function.hpp
1 //
2 // detail/executor_function.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10
11 #ifndef BOOST_ASIO_DETAIL_EXECUTOR_FUNCTION_HPP
12 #define BOOST_ASIO_DETAIL_EXECUTOR_FUNCTION_HPP
13
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/asio/detail/handler_alloc_helpers.hpp>
20 #include <boost/asio/detail/handler_invoke_helpers.hpp>
21 #include <boost/asio/detail/memory.hpp>
22
23 #include <boost/asio/detail/push_options.hpp>
24
25 namespace boost {
26 namespace asio {
27 namespace detail {
28
29 #if defined(BOOST_ASIO_HAS_MOVE)
30
31 // Lightweight, move-only function object wrapper.
32 class executor_function
33 {
34 public:
35 template <typename F, typename Alloc>
36 explicit executor_function(F f, const Alloc& a)
37 {
38 // Allocate and construct an object to wrap the function.
39 typedef impl<F, Alloc> impl_type;
40 typename impl_type::ptr p = {
41 detail::addressof(a), impl_type::ptr::allocate(a), 0 };
42 impl_ = new (p.v) impl_type(BOOST_ASIO_MOVE_CAST(F)(f), a);
43 p.v = 0;
44 }
45
46 executor_function(executor_function&& other) BOOST_ASIO_NOEXCEPT
47 : impl_(other.impl_)
48 {
49 other.impl_ = 0;
50 }
51
52 ~executor_function()
53 {
54 if (impl_)
55 impl_->complete_(impl_, false);
56 }
57
58 void operator()()
59 {
60 if (impl_)
61 {
62 impl_base* i = impl_;
63 impl_ = 0;
64 i->complete_(i, true);
65 }
66 }
67
68 private:
69 // Base class for polymorphic function implementations.
70 struct impl_base
71 {
72 void (*complete_)(impl_base*, bool);
73 };
74
75 // Polymorphic function implementation.
76 template <typename Function, typename Alloc>
77 struct impl : impl_base
78 {
79 BOOST_ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(
80 thread_info_base::executor_function_tag, impl);
81
82 template <typename F>
83 impl(BOOST_ASIO_MOVE_ARG(F) f, const Alloc& a)
84 : function_(BOOST_ASIO_MOVE_CAST(F)(f)),
85 allocator_(a)
86 {
87 complete_ = &executor_function::complete<Function, Alloc>;
88 }
89
90 Function function_;
91 Alloc allocator_;
92 };
93
94 // Helper to complete function invocation.
95 template <typename Function, typename Alloc>
96 static void complete(impl_base* base, bool call)
97 {
98 // Take ownership of the function object.
99 impl<Function, Alloc>* i(static_cast<impl<Function, Alloc>*>(base));
100 Alloc allocator(i->allocator_);
101 typename impl<Function, Alloc>::ptr p = {
102 detail::addressof(allocator), i, i };
103
104 // Make a copy of the function so that the memory can be deallocated before
105 // the upcall is made. Even if we're not about to make an upcall, a
106 // sub-object of the function may be the true owner of the memory
107 // associated with the function. Consequently, a local copy of the function
108 // is required to ensure that any owning sub-object remains valid until
109 // after we have deallocated the memory here.
110 Function function(BOOST_ASIO_MOVE_CAST(Function)(i->function_));
111 p.reset();
112
113 // Make the upcall if required.
114 if (call)
115 {
116 boost_asio_handler_invoke_helpers::invoke(function, function);
117 }
118 }
119
120 impl_base* impl_;
121 };
122
123 #else // defined(BOOST_ASIO_HAS_MOVE)
124
125 // Not so lightweight, copyable function object wrapper.
126 class executor_function
127 {
128 public:
129 template <typename F, typename Alloc>
130 explicit executor_function(const F& f, const Alloc&)
131 : impl_(new impl<typename decay<F>::type>(f))
132 {
133 }
134
135 void operator()()
136 {
137 impl_->complete_(impl_.get());
138 }
139
140 private:
141 // Base class for polymorphic function implementations.
142 struct impl_base
143 {
144 void (*complete_)(impl_base*);
145 };
146
147 // Polymorphic function implementation.
148 template <typename F>
149 struct impl : impl_base
150 {
151 impl(const F& f)
152 : function_(f)
153 {
154 complete_ = &executor_function::complete<F>;
155 }
156
157 F function_;
158 };
159
160 // Helper to complete function invocation.
161 template <typename F>
162 static void complete(impl_base* i)
163 {
164 static_cast<impl<F>*>(i)->function_();
165 }
166
167 shared_ptr<impl_base> impl_;
168 };
169
170 #endif // defined(BOOST_ASIO_HAS_MOVE)
171
172 // Lightweight, non-owning, copyable function object wrapper.
173 class executor_function_view
174 {
175 public:
176 template <typename F>
177 explicit executor_function_view(F& f) BOOST_ASIO_NOEXCEPT
178 : complete_(&executor_function_view::complete<F>),
179 function_(&f)
180 {
181 }
182
183 void operator()()
184 {
185 complete_(function_);
186 }
187
188 private:
189 // Helper to complete function invocation.
190 template <typename F>
191 static void complete(void* f)
192 {
193 (*static_cast<F*>(f))();
194 }
195
196 void (*complete_)(void*);
197 void* function_;
198 };
199
200 } // namespace detail
201 } // namespace asio
202 } // namespace boost
203
204 #include <boost/asio/detail/pop_options.hpp>
205
206 #endif // BOOST_ASIO_DETAIL_EXECUTOR_FUNCTION_HPP