executor.hpp 6.6 KB

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