executor.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. //
  2. // executor.hpp
  3. // ~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2018 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_EXECUTOR_HPP
  11. #define BOOST_ASIO_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. #include <typeinfo>
  17. #include <boost/asio/detail/cstddef.hpp>
  18. #include <boost/asio/detail/memory.hpp>
  19. #include <boost/asio/detail/throw_exception.hpp>
  20. #include <boost/asio/execution_context.hpp>
  21. #include <boost/asio/detail/push_options.hpp>
  22. namespace boost {
  23. namespace asio {
  24. /// Exception thrown when trying to access an empty polymorphic executor.
  25. class bad_executor
  26. : public std::exception
  27. {
  28. public:
  29. /// Constructor.
  30. BOOST_ASIO_DECL bad_executor() BOOST_ASIO_NOEXCEPT;
  31. /// Obtain message associated with exception.
  32. BOOST_ASIO_DECL virtual const char* what() const
  33. BOOST_ASIO_NOEXCEPT_OR_NOTHROW;
  34. };
  35. /// Polymorphic wrapper for executors.
  36. class executor
  37. {
  38. public:
  39. /// Default constructor.
  40. executor() BOOST_ASIO_NOEXCEPT
  41. : impl_(0)
  42. {
  43. }
  44. /// Construct from nullptr.
  45. executor(nullptr_t) BOOST_ASIO_NOEXCEPT
  46. : impl_(0)
  47. {
  48. }
  49. /// Copy constructor.
  50. executor(const executor& other) BOOST_ASIO_NOEXCEPT
  51. : impl_(other.clone())
  52. {
  53. }
  54. #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  55. /// Move constructor.
  56. executor(executor&& other) BOOST_ASIO_NOEXCEPT
  57. : impl_(other.impl_)
  58. {
  59. other.impl_ = 0;
  60. }
  61. #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  62. /// Construct a polymorphic wrapper for the specified executor.
  63. template <typename Executor>
  64. executor(Executor e);
  65. /// Allocator-aware constructor to create a polymorphic wrapper for the
  66. /// specified executor.
  67. template <typename Executor, typename Allocator>
  68. executor(allocator_arg_t, const Allocator& a, Executor e);
  69. /// Destructor.
  70. ~executor()
  71. {
  72. destroy();
  73. }
  74. /// Assignment operator.
  75. executor& operator=(const executor& other) BOOST_ASIO_NOEXCEPT
  76. {
  77. destroy();
  78. impl_ = other.clone();
  79. return *this;
  80. }
  81. #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  82. // Move assignment operator.
  83. executor& operator=(executor&& other) BOOST_ASIO_NOEXCEPT
  84. {
  85. destroy();
  86. impl_ = other.impl_;
  87. other.impl_ = 0;
  88. return *this;
  89. }
  90. #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  91. /// Assignment operator for nullptr_t.
  92. executor& operator=(nullptr_t) BOOST_ASIO_NOEXCEPT
  93. {
  94. destroy();
  95. impl_ = 0;
  96. return *this;
  97. }
  98. /// Assignment operator to create a polymorphic wrapper for the specified
  99. /// executor.
  100. template <typename Executor>
  101. executor& operator=(BOOST_ASIO_MOVE_ARG(Executor) e) BOOST_ASIO_NOEXCEPT
  102. {
  103. executor tmp(BOOST_ASIO_MOVE_CAST(Executor)(e));
  104. destroy();
  105. impl_ = tmp.impl_;
  106. tmp.impl_ = 0;
  107. return *this;
  108. }
  109. /// Obtain the underlying execution context.
  110. execution_context& context() const BOOST_ASIO_NOEXCEPT
  111. {
  112. return get_impl()->context();
  113. }
  114. /// Inform the executor that it has some outstanding work to do.
  115. void on_work_started() const BOOST_ASIO_NOEXCEPT
  116. {
  117. get_impl()->on_work_started();
  118. }
  119. /// Inform the executor that some work is no longer outstanding.
  120. void on_work_finished() const BOOST_ASIO_NOEXCEPT
  121. {
  122. get_impl()->on_work_finished();
  123. }
  124. /// Request the executor to invoke the given function object.
  125. /**
  126. * This function is used to ask the executor to execute the given function
  127. * object. The function object is executed according to the rules of the
  128. * target executor object.
  129. *
  130. * @param f The function object to be called. The executor will make a copy
  131. * of the handler object as required. The function signature of the function
  132. * object must be: @code void function(); @endcode
  133. *
  134. * @param a An allocator that may be used by the executor to allocate the
  135. * internal storage needed for function invocation.
  136. */
  137. template <typename Function, typename Allocator>
  138. void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
  139. /// Request the executor to invoke the given function object.
  140. /**
  141. * This function is used to ask the executor to execute the given function
  142. * object. The function object is executed according to the rules of the
  143. * target executor object.
  144. *
  145. * @param f The function object to be called. The executor will make
  146. * a copy of the handler object as required. The function signature of the
  147. * function object must be: @code void function(); @endcode
  148. *
  149. * @param a An allocator that may be used by the executor to allocate the
  150. * internal storage needed for function invocation.
  151. */
  152. template <typename Function, typename Allocator>
  153. void post(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
  154. /// Request the executor to invoke the given function object.
  155. /**
  156. * This function is used to ask the executor to execute the given function
  157. * object. The function object is executed according to the rules of the
  158. * target executor object.
  159. *
  160. * @param f The function object to be called. The executor will make
  161. * a copy of the handler object as required. The function signature of the
  162. * function object must be: @code void function(); @endcode
  163. *
  164. * @param a An allocator that may be used by the executor to allocate the
  165. * internal storage needed for function invocation.
  166. */
  167. template <typename Function, typename Allocator>
  168. void defer(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
  169. struct unspecified_bool_type_t {};
  170. typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
  171. static void unspecified_bool_true(unspecified_bool_type_t) {}
  172. /// Operator to test if the executor contains a valid target.
  173. operator unspecified_bool_type() const BOOST_ASIO_NOEXCEPT
  174. {
  175. return impl_ ? &executor::unspecified_bool_true : 0;
  176. }
  177. /// Obtain type information for the target executor object.
  178. /**
  179. * @returns If @c *this has a target type of type @c T, <tt>typeid(T)</tt>;
  180. * otherwise, <tt>typeid(void)</tt>.
  181. */
  182. #if !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
  183. const std::type_info& target_type() const BOOST_ASIO_NOEXCEPT
  184. {
  185. return impl_ ? impl_->target_type() : typeid(void);
  186. }
  187. #else // !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
  188. const void* target_type() const BOOST_ASIO_NOEXCEPT
  189. {
  190. return impl_ ? impl_->target_type() : 0;
  191. }
  192. #endif // !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
  193. /// Obtain a pointer to the target executor object.
  194. /**
  195. * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored
  196. * executor target; otherwise, a null pointer.
  197. */
  198. template <typename Executor>
  199. Executor* target() BOOST_ASIO_NOEXCEPT;
  200. /// Obtain a pointer to the target executor object.
  201. /**
  202. * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored
  203. * executor target; otherwise, a null pointer.
  204. */
  205. template <typename Executor>
  206. const Executor* target() const BOOST_ASIO_NOEXCEPT;
  207. /// Compare two executors for equality.
  208. friend bool operator==(const executor& a,
  209. const executor& b) BOOST_ASIO_NOEXCEPT
  210. {
  211. if (a.impl_ == b.impl_)
  212. return true;
  213. if (!a.impl_ || !b.impl_)
  214. return false;
  215. return a.impl_->equals(b.impl_);
  216. }
  217. /// Compare two executors for inequality.
  218. friend bool operator!=(const executor& a,
  219. const executor& b) BOOST_ASIO_NOEXCEPT
  220. {
  221. return !(a == b);
  222. }
  223. private:
  224. #if !defined(GENERATING_DOCUMENTATION)
  225. class function;
  226. template <typename, typename> class impl;
  227. #if !defined(BOOST_ASIO_NO_TYPEID)
  228. typedef const std::type_info& type_id_result_type;
  229. #else // !defined(BOOST_ASIO_NO_TYPEID)
  230. typedef const void* type_id_result_type;
  231. #endif // !defined(BOOST_ASIO_NO_TYPEID)
  232. template <typename T>
  233. static type_id_result_type type_id()
  234. {
  235. #if !defined(BOOST_ASIO_NO_TYPEID)
  236. return typeid(T);
  237. #else // !defined(BOOST_ASIO_NO_TYPEID)
  238. static int unique_id;
  239. return &unique_id;
  240. #endif // !defined(BOOST_ASIO_NO_TYPEID)
  241. }
  242. // Base class for all polymorphic executor implementations.
  243. class impl_base
  244. {
  245. public:
  246. virtual impl_base* clone() const BOOST_ASIO_NOEXCEPT = 0;
  247. virtual void destroy() BOOST_ASIO_NOEXCEPT = 0;
  248. virtual execution_context& context() BOOST_ASIO_NOEXCEPT = 0;
  249. virtual void on_work_started() BOOST_ASIO_NOEXCEPT = 0;
  250. virtual void on_work_finished() BOOST_ASIO_NOEXCEPT = 0;
  251. virtual void dispatch(BOOST_ASIO_MOVE_ARG(function)) = 0;
  252. virtual void post(BOOST_ASIO_MOVE_ARG(function)) = 0;
  253. virtual void defer(BOOST_ASIO_MOVE_ARG(function)) = 0;
  254. virtual type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT = 0;
  255. virtual void* target() BOOST_ASIO_NOEXCEPT = 0;
  256. virtual const void* target() const BOOST_ASIO_NOEXCEPT = 0;
  257. virtual bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT = 0;
  258. protected:
  259. impl_base(bool fast_dispatch) : fast_dispatch_(fast_dispatch) {}
  260. virtual ~impl_base() {}
  261. private:
  262. friend class executor;
  263. const bool fast_dispatch_;
  264. };
  265. // Helper function to check and return the implementation pointer.
  266. impl_base* get_impl() const
  267. {
  268. if (!impl_)
  269. {
  270. bad_executor ex;
  271. boost::asio::detail::throw_exception(ex);
  272. }
  273. return impl_;
  274. }
  275. // Helper function to clone another implementation.
  276. impl_base* clone() const BOOST_ASIO_NOEXCEPT
  277. {
  278. return impl_ ? impl_->clone() : 0;
  279. }
  280. // Helper function to destroy an implementation.
  281. void destroy() BOOST_ASIO_NOEXCEPT
  282. {
  283. if (impl_)
  284. impl_->destroy();
  285. }
  286. impl_base* impl_;
  287. #endif // !defined(GENERATING_DOCUMENTATION)
  288. };
  289. } // namespace asio
  290. } // namespace boost
  291. BOOST_ASIO_USES_ALLOCATOR(boost::asio::executor)
  292. #include <boost/asio/detail/pop_options.hpp>
  293. #include <boost/asio/impl/executor.hpp>
  294. #if defined(BOOST_ASIO_HEADER_ONLY)
  295. # include <boost/asio/impl/executor.ipp>
  296. #endif // defined(BOOST_ASIO_HEADER_ONLY)
  297. #endif // BOOST_ASIO_EXECUTOR_HPP