5 // Copyright (c) 2003-2017 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_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>
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_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);
50 function(function&& other)
66 detail::scheduler_operation* op = op_;
68 op->complete(this, boost::system::error_code(), 0);
73 detail::scheduler_operation* op_;
76 #else // defined(BOOST_ASIO_HAS_MOVE)
78 // Not so lightweight, copyable function object wrapper.
79 class executor::function
82 template <typename F, typename Alloc>
83 explicit function(const F& f, const Alloc&)
84 : impl_(new impl<F>(f))
90 impl_->invoke_(impl_.get());
94 // Base class for polymorphic function implementations.
97 void (*invoke_)(impl_base*);
100 // Polymorphic function implementation.
101 template <typename F>
102 struct impl : impl_base
107 invoke_ = &function::invoke<F>;
113 // Helper to invoke a function.
114 template <typename F>
115 static void invoke(impl_base* i)
117 static_cast<impl<F>*>(i)->function_();
120 detail::shared_ptr<impl_base> impl_;
123 #endif // defined(BOOST_ASIO_HAS_MOVE)
125 // Default polymorphic allocator implementation.
126 template <typename Executor, typename Allocator>
128 : public executor::impl_base
131 typedef BOOST_ASIO_REBIND_ALLOC(Allocator, impl) allocator_type;
133 static impl_base* create(const Executor& e, Allocator a = Allocator())
136 impl* p = new (mem.ptr_) impl(e, a);
141 impl(const Executor& e, const Allocator& a) BOOST_ASIO_NOEXCEPT
149 impl_base* clone() const BOOST_ASIO_NOEXCEPT
152 return const_cast<impl_base*>(static_cast<const impl_base*>(this));
155 void destroy() BOOST_ASIO_NOEXCEPT
157 if (--ref_count_ == 0)
159 allocator_type alloc(allocator_);
162 alloc.deallocate(p, 1);
166 void on_work_started() BOOST_ASIO_NOEXCEPT
168 executor_.on_work_started();
171 void on_work_finished() BOOST_ASIO_NOEXCEPT
173 executor_.on_work_finished();
176 execution_context& context() BOOST_ASIO_NOEXCEPT
178 return executor_.context();
181 void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
183 executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
186 void post(BOOST_ASIO_MOVE_ARG(function) f)
188 executor_.post(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
191 void defer(BOOST_ASIO_MOVE_ARG(function) f)
193 executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
196 type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
198 return type_id<Executor>();
201 void* target() BOOST_ASIO_NOEXCEPT
206 const void* target() const BOOST_ASIO_NOEXCEPT
211 bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
215 if (target_type() != e->target_type())
217 return executor_ == *static_cast<const Executor*>(e->target());
221 mutable detail::atomic_count ref_count_;
223 Allocator allocator_;
227 allocator_type allocator_;
230 explicit raw_mem(const Allocator& a)
232 ptr_(allocator_.allocate(1))
239 allocator_.deallocate(ptr_, 1);
243 // Disallow copying and assignment.
244 raw_mem(const raw_mem&);
245 raw_mem operator=(const raw_mem&);
249 // Polymorphic allocator specialisation for system_executor.
250 template <typename Allocator>
251 class executor::impl<system_executor, Allocator>
252 : public executor::impl_base
255 static impl_base* create(const system_executor&,
256 const Allocator& = Allocator())
258 return &detail::global<impl<system_executor, std::allocator<void> > >();
266 impl_base* clone() const BOOST_ASIO_NOEXCEPT
268 return const_cast<impl_base*>(static_cast<const impl_base*>(this));
271 void destroy() BOOST_ASIO_NOEXCEPT
275 void on_work_started() BOOST_ASIO_NOEXCEPT
277 executor_.on_work_started();
280 void on_work_finished() BOOST_ASIO_NOEXCEPT
282 executor_.on_work_finished();
285 execution_context& context() BOOST_ASIO_NOEXCEPT
287 return executor_.context();
290 void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
292 executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
295 void post(BOOST_ASIO_MOVE_ARG(function) f)
297 executor_.post(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
300 void defer(BOOST_ASIO_MOVE_ARG(function) f)
302 executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
305 type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
307 return type_id<system_executor>();
310 void* target() BOOST_ASIO_NOEXCEPT
315 const void* target() const BOOST_ASIO_NOEXCEPT
320 bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
326 system_executor executor_;
327 Allocator allocator_;
330 template <typename Executor>
331 executor::executor(Executor e)
332 : impl_(impl<Executor, std::allocator<void> >::create(e))
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))
342 template <typename Function, typename Allocator>
343 void executor::dispatch(BOOST_ASIO_MOVE_ARG(Function) f,
344 const Allocator& a) const
346 impl_base* i = get_impl();
347 if (i->fast_dispatch_)
348 system_executor().dispatch(BOOST_ASIO_MOVE_CAST(Function)(f), a);
350 i->dispatch(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
353 template <typename Function, typename Allocator>
354 void executor::post(BOOST_ASIO_MOVE_ARG(Function) f,
355 const Allocator& a) const
357 get_impl()->post(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
360 template <typename Function, typename Allocator>
361 void executor::defer(BOOST_ASIO_MOVE_ARG(Function) f,
362 const Allocator& a) const
364 get_impl()->defer(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
367 template <typename Executor>
368 Executor* executor::target() BOOST_ASIO_NOEXCEPT
370 return impl_ && impl_->target_type() == type_id<Executor>()
371 ? static_cast<Executor*>(impl_->target()) : 0;
374 template <typename Executor>
375 const Executor* executor::target() const BOOST_ASIO_NOEXCEPT
377 return impl_ && impl_->target_type() == type_id<Executor>()
378 ? static_cast<Executor*>(impl_->target()) : 0;
381 #endif // !defined(GENERATING_DOCUMENTATION)
386 #include <boost/asio/detail/pop_options.hpp>
388 #endif // BOOST_ASIO_IMPL_EXECUTOR_HPP