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