associated_executor.hpp 6.9 KB

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