bind_immediate_executor.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. //
  2. // bind_immediate_executor.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2023 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 ASIO_BIND_IMMEDIATE_EXECUTOR_HPP
  11. #define ASIO_BIND_IMMEDIATE_EXECUTOR_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include "asio/detail/config.hpp"
  16. #include "asio/detail/type_traits.hpp"
  17. #include "asio/associated_immediate_executor.hpp"
  18. #include "asio/associator.hpp"
  19. #include "asio/async_result.hpp"
  20. #include "asio/detail/push_options.hpp"
  21. namespace asio {
  22. namespace detail {
  23. // Helper to automatically define nested typedef result_type.
  24. template <typename T, typename = void>
  25. struct immediate_executor_binder_result_type
  26. {
  27. protected:
  28. typedef void result_type_or_void;
  29. };
  30. template <typename T>
  31. struct immediate_executor_binder_result_type<T, void_t<typename T::result_type>>
  32. {
  33. typedef typename T::result_type result_type;
  34. protected:
  35. typedef result_type result_type_or_void;
  36. };
  37. template <typename R>
  38. struct immediate_executor_binder_result_type<R(*)()>
  39. {
  40. typedef R result_type;
  41. protected:
  42. typedef result_type result_type_or_void;
  43. };
  44. template <typename R>
  45. struct immediate_executor_binder_result_type<R(&)()>
  46. {
  47. typedef R result_type;
  48. protected:
  49. typedef result_type result_type_or_void;
  50. };
  51. template <typename R, typename A1>
  52. struct immediate_executor_binder_result_type<R(*)(A1)>
  53. {
  54. typedef R result_type;
  55. protected:
  56. typedef result_type result_type_or_void;
  57. };
  58. template <typename R, typename A1>
  59. struct immediate_executor_binder_result_type<R(&)(A1)>
  60. {
  61. typedef R result_type;
  62. protected:
  63. typedef result_type result_type_or_void;
  64. };
  65. template <typename R, typename A1, typename A2>
  66. struct immediate_executor_binder_result_type<R(*)(A1, A2)>
  67. {
  68. typedef R result_type;
  69. protected:
  70. typedef result_type result_type_or_void;
  71. };
  72. template <typename R, typename A1, typename A2>
  73. struct immediate_executor_binder_result_type<R(&)(A1, A2)>
  74. {
  75. typedef R result_type;
  76. protected:
  77. typedef result_type result_type_or_void;
  78. };
  79. // Helper to automatically define nested typedef argument_type.
  80. template <typename T, typename = void>
  81. struct immediate_executor_binder_argument_type {};
  82. template <typename T>
  83. struct immediate_executor_binder_argument_type<T,
  84. void_t<typename T::argument_type>>
  85. {
  86. typedef typename T::argument_type argument_type;
  87. };
  88. template <typename R, typename A1>
  89. struct immediate_executor_binder_argument_type<R(*)(A1)>
  90. {
  91. typedef A1 argument_type;
  92. };
  93. template <typename R, typename A1>
  94. struct immediate_executor_binder_argument_type<R(&)(A1)>
  95. {
  96. typedef A1 argument_type;
  97. };
  98. // Helper to automatically define nested typedefs first_argument_type and
  99. // second_argument_type.
  100. template <typename T, typename = void>
  101. struct immediate_executor_binder_argument_types {};
  102. template <typename T>
  103. struct immediate_executor_binder_argument_types<T,
  104. void_t<typename T::first_argument_type>>
  105. {
  106. typedef typename T::first_argument_type first_argument_type;
  107. typedef typename T::second_argument_type second_argument_type;
  108. };
  109. template <typename R, typename A1, typename A2>
  110. struct immediate_executor_binder_argument_type<R(*)(A1, A2)>
  111. {
  112. typedef A1 first_argument_type;
  113. typedef A2 second_argument_type;
  114. };
  115. template <typename R, typename A1, typename A2>
  116. struct immediate_executor_binder_argument_type<R(&)(A1, A2)>
  117. {
  118. typedef A1 first_argument_type;
  119. typedef A2 second_argument_type;
  120. };
  121. } // namespace detail
  122. /// A call wrapper type to bind a immediate executor of type @c Executor
  123. /// to an object of type @c T.
  124. template <typename T, typename Executor>
  125. class immediate_executor_binder
  126. #if !defined(GENERATING_DOCUMENTATION)
  127. : public detail::immediate_executor_binder_result_type<T>,
  128. public detail::immediate_executor_binder_argument_type<T>,
  129. public detail::immediate_executor_binder_argument_types<T>
  130. #endif // !defined(GENERATING_DOCUMENTATION)
  131. {
  132. public:
  133. /// The type of the target object.
  134. typedef T target_type;
  135. /// The type of the associated immediate executor.
  136. typedef Executor immediate_executor_type;
  137. #if defined(GENERATING_DOCUMENTATION)
  138. /// The return type if a function.
  139. /**
  140. * The type of @c result_type is based on the type @c T of the wrapper's
  141. * target object:
  142. *
  143. * @li if @c T is a pointer to function type, @c result_type is a synonym for
  144. * the return type of @c T;
  145. *
  146. * @li if @c T is a class type with a member type @c result_type, then @c
  147. * result_type is a synonym for @c T::result_type;
  148. *
  149. * @li otherwise @c result_type is not defined.
  150. */
  151. typedef see_below result_type;
  152. /// The type of the function's argument.
  153. /**
  154. * The type of @c argument_type is based on the type @c T of the wrapper's
  155. * target object:
  156. *
  157. * @li if @c T is a pointer to a function type accepting a single argument,
  158. * @c argument_type is a synonym for the return type of @c T;
  159. *
  160. * @li if @c T is a class type with a member type @c argument_type, then @c
  161. * argument_type is a synonym for @c T::argument_type;
  162. *
  163. * @li otherwise @c argument_type is not defined.
  164. */
  165. typedef see_below argument_type;
  166. /// The type of the function's first argument.
  167. /**
  168. * The type of @c first_argument_type is based on the type @c T of the
  169. * wrapper's target object:
  170. *
  171. * @li if @c T is a pointer to a function type accepting two arguments, @c
  172. * first_argument_type is a synonym for the return type of @c T;
  173. *
  174. * @li if @c T is a class type with a member type @c first_argument_type,
  175. * then @c first_argument_type is a synonym for @c T::first_argument_type;
  176. *
  177. * @li otherwise @c first_argument_type is not defined.
  178. */
  179. typedef see_below first_argument_type;
  180. /// The type of the function's second argument.
  181. /**
  182. * The type of @c second_argument_type is based on the type @c T of the
  183. * wrapper's target object:
  184. *
  185. * @li if @c T is a pointer to a function type accepting two arguments, @c
  186. * second_argument_type is a synonym for the return type of @c T;
  187. *
  188. * @li if @c T is a class type with a member type @c first_argument_type,
  189. * then @c second_argument_type is a synonym for @c T::second_argument_type;
  190. *
  191. * @li otherwise @c second_argument_type is not defined.
  192. */
  193. typedef see_below second_argument_type;
  194. #endif // defined(GENERATING_DOCUMENTATION)
  195. /// Construct a immediate executor wrapper for the specified object.
  196. /**
  197. * This constructor is only valid if the type @c T is constructible from type
  198. * @c U.
  199. */
  200. template <typename U>
  201. immediate_executor_binder(const immediate_executor_type& e,
  202. U&& u)
  203. : executor_(e),
  204. target_(static_cast<U&&>(u))
  205. {
  206. }
  207. /// Copy constructor.
  208. immediate_executor_binder(const immediate_executor_binder& other)
  209. : executor_(other.get_immediate_executor()),
  210. target_(other.get())
  211. {
  212. }
  213. /// Construct a copy, but specify a different immediate executor.
  214. immediate_executor_binder(const immediate_executor_type& e,
  215. const immediate_executor_binder& other)
  216. : executor_(e),
  217. target_(other.get())
  218. {
  219. }
  220. /// Construct a copy of a different immediate executor wrapper type.
  221. /**
  222. * This constructor is only valid if the @c Executor type is
  223. * constructible from type @c OtherExecutor, and the type @c T is
  224. * constructible from type @c U.
  225. */
  226. template <typename U, typename OtherExecutor>
  227. immediate_executor_binder(
  228. const immediate_executor_binder<U, OtherExecutor>& other)
  229. : executor_(other.get_immediate_executor()),
  230. target_(other.get())
  231. {
  232. }
  233. /// Construct a copy of a different immediate executor wrapper type, but
  234. /// specify a different immediate executor.
  235. /**
  236. * This constructor is only valid if the type @c T is constructible from type
  237. * @c U.
  238. */
  239. template <typename U, typename OtherExecutor>
  240. immediate_executor_binder(const immediate_executor_type& e,
  241. const immediate_executor_binder<U, OtherExecutor>& other)
  242. : executor_(e),
  243. target_(other.get())
  244. {
  245. }
  246. /// Move constructor.
  247. immediate_executor_binder(immediate_executor_binder&& other)
  248. : executor_(static_cast<immediate_executor_type&&>(
  249. other.get_immediate_executor())),
  250. target_(static_cast<T&&>(other.get()))
  251. {
  252. }
  253. /// Move construct the target object, but specify a different immediate
  254. /// executor.
  255. immediate_executor_binder(const immediate_executor_type& e,
  256. immediate_executor_binder&& other)
  257. : executor_(e),
  258. target_(static_cast<T&&>(other.get()))
  259. {
  260. }
  261. /// Move construct from a different immediate executor wrapper type.
  262. template <typename U, typename OtherExecutor>
  263. immediate_executor_binder(
  264. immediate_executor_binder<U, OtherExecutor>&& other)
  265. : executor_(static_cast<OtherExecutor&&>(
  266. other.get_immediate_executor())),
  267. target_(static_cast<U&&>(other.get()))
  268. {
  269. }
  270. /// Move construct from a different immediate executor wrapper type, but
  271. /// specify a different immediate executor.
  272. template <typename U, typename OtherExecutor>
  273. immediate_executor_binder(const immediate_executor_type& e,
  274. immediate_executor_binder<U, OtherExecutor>&& other)
  275. : executor_(e),
  276. target_(static_cast<U&&>(other.get()))
  277. {
  278. }
  279. /// Destructor.
  280. ~immediate_executor_binder()
  281. {
  282. }
  283. /// Obtain a reference to the target object.
  284. target_type& get() noexcept
  285. {
  286. return target_;
  287. }
  288. /// Obtain a reference to the target object.
  289. const target_type& get() const noexcept
  290. {
  291. return target_;
  292. }
  293. /// Obtain the associated immediate executor.
  294. immediate_executor_type get_immediate_executor() const noexcept
  295. {
  296. return executor_;
  297. }
  298. /// Forwarding function call operator.
  299. template <typename... Args>
  300. result_of_t<T(Args...)> operator()(Args&&... args)
  301. {
  302. return target_(static_cast<Args&&>(args)...);
  303. }
  304. /// Forwarding function call operator.
  305. template <typename... Args>
  306. result_of_t<T(Args...)> operator()(Args&&... args) const
  307. {
  308. return target_(static_cast<Args&&>(args)...);
  309. }
  310. private:
  311. Executor executor_;
  312. T target_;
  313. };
  314. /// Associate an object of type @c T with a immediate executor of type
  315. /// @c Executor.
  316. template <typename Executor, typename T>
  317. ASIO_NODISCARD inline immediate_executor_binder<decay_t<T>, Executor>
  318. bind_immediate_executor(const Executor& e, T&& t)
  319. {
  320. return immediate_executor_binder<
  321. decay_t<T>, Executor>(
  322. e, static_cast<T&&>(t));
  323. }
  324. #if !defined(GENERATING_DOCUMENTATION)
  325. namespace detail {
  326. template <typename TargetAsyncResult, typename Executor, typename = void>
  327. class immediate_executor_binder_completion_handler_async_result
  328. {
  329. public:
  330. template <typename T>
  331. explicit immediate_executor_binder_completion_handler_async_result(T&)
  332. {
  333. }
  334. };
  335. template <typename TargetAsyncResult, typename Executor>
  336. class immediate_executor_binder_completion_handler_async_result<
  337. TargetAsyncResult, Executor,
  338. void_t<
  339. typename TargetAsyncResult::completion_handler_type
  340. >>
  341. {
  342. public:
  343. typedef immediate_executor_binder<
  344. typename TargetAsyncResult::completion_handler_type, Executor>
  345. completion_handler_type;
  346. explicit immediate_executor_binder_completion_handler_async_result(
  347. typename TargetAsyncResult::completion_handler_type& handler)
  348. : target_(handler)
  349. {
  350. }
  351. typename TargetAsyncResult::return_type get()
  352. {
  353. return target_.get();
  354. }
  355. private:
  356. TargetAsyncResult target_;
  357. };
  358. template <typename TargetAsyncResult, typename = void>
  359. struct immediate_executor_binder_async_result_return_type
  360. {
  361. };
  362. template <typename TargetAsyncResult>
  363. struct immediate_executor_binder_async_result_return_type<
  364. TargetAsyncResult,
  365. void_t<
  366. typename TargetAsyncResult::return_type
  367. >>
  368. {
  369. typedef typename TargetAsyncResult::return_type return_type;
  370. };
  371. } // namespace detail
  372. template <typename T, typename Executor, typename Signature>
  373. class async_result<immediate_executor_binder<T, Executor>, Signature> :
  374. public detail::immediate_executor_binder_completion_handler_async_result<
  375. async_result<T, Signature>, Executor>,
  376. public detail::immediate_executor_binder_async_result_return_type<
  377. async_result<T, Signature>>
  378. {
  379. public:
  380. explicit async_result(immediate_executor_binder<T, Executor>& b)
  381. : detail::immediate_executor_binder_completion_handler_async_result<
  382. async_result<T, Signature>, Executor>(b.get())
  383. {
  384. }
  385. template <typename Initiation>
  386. struct init_wrapper
  387. {
  388. template <typename Init>
  389. init_wrapper(const Executor& e, Init&& init)
  390. : executor_(e),
  391. initiation_(static_cast<Init&&>(init))
  392. {
  393. }
  394. template <typename Handler, typename... Args>
  395. void operator()(Handler&& handler, Args&&... args)
  396. {
  397. static_cast<Initiation&&>(initiation_)(
  398. immediate_executor_binder<
  399. decay_t<Handler>, Executor>(
  400. executor_, static_cast<Handler&&>(handler)),
  401. static_cast<Args&&>(args)...);
  402. }
  403. template <typename Handler, typename... Args>
  404. void operator()(Handler&& handler, Args&&... args) const
  405. {
  406. initiation_(
  407. immediate_executor_binder<
  408. decay_t<Handler>, Executor>(
  409. executor_, static_cast<Handler&&>(handler)),
  410. static_cast<Args&&>(args)...);
  411. }
  412. Executor executor_;
  413. Initiation initiation_;
  414. };
  415. template <typename Initiation, typename RawCompletionToken, typename... Args>
  416. static auto initiate(Initiation&& initiation,
  417. RawCompletionToken&& token, Args&&... args)
  418. -> decltype(
  419. async_initiate<T, Signature>(
  420. declval<init_wrapper<decay_t<Initiation>>>(),
  421. token.get(), static_cast<Args&&>(args)...))
  422. {
  423. return async_initiate<T, Signature>(
  424. init_wrapper<decay_t<Initiation>>(
  425. token.get_immediate_executor(),
  426. static_cast<Initiation&&>(initiation)),
  427. token.get(), static_cast<Args&&>(args)...);
  428. }
  429. private:
  430. async_result(const async_result&) = delete;
  431. async_result& operator=(const async_result&) = delete;
  432. async_result<T, Signature> target_;
  433. };
  434. template <template <typename, typename> class Associator,
  435. typename T, typename Executor, typename DefaultCandidate>
  436. struct associator<Associator,
  437. immediate_executor_binder<T, Executor>,
  438. DefaultCandidate>
  439. : Associator<T, DefaultCandidate>
  440. {
  441. static typename Associator<T, DefaultCandidate>::type get(
  442. const immediate_executor_binder<T, Executor>& b) noexcept
  443. {
  444. return Associator<T, DefaultCandidate>::get(b.get());
  445. }
  446. static auto get(const immediate_executor_binder<T, Executor>& b,
  447. const DefaultCandidate& c) noexcept
  448. -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c))
  449. {
  450. return Associator<T, DefaultCandidate>::get(b.get(), c);
  451. }
  452. };
  453. template <typename T, typename Executor, typename Executor1>
  454. struct associated_immediate_executor<
  455. immediate_executor_binder<T, Executor>,
  456. Executor1>
  457. {
  458. typedef Executor type;
  459. static auto get(const immediate_executor_binder<T, Executor>& b,
  460. const Executor1& = Executor1()) noexcept
  461. -> decltype(b.get_immediate_executor())
  462. {
  463. return b.get_immediate_executor();
  464. }
  465. };
  466. #endif // !defined(GENERATING_DOCUMENTATION)
  467. } // namespace asio
  468. #include "asio/detail/pop_options.hpp"
  469. #endif // ASIO_BIND_IMMEDIATE_EXECUTOR_HPP