associated_executor.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. //
  2. // associated_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_ASSOCIATED_EXECUTOR_HPP
  11. #define BOOST_ASIO_ASSOCIATED_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 <boost/asio/associator.hpp>
  17. #include <boost/asio/detail/functional.hpp>
  18. #include <boost/asio/detail/type_traits.hpp>
  19. #include <boost/asio/execution/executor.hpp>
  20. #include <boost/asio/is_executor.hpp>
  21. #include <boost/asio/system_executor.hpp>
  22. #include <boost/asio/detail/push_options.hpp>
  23. namespace boost {
  24. namespace asio {
  25. template <typename T, typename Executor>
  26. struct associated_executor;
  27. namespace detail {
  28. template <typename T, typename = void>
  29. struct has_executor_type : false_type
  30. {
  31. };
  32. template <typename T>
  33. struct has_executor_type<T, void_t<typename T::executor_type>>
  34. : true_type
  35. {
  36. };
  37. template <typename T, typename E, typename = void, typename = void>
  38. struct associated_executor_impl
  39. {
  40. typedef void asio_associated_executor_is_unspecialised;
  41. typedef E type;
  42. static type get(const T&) noexcept
  43. {
  44. return type();
  45. }
  46. static const type& get(const T&, const E& e) noexcept
  47. {
  48. return e;
  49. }
  50. };
  51. template <typename T, typename E>
  52. struct associated_executor_impl<T, E, void_t<typename T::executor_type>>
  53. {
  54. typedef typename T::executor_type type;
  55. static auto get(const T& t) noexcept
  56. -> decltype(t.get_executor())
  57. {
  58. return t.get_executor();
  59. }
  60. static auto get(const T& t, const E&) noexcept
  61. -> decltype(t.get_executor())
  62. {
  63. return t.get_executor();
  64. }
  65. };
  66. template <typename T, typename E>
  67. struct associated_executor_impl<T, E,
  68. enable_if_t<
  69. !has_executor_type<T>::value
  70. >,
  71. void_t<
  72. typename associator<associated_executor, T, E>::type
  73. >> : associator<associated_executor, T, E>
  74. {
  75. };
  76. } // namespace detail
  77. /// Traits type used to obtain the executor associated with an object.
  78. /**
  79. * A program may specialise this traits type if the @c T template parameter in
  80. * the specialisation is a user-defined type. The template parameter @c
  81. * Executor shall be a type meeting the Executor requirements.
  82. *
  83. * Specialisations shall meet the following requirements, where @c t is a const
  84. * reference to an object of type @c T, and @c e is an object of type @c
  85. * Executor.
  86. *
  87. * @li Provide a nested typedef @c type that identifies a type meeting the
  88. * Executor requirements.
  89. *
  90. * @li Provide a noexcept static member function named @c get, callable as @c
  91. * get(t) and with return type @c type or a (possibly const) reference to @c
  92. * type.
  93. *
  94. * @li Provide a noexcept static member function named @c get, callable as @c
  95. * get(t,e) and with return type @c type or a (possibly const) reference to @c
  96. * type.
  97. */
  98. template <typename T, typename Executor = system_executor>
  99. struct associated_executor
  100. #if !defined(GENERATING_DOCUMENTATION)
  101. : detail::associated_executor_impl<T, Executor>
  102. #endif // !defined(GENERATING_DOCUMENTATION)
  103. {
  104. #if defined(GENERATING_DOCUMENTATION)
  105. /// If @c T has a nested type @c executor_type, <tt>T::executor_type</tt>.
  106. /// Otherwise @c Executor.
  107. typedef see_below type;
  108. /// If @c T has a nested type @c executor_type, returns
  109. /// <tt>t.get_executor()</tt>. Otherwise returns @c type().
  110. static decltype(auto) get(const T& t) noexcept;
  111. /// If @c T has a nested type @c executor_type, returns
  112. /// <tt>t.get_executor()</tt>. Otherwise returns @c ex.
  113. static decltype(auto) get(const T& t, const Executor& ex) noexcept;
  114. #endif // defined(GENERATING_DOCUMENTATION)
  115. };
  116. /// Helper function to obtain an object's associated executor.
  117. /**
  118. * @returns <tt>associated_executor<T>::get(t)</tt>
  119. */
  120. template <typename T>
  121. BOOST_ASIO_NODISCARD inline typename associated_executor<T>::type
  122. get_associated_executor(const T& t) noexcept
  123. {
  124. return associated_executor<T>::get(t);
  125. }
  126. /// Helper function to obtain an object's associated executor.
  127. /**
  128. * @returns <tt>associated_executor<T, Executor>::get(t, ex)</tt>
  129. */
  130. template <typename T, typename Executor>
  131. BOOST_ASIO_NODISCARD inline auto get_associated_executor(
  132. const T& t, const Executor& ex,
  133. constraint_t<
  134. is_executor<Executor>::value || execution::is_executor<Executor>::value
  135. > = 0) noexcept
  136. -> decltype(associated_executor<T, Executor>::get(t, ex))
  137. {
  138. return associated_executor<T, Executor>::get(t, ex);
  139. }
  140. /// Helper function to obtain an object's associated executor.
  141. /**
  142. * @returns <tt>associated_executor<T, typename
  143. * ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt>
  144. */
  145. template <typename T, typename ExecutionContext>
  146. BOOST_ASIO_NODISCARD inline typename associated_executor<T,
  147. typename ExecutionContext::executor_type>::type
  148. get_associated_executor(const T& t, ExecutionContext& ctx,
  149. constraint_t<is_convertible<ExecutionContext&,
  150. execution_context&>::value> = 0) noexcept
  151. {
  152. return associated_executor<T,
  153. typename ExecutionContext::executor_type>::get(t, ctx.get_executor());
  154. }
  155. template <typename T, typename Executor = system_executor>
  156. using associated_executor_t = typename associated_executor<T, Executor>::type;
  157. namespace detail {
  158. template <typename T, typename E, typename = void>
  159. struct associated_executor_forwarding_base
  160. {
  161. };
  162. template <typename T, typename E>
  163. struct associated_executor_forwarding_base<T, E,
  164. enable_if_t<
  165. is_same<
  166. typename associated_executor<T,
  167. E>::asio_associated_executor_is_unspecialised,
  168. void
  169. >::value
  170. >>
  171. {
  172. typedef void asio_associated_executor_is_unspecialised;
  173. };
  174. } // namespace detail
  175. /// Specialisation of associated_executor for @c std::reference_wrapper.
  176. template <typename T, typename Executor>
  177. struct associated_executor<reference_wrapper<T>, Executor>
  178. #if !defined(GENERATING_DOCUMENTATION)
  179. : detail::associated_executor_forwarding_base<T, Executor>
  180. #endif // !defined(GENERATING_DOCUMENTATION)
  181. {
  182. /// Forwards @c type to the associator specialisation for the unwrapped type
  183. /// @c T.
  184. typedef typename associated_executor<T, Executor>::type type;
  185. /// Forwards the request to get the executor to the associator specialisation
  186. /// for the unwrapped type @c T.
  187. static type get(reference_wrapper<T> t) noexcept
  188. {
  189. return associated_executor<T, Executor>::get(t.get());
  190. }
  191. /// Forwards the request to get the executor to the associator specialisation
  192. /// for the unwrapped type @c T.
  193. static auto get(reference_wrapper<T> t, const Executor& ex) noexcept
  194. -> decltype(associated_executor<T, Executor>::get(t.get(), ex))
  195. {
  196. return associated_executor<T, Executor>::get(t.get(), ex);
  197. }
  198. };
  199. } // namespace asio
  200. } // namespace boost
  201. #include <boost/asio/detail/pop_options.hpp>
  202. #endif // BOOST_ASIO_ASSOCIATED_EXECUTOR_HPP