5 // Copyright (c) 2003-2022 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>
20 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
22 #include <boost/asio/detail/atomic_count.hpp>
23 #include <boost/asio/detail/global.hpp>
24 #include <boost/asio/detail/memory.hpp>
25 #include <boost/asio/executor.hpp>
26 #include <boost/asio/system_executor.hpp>
28 #include <boost/asio/detail/push_options.hpp>
33 #if !defined(GENERATING_DOCUMENTATION)
35 // Default polymorphic executor implementation.
36 template <typename Executor, typename Allocator>
38 : public executor::impl_base
41 typedef BOOST_ASIO_REBIND_ALLOC(Allocator, impl) allocator_type;
43 static impl_base* create(const Executor& e, Allocator a = Allocator())
46 impl* p = new (mem.ptr_) impl(e, a);
51 impl(const Executor& e, const Allocator& a) BOOST_ASIO_NOEXCEPT
59 impl_base* clone() const BOOST_ASIO_NOEXCEPT
61 detail::ref_count_up(ref_count_);
62 return const_cast<impl_base*>(static_cast<const impl_base*>(this));
65 void destroy() BOOST_ASIO_NOEXCEPT
67 if (detail::ref_count_down(ref_count_))
69 allocator_type alloc(allocator_);
72 alloc.deallocate(p, 1);
76 void on_work_started() BOOST_ASIO_NOEXCEPT
78 executor_.on_work_started();
81 void on_work_finished() BOOST_ASIO_NOEXCEPT
83 executor_.on_work_finished();
86 execution_context& context() BOOST_ASIO_NOEXCEPT
88 return executor_.context();
91 void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
93 executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
96 void post(BOOST_ASIO_MOVE_ARG(function) f)
98 executor_.post(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
101 void defer(BOOST_ASIO_MOVE_ARG(function) f)
103 executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
106 type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
108 return type_id<Executor>();
111 void* target() BOOST_ASIO_NOEXCEPT
116 const void* target() const BOOST_ASIO_NOEXCEPT
121 bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
125 if (target_type() != e->target_type())
127 return executor_ == *static_cast<const Executor*>(e->target());
131 mutable detail::atomic_count ref_count_;
133 Allocator allocator_;
137 allocator_type allocator_;
140 explicit raw_mem(const Allocator& a)
142 ptr_(allocator_.allocate(1))
149 allocator_.deallocate(ptr_, 1);
153 // Disallow copying and assignment.
154 raw_mem(const raw_mem&);
155 raw_mem operator=(const raw_mem&);
159 // Polymorphic executor specialisation for system_executor.
160 template <typename Allocator>
161 class executor::impl<system_executor, Allocator>
162 : public executor::impl_base
165 static impl_base* create(const system_executor&,
166 const Allocator& = Allocator())
168 return &detail::global<impl<system_executor, std::allocator<void> > >();
176 impl_base* clone() const BOOST_ASIO_NOEXCEPT
178 return const_cast<impl_base*>(static_cast<const impl_base*>(this));
181 void destroy() BOOST_ASIO_NOEXCEPT
185 void on_work_started() BOOST_ASIO_NOEXCEPT
187 executor_.on_work_started();
190 void on_work_finished() BOOST_ASIO_NOEXCEPT
192 executor_.on_work_finished();
195 execution_context& context() BOOST_ASIO_NOEXCEPT
197 return executor_.context();
200 void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
202 executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f),
203 std::allocator<void>());
206 void post(BOOST_ASIO_MOVE_ARG(function) f)
208 executor_.post(BOOST_ASIO_MOVE_CAST(function)(f),
209 std::allocator<void>());
212 void defer(BOOST_ASIO_MOVE_ARG(function) f)
214 executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f),
215 std::allocator<void>());
218 type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
220 return type_id<system_executor>();
223 void* target() BOOST_ASIO_NOEXCEPT
228 const void* target() const BOOST_ASIO_NOEXCEPT
233 bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
239 system_executor executor_;
242 template <typename Executor>
243 executor::executor(Executor e)
244 : impl_(impl<Executor, std::allocator<void> >::create(e))
248 template <typename Executor, typename Allocator>
249 executor::executor(allocator_arg_t, const Allocator& a, Executor e)
250 : impl_(impl<Executor, Allocator>::create(e, a))
254 template <typename Function, typename Allocator>
255 void executor::dispatch(BOOST_ASIO_MOVE_ARG(Function) f,
256 const Allocator& a) const
258 impl_base* i = get_impl();
259 if (i->fast_dispatch_)
260 system_executor().dispatch(BOOST_ASIO_MOVE_CAST(Function)(f), a);
262 i->dispatch(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
265 template <typename Function, typename Allocator>
266 void executor::post(BOOST_ASIO_MOVE_ARG(Function) f,
267 const Allocator& a) const
269 get_impl()->post(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
272 template <typename Function, typename Allocator>
273 void executor::defer(BOOST_ASIO_MOVE_ARG(Function) f,
274 const Allocator& a) const
276 get_impl()->defer(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
279 template <typename Executor>
280 Executor* executor::target() BOOST_ASIO_NOEXCEPT
282 return impl_ && impl_->target_type() == type_id<Executor>()
283 ? static_cast<Executor*>(impl_->target()) : 0;
286 template <typename Executor>
287 const Executor* executor::target() const BOOST_ASIO_NOEXCEPT
289 return impl_ && impl_->target_type() == type_id<Executor>()
290 ? static_cast<Executor*>(impl_->target()) : 0;
293 #endif // !defined(GENERATING_DOCUMENTATION)
298 #include <boost/asio/detail/pop_options.hpp>
300 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
302 #endif // BOOST_ASIO_IMPL_EXECUTOR_HPP