]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/asio/impl/executor.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / asio / impl / executor.hpp
CommitLineData
b32b8144
FG
1//
2// impl/executor.hpp
3// ~~~~~~~~~~~~~~~~~
4//
92f5a8d4 5// Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
b32b8144
FG
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_IMPL_EXECUTOR_HPP
12#define BOOST_ASIO_IMPL_EXECUTOR_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/atomic_count.hpp>
92f5a8d4 20#include <boost/asio/detail/executor_function.hpp>
b32b8144
FG
21#include <boost/asio/detail/global.hpp>
22#include <boost/asio/detail/memory.hpp>
23#include <boost/asio/detail/recycling_allocator.hpp>
24#include <boost/asio/executor.hpp>
25#include <boost/asio/system_executor.hpp>
26
27#include <boost/asio/detail/push_options.hpp>
28
29namespace boost {
30namespace asio {
31
32#if !defined(GENERATING_DOCUMENTATION)
33
34#if defined(BOOST_ASIO_HAS_MOVE)
35
36// Lightweight, move-only function object wrapper.
37class executor::function
38{
39public:
40 template <typename F, typename Alloc>
41 explicit function(F f, const Alloc& a)
42 {
43 // Allocate and construct an operation to wrap the function.
92f5a8d4
TL
44 typedef detail::executor_function<F, Alloc> func_type;
45 typename func_type::ptr p = {
46 detail::addressof(a), func_type::ptr::allocate(a), 0 };
47 func_ = new (p.v) func_type(BOOST_ASIO_MOVE_CAST(F)(f), a);
b32b8144
FG
48 p.v = 0;
49 }
50
92f5a8d4
TL
51 function(function&& other) BOOST_ASIO_NOEXCEPT
52 : func_(other.func_)
b32b8144 53 {
92f5a8d4 54 other.func_ = 0;
b32b8144
FG
55 }
56
57 ~function()
58 {
92f5a8d4
TL
59 if (func_)
60 func_->destroy();
b32b8144
FG
61 }
62
63 void operator()()
64 {
92f5a8d4 65 if (func_)
b32b8144 66 {
92f5a8d4
TL
67 detail::executor_function_base* func = func_;
68 func_ = 0;
69 func->complete();
b32b8144
FG
70 }
71 }
72
73private:
92f5a8d4 74 detail::executor_function_base* func_;
b32b8144
FG
75};
76
77#else // defined(BOOST_ASIO_HAS_MOVE)
78
79// Not so lightweight, copyable function object wrapper.
80class executor::function
81{
82public:
83 template <typename F, typename Alloc>
84 explicit function(const F& f, const Alloc&)
85 : impl_(new impl<F>(f))
86 {
87 }
88
89 void operator()()
90 {
91 impl_->invoke_(impl_.get());
92 }
93
94private:
95 // Base class for polymorphic function implementations.
96 struct impl_base
97 {
98 void (*invoke_)(impl_base*);
99 };
100
101 // Polymorphic function implementation.
102 template <typename F>
103 struct impl : impl_base
104 {
105 impl(const F& f)
106 : function_(f)
107 {
108 invoke_ = &function::invoke<F>;
109 }
110
111 F function_;
112 };
113
114 // Helper to invoke a function.
115 template <typename F>
116 static void invoke(impl_base* i)
117 {
118 static_cast<impl<F>*>(i)->function_();
119 }
120
121 detail::shared_ptr<impl_base> impl_;
122};
123
124#endif // defined(BOOST_ASIO_HAS_MOVE)
125
126// Default polymorphic allocator implementation.
127template <typename Executor, typename Allocator>
128class executor::impl
129 : public executor::impl_base
130{
131public:
132 typedef BOOST_ASIO_REBIND_ALLOC(Allocator, impl) allocator_type;
133
134 static impl_base* create(const Executor& e, Allocator a = Allocator())
135 {
136 raw_mem mem(a);
137 impl* p = new (mem.ptr_) impl(e, a);
138 mem.ptr_ = 0;
139 return p;
140 }
141
142 impl(const Executor& e, const Allocator& a) BOOST_ASIO_NOEXCEPT
143 : impl_base(false),
144 ref_count_(1),
145 executor_(e),
146 allocator_(a)
147 {
148 }
149
150 impl_base* clone() const BOOST_ASIO_NOEXCEPT
151 {
152 ++ref_count_;
153 return const_cast<impl_base*>(static_cast<const impl_base*>(this));
154 }
155
156 void destroy() BOOST_ASIO_NOEXCEPT
157 {
158 if (--ref_count_ == 0)
159 {
160 allocator_type alloc(allocator_);
161 impl* p = this;
162 p->~impl();
163 alloc.deallocate(p, 1);
164 }
165 }
166
167 void on_work_started() BOOST_ASIO_NOEXCEPT
168 {
169 executor_.on_work_started();
170 }
171
172 void on_work_finished() BOOST_ASIO_NOEXCEPT
173 {
174 executor_.on_work_finished();
175 }
176
177 execution_context& context() BOOST_ASIO_NOEXCEPT
178 {
179 return executor_.context();
180 }
181
182 void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
183 {
184 executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
185 }
186
187 void post(BOOST_ASIO_MOVE_ARG(function) f)
188 {
189 executor_.post(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
190 }
191
192 void defer(BOOST_ASIO_MOVE_ARG(function) f)
193 {
194 executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
195 }
196
197 type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
198 {
199 return type_id<Executor>();
200 }
201
202 void* target() BOOST_ASIO_NOEXCEPT
203 {
204 return &executor_;
205 }
206
207 const void* target() const BOOST_ASIO_NOEXCEPT
208 {
209 return &executor_;
210 }
211
212 bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
213 {
214 if (this == e)
215 return true;
216 if (target_type() != e->target_type())
217 return false;
218 return executor_ == *static_cast<const Executor*>(e->target());
219 }
220
221private:
222 mutable detail::atomic_count ref_count_;
223 Executor executor_;
224 Allocator allocator_;
225
226 struct raw_mem
227 {
228 allocator_type allocator_;
229 impl* ptr_;
230
231 explicit raw_mem(const Allocator& a)
232 : allocator_(a),
233 ptr_(allocator_.allocate(1))
234 {
235 }
236
237 ~raw_mem()
238 {
239 if (ptr_)
240 allocator_.deallocate(ptr_, 1);
241 }
242
243 private:
244 // Disallow copying and assignment.
245 raw_mem(const raw_mem&);
246 raw_mem operator=(const raw_mem&);
247 };
248};
249
250// Polymorphic allocator specialisation for system_executor.
251template <typename Allocator>
252class executor::impl<system_executor, Allocator>
253 : public executor::impl_base
254{
255public:
256 static impl_base* create(const system_executor&,
257 const Allocator& = Allocator())
258 {
259 return &detail::global<impl<system_executor, std::allocator<void> > >();
260 }
261
262 impl()
263 : impl_base(true)
264 {
265 }
266
267 impl_base* clone() const BOOST_ASIO_NOEXCEPT
268 {
269 return const_cast<impl_base*>(static_cast<const impl_base*>(this));
270 }
271
272 void destroy() BOOST_ASIO_NOEXCEPT
273 {
274 }
275
276 void on_work_started() BOOST_ASIO_NOEXCEPT
277 {
278 executor_.on_work_started();
279 }
280
281 void on_work_finished() BOOST_ASIO_NOEXCEPT
282 {
283 executor_.on_work_finished();
284 }
285
286 execution_context& context() BOOST_ASIO_NOEXCEPT
287 {
288 return executor_.context();
289 }
290
291 void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
292 {
293 executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
294 }
295
296 void post(BOOST_ASIO_MOVE_ARG(function) f)
297 {
298 executor_.post(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
299 }
300
301 void defer(BOOST_ASIO_MOVE_ARG(function) f)
302 {
303 executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
304 }
305
306 type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
307 {
308 return type_id<system_executor>();
309 }
310
311 void* target() BOOST_ASIO_NOEXCEPT
312 {
313 return &executor_;
314 }
315
316 const void* target() const BOOST_ASIO_NOEXCEPT
317 {
318 return &executor_;
319 }
320
321 bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
322 {
323 return this == e;
324 }
325
326private:
327 system_executor executor_;
328 Allocator allocator_;
329};
330
331template <typename Executor>
332executor::executor(Executor e)
333 : impl_(impl<Executor, std::allocator<void> >::create(e))
334{
335}
336
337template <typename Executor, typename Allocator>
338executor::executor(allocator_arg_t, const Allocator& a, Executor e)
339 : impl_(impl<Executor, Allocator>::create(e, a))
340{
341}
342
343template <typename Function, typename Allocator>
344void executor::dispatch(BOOST_ASIO_MOVE_ARG(Function) f,
345 const Allocator& a) const
346{
347 impl_base* i = get_impl();
348 if (i->fast_dispatch_)
349 system_executor().dispatch(BOOST_ASIO_MOVE_CAST(Function)(f), a);
350 else
351 i->dispatch(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
352}
353
354template <typename Function, typename Allocator>
355void executor::post(BOOST_ASIO_MOVE_ARG(Function) f,
356 const Allocator& a) const
357{
358 get_impl()->post(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
359}
360
361template <typename Function, typename Allocator>
362void executor::defer(BOOST_ASIO_MOVE_ARG(Function) f,
363 const Allocator& a) const
364{
365 get_impl()->defer(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
366}
367
368template <typename Executor>
369Executor* executor::target() BOOST_ASIO_NOEXCEPT
370{
371 return impl_ && impl_->target_type() == type_id<Executor>()
372 ? static_cast<Executor*>(impl_->target()) : 0;
373}
374
375template <typename Executor>
376const Executor* executor::target() const BOOST_ASIO_NOEXCEPT
377{
378 return impl_ && impl_->target_type() == type_id<Executor>()
379 ? static_cast<Executor*>(impl_->target()) : 0;
380}
381
382#endif // !defined(GENERATING_DOCUMENTATION)
383
384} // namespace asio
385} // namespace boost
386
387#include <boost/asio/detail/pop_options.hpp>
388
389#endif // BOOST_ASIO_IMPL_EXECUTOR_HPP