5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_IMPL_EXECUTOR_HPP
12 #define BOOST_ASIO_IMPL_EXECUTOR_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/asio/detail/atomic_count.hpp>
20 #include <boost/asio/detail/executor_function.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>
27 #include <boost/asio/detail/push_options.hpp>
32 #if !defined(GENERATING_DOCUMENTATION)
34 #if defined(BOOST_ASIO_HAS_MOVE)
36 // Lightweight, move-only function object wrapper.
37 class executor::function
40 template <typename F, typename Alloc>
41 explicit function(F f, const Alloc& a)
43 // Allocate and construct an operation to wrap the function.
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);
51 function(function&& other) BOOST_ASIO_NOEXCEPT
67 detail::executor_function_base* func = func_;
74 detail::executor_function_base* func_;
77 #else // defined(BOOST_ASIO_HAS_MOVE)
79 // Not so lightweight, copyable function object wrapper.
80 class executor::function
83 template <typename F, typename Alloc>
84 explicit function(const F& f, const Alloc&)
85 : impl_(new impl<F>(f))
91 impl_->invoke_(impl_.get());
95 // Base class for polymorphic function implementations.
98 void (*invoke_)(impl_base*);
101 // Polymorphic function implementation.
102 template <typename F>
103 struct impl : impl_base
108 invoke_ = &function::invoke<F>;
114 // Helper to invoke a function.
115 template <typename F>
116 static void invoke(impl_base* i)
118 static_cast<impl<F>*>(i)->function_();
121 detail::shared_ptr<impl_base> impl_;
124 #endif // defined(BOOST_ASIO_HAS_MOVE)
126 // Default polymorphic allocator implementation.
127 template <typename Executor, typename Allocator>
129 : public executor::impl_base
132 typedef BOOST_ASIO_REBIND_ALLOC(Allocator, impl) allocator_type;
134 static impl_base* create(const Executor& e, Allocator a = Allocator())
137 impl* p = new (mem.ptr_) impl(e, a);
142 impl(const Executor& e, const Allocator& a) BOOST_ASIO_NOEXCEPT
150 impl_base* clone() const BOOST_ASIO_NOEXCEPT
153 return const_cast<impl_base*>(static_cast<const impl_base*>(this));
156 void destroy() BOOST_ASIO_NOEXCEPT
158 if (--ref_count_ == 0)
160 allocator_type alloc(allocator_);
163 alloc.deallocate(p, 1);
167 void on_work_started() BOOST_ASIO_NOEXCEPT
169 executor_.on_work_started();
172 void on_work_finished() BOOST_ASIO_NOEXCEPT
174 executor_.on_work_finished();
177 execution_context& context() BOOST_ASIO_NOEXCEPT
179 return executor_.context();
182 void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
184 executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
187 void post(BOOST_ASIO_MOVE_ARG(function) f)
189 executor_.post(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
192 void defer(BOOST_ASIO_MOVE_ARG(function) f)
194 executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
197 type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
199 return type_id<Executor>();
202 void* target() BOOST_ASIO_NOEXCEPT
207 const void* target() const BOOST_ASIO_NOEXCEPT
212 bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
216 if (target_type() != e->target_type())
218 return executor_ == *static_cast<const Executor*>(e->target());
222 mutable detail::atomic_count ref_count_;
224 Allocator allocator_;
228 allocator_type allocator_;
231 explicit raw_mem(const Allocator& a)
233 ptr_(allocator_.allocate(1))
240 allocator_.deallocate(ptr_, 1);
244 // Disallow copying and assignment.
245 raw_mem(const raw_mem&);
246 raw_mem operator=(const raw_mem&);
250 // Polymorphic allocator specialisation for system_executor.
251 template <typename Allocator>
252 class executor::impl<system_executor, Allocator>
253 : public executor::impl_base
256 static impl_base* create(const system_executor&,
257 const Allocator& = Allocator())
259 return &detail::global<impl<system_executor, std::allocator<void> > >();
267 impl_base* clone() const BOOST_ASIO_NOEXCEPT
269 return const_cast<impl_base*>(static_cast<const impl_base*>(this));
272 void destroy() BOOST_ASIO_NOEXCEPT
276 void on_work_started() BOOST_ASIO_NOEXCEPT
278 executor_.on_work_started();
281 void on_work_finished() BOOST_ASIO_NOEXCEPT
283 executor_.on_work_finished();
286 execution_context& context() BOOST_ASIO_NOEXCEPT
288 return executor_.context();
291 void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
293 executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
296 void post(BOOST_ASIO_MOVE_ARG(function) f)
298 executor_.post(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
301 void defer(BOOST_ASIO_MOVE_ARG(function) f)
303 executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
306 type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
308 return type_id<system_executor>();
311 void* target() BOOST_ASIO_NOEXCEPT
316 const void* target() const BOOST_ASIO_NOEXCEPT
321 bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
327 system_executor executor_;
328 Allocator allocator_;
331 template <typename Executor>
332 executor::executor(Executor e)
333 : impl_(impl<Executor, std::allocator<void> >::create(e))
337 template <typename Executor, typename Allocator>
338 executor::executor(allocator_arg_t, const Allocator& a, Executor e)
339 : impl_(impl<Executor, Allocator>::create(e, a))
343 template <typename Function, typename Allocator>
344 void executor::dispatch(BOOST_ASIO_MOVE_ARG(Function) f,
345 const Allocator& a) const
347 impl_base* i = get_impl();
348 if (i->fast_dispatch_)
349 system_executor().dispatch(BOOST_ASIO_MOVE_CAST(Function)(f), a);
351 i->dispatch(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
354 template <typename Function, typename Allocator>
355 void executor::post(BOOST_ASIO_MOVE_ARG(Function) f,
356 const Allocator& a) const
358 get_impl()->post(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
361 template <typename Function, typename Allocator>
362 void executor::defer(BOOST_ASIO_MOVE_ARG(Function) f,
363 const Allocator& a) const
365 get_impl()->defer(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
368 template <typename Executor>
369 Executor* executor::target() BOOST_ASIO_NOEXCEPT
371 return impl_ && impl_->target_type() == type_id<Executor>()
372 ? static_cast<Executor*>(impl_->target()) : 0;
375 template <typename Executor>
376 const Executor* executor::target() const BOOST_ASIO_NOEXCEPT
378 return impl_ && impl_->target_type() == type_id<Executor>()
379 ? static_cast<Executor*>(impl_->target()) : 0;
382 #endif // !defined(GENERATING_DOCUMENTATION)
387 #include <boost/asio/detail/pop_options.hpp>
389 #endif // BOOST_ASIO_IMPL_EXECUTOR_HPP