executor.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. //
  2. // impl/executor.hpp
  3. // ~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2021 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. #ifndef BOOST_ASIO_IMPL_EXECUTOR_HPP
  11. #define BOOST_ASIO_IMPL_EXECUTOR_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
  17. #include <boost/asio/detail/atomic_count.hpp>
  18. #include <boost/asio/detail/global.hpp>
  19. #include <boost/asio/detail/memory.hpp>
  20. #include <boost/asio/executor.hpp>
  21. #include <boost/asio/system_executor.hpp>
  22. #include <boost/asio/detail/push_options.hpp>
  23. namespace boost {
  24. namespace asio {
  25. #if !defined(GENERATING_DOCUMENTATION)
  26. // Default polymorphic executor implementation.
  27. template <typename Executor, typename Allocator>
  28. class executor::impl
  29. : public executor::impl_base
  30. {
  31. public:
  32. typedef BOOST_ASIO_REBIND_ALLOC(Allocator, impl) allocator_type;
  33. static impl_base* create(const Executor& e, Allocator a = Allocator())
  34. {
  35. raw_mem mem(a);
  36. impl* p = new (mem.ptr_) impl(e, a);
  37. mem.ptr_ = 0;
  38. return p;
  39. }
  40. impl(const Executor& e, const Allocator& a) BOOST_ASIO_NOEXCEPT
  41. : impl_base(false),
  42. ref_count_(1),
  43. executor_(e),
  44. allocator_(a)
  45. {
  46. }
  47. impl_base* clone() const BOOST_ASIO_NOEXCEPT
  48. {
  49. detail::ref_count_up(ref_count_);
  50. return const_cast<impl_base*>(static_cast<const impl_base*>(this));
  51. }
  52. void destroy() BOOST_ASIO_NOEXCEPT
  53. {
  54. if (detail::ref_count_down(ref_count_))
  55. {
  56. allocator_type alloc(allocator_);
  57. impl* p = this;
  58. p->~impl();
  59. alloc.deallocate(p, 1);
  60. }
  61. }
  62. void on_work_started() BOOST_ASIO_NOEXCEPT
  63. {
  64. executor_.on_work_started();
  65. }
  66. void on_work_finished() BOOST_ASIO_NOEXCEPT
  67. {
  68. executor_.on_work_finished();
  69. }
  70. execution_context& context() BOOST_ASIO_NOEXCEPT
  71. {
  72. return executor_.context();
  73. }
  74. void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
  75. {
  76. executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
  77. }
  78. void post(BOOST_ASIO_MOVE_ARG(function) f)
  79. {
  80. executor_.post(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
  81. }
  82. void defer(BOOST_ASIO_MOVE_ARG(function) f)
  83. {
  84. executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
  85. }
  86. type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
  87. {
  88. return type_id<Executor>();
  89. }
  90. void* target() BOOST_ASIO_NOEXCEPT
  91. {
  92. return &executor_;
  93. }
  94. const void* target() const BOOST_ASIO_NOEXCEPT
  95. {
  96. return &executor_;
  97. }
  98. bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
  99. {
  100. if (this == e)
  101. return true;
  102. if (target_type() != e->target_type())
  103. return false;
  104. return executor_ == *static_cast<const Executor*>(e->target());
  105. }
  106. private:
  107. mutable detail::atomic_count ref_count_;
  108. Executor executor_;
  109. Allocator allocator_;
  110. struct raw_mem
  111. {
  112. allocator_type allocator_;
  113. impl* ptr_;
  114. explicit raw_mem(const Allocator& a)
  115. : allocator_(a),
  116. ptr_(allocator_.allocate(1))
  117. {
  118. }
  119. ~raw_mem()
  120. {
  121. if (ptr_)
  122. allocator_.deallocate(ptr_, 1);
  123. }
  124. private:
  125. // Disallow copying and assignment.
  126. raw_mem(const raw_mem&);
  127. raw_mem operator=(const raw_mem&);
  128. };
  129. };
  130. // Polymorphic executor specialisation for system_executor.
  131. template <typename Allocator>
  132. class executor::impl<system_executor, Allocator>
  133. : public executor::impl_base
  134. {
  135. public:
  136. static impl_base* create(const system_executor&,
  137. const Allocator& = Allocator())
  138. {
  139. return &detail::global<impl<system_executor, std::allocator<void> > >();
  140. }
  141. impl()
  142. : impl_base(true)
  143. {
  144. }
  145. impl_base* clone() const BOOST_ASIO_NOEXCEPT
  146. {
  147. return const_cast<impl_base*>(static_cast<const impl_base*>(this));
  148. }
  149. void destroy() BOOST_ASIO_NOEXCEPT
  150. {
  151. }
  152. void on_work_started() BOOST_ASIO_NOEXCEPT
  153. {
  154. executor_.on_work_started();
  155. }
  156. void on_work_finished() BOOST_ASIO_NOEXCEPT
  157. {
  158. executor_.on_work_finished();
  159. }
  160. execution_context& context() BOOST_ASIO_NOEXCEPT
  161. {
  162. return executor_.context();
  163. }
  164. void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
  165. {
  166. executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f),
  167. std::allocator<void>());
  168. }
  169. void post(BOOST_ASIO_MOVE_ARG(function) f)
  170. {
  171. executor_.post(BOOST_ASIO_MOVE_CAST(function)(f),
  172. std::allocator<void>());
  173. }
  174. void defer(BOOST_ASIO_MOVE_ARG(function) f)
  175. {
  176. executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f),
  177. std::allocator<void>());
  178. }
  179. type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
  180. {
  181. return type_id<system_executor>();
  182. }
  183. void* target() BOOST_ASIO_NOEXCEPT
  184. {
  185. return &executor_;
  186. }
  187. const void* target() const BOOST_ASIO_NOEXCEPT
  188. {
  189. return &executor_;
  190. }
  191. bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
  192. {
  193. return this == e;
  194. }
  195. private:
  196. system_executor executor_;
  197. };
  198. template <typename Executor>
  199. executor::executor(Executor e)
  200. : impl_(impl<Executor, std::allocator<void> >::create(e))
  201. {
  202. }
  203. template <typename Executor, typename Allocator>
  204. executor::executor(allocator_arg_t, const Allocator& a, Executor e)
  205. : impl_(impl<Executor, Allocator>::create(e, a))
  206. {
  207. }
  208. template <typename Function, typename Allocator>
  209. void executor::dispatch(BOOST_ASIO_MOVE_ARG(Function) f,
  210. const Allocator& a) const
  211. {
  212. impl_base* i = get_impl();
  213. if (i->fast_dispatch_)
  214. system_executor().dispatch(BOOST_ASIO_MOVE_CAST(Function)(f), a);
  215. else
  216. i->dispatch(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
  217. }
  218. template <typename Function, typename Allocator>
  219. void executor::post(BOOST_ASIO_MOVE_ARG(Function) f,
  220. const Allocator& a) const
  221. {
  222. get_impl()->post(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
  223. }
  224. template <typename Function, typename Allocator>
  225. void executor::defer(BOOST_ASIO_MOVE_ARG(Function) f,
  226. const Allocator& a) const
  227. {
  228. get_impl()->defer(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
  229. }
  230. template <typename Executor>
  231. Executor* executor::target() BOOST_ASIO_NOEXCEPT
  232. {
  233. return impl_ && impl_->target_type() == type_id<Executor>()
  234. ? static_cast<Executor*>(impl_->target()) : 0;
  235. }
  236. template <typename Executor>
  237. const Executor* executor::target() const BOOST_ASIO_NOEXCEPT
  238. {
  239. return impl_ && impl_->target_type() == type_id<Executor>()
  240. ? static_cast<Executor*>(impl_->target()) : 0;
  241. }
  242. #endif // !defined(GENERATING_DOCUMENTATION)
  243. } // namespace asio
  244. } // namespace boost
  245. #include <boost/asio/detail/pop_options.hpp>
  246. #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
  247. #endif // BOOST_ASIO_IMPL_EXECUTOR_HPP