bind_executor.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. //
  2. // bind_executor.hpp
  3. // ~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2022 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_EXECUTOR_HPP
  11. #define ASIO_BIND_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/detail/variadic_templates.hpp"
  18. #include "asio/associated_executor.hpp"
  19. #include "asio/associator.hpp"
  20. #include "asio/async_result.hpp"
  21. #include "asio/execution/executor.hpp"
  22. #include "asio/execution_context.hpp"
  23. #include "asio/is_executor.hpp"
  24. #include "asio/uses_executor.hpp"
  25. #include "asio/detail/push_options.hpp"
  26. namespace asio {
  27. namespace detail {
  28. // Helper to automatically define nested typedef result_type.
  29. template <typename T, typename = void>
  30. struct executor_binder_result_type
  31. {
  32. protected:
  33. typedef void result_type_or_void;
  34. };
  35. template <typename T>
  36. struct executor_binder_result_type<T,
  37. typename void_type<typename T::result_type>::type>
  38. {
  39. typedef typename T::result_type result_type;
  40. protected:
  41. typedef result_type result_type_or_void;
  42. };
  43. template <typename R>
  44. struct executor_binder_result_type<R(*)()>
  45. {
  46. typedef R result_type;
  47. protected:
  48. typedef result_type result_type_or_void;
  49. };
  50. template <typename R>
  51. struct executor_binder_result_type<R(&)()>
  52. {
  53. typedef R result_type;
  54. protected:
  55. typedef result_type result_type_or_void;
  56. };
  57. template <typename R, typename A1>
  58. struct executor_binder_result_type<R(*)(A1)>
  59. {
  60. typedef R result_type;
  61. protected:
  62. typedef result_type result_type_or_void;
  63. };
  64. template <typename R, typename A1>
  65. struct executor_binder_result_type<R(&)(A1)>
  66. {
  67. typedef R result_type;
  68. protected:
  69. typedef result_type result_type_or_void;
  70. };
  71. template <typename R, typename A1, typename A2>
  72. struct executor_binder_result_type<R(*)(A1, A2)>
  73. {
  74. typedef R result_type;
  75. protected:
  76. typedef result_type result_type_or_void;
  77. };
  78. template <typename R, typename A1, typename A2>
  79. struct executor_binder_result_type<R(&)(A1, A2)>
  80. {
  81. typedef R result_type;
  82. protected:
  83. typedef result_type result_type_or_void;
  84. };
  85. // Helper to automatically define nested typedef argument_type.
  86. template <typename T, typename = void>
  87. struct executor_binder_argument_type {};
  88. template <typename T>
  89. struct executor_binder_argument_type<T,
  90. typename void_type<typename T::argument_type>::type>
  91. {
  92. typedef typename T::argument_type argument_type;
  93. };
  94. template <typename R, typename A1>
  95. struct executor_binder_argument_type<R(*)(A1)>
  96. {
  97. typedef A1 argument_type;
  98. };
  99. template <typename R, typename A1>
  100. struct executor_binder_argument_type<R(&)(A1)>
  101. {
  102. typedef A1 argument_type;
  103. };
  104. // Helper to automatically define nested typedefs first_argument_type and
  105. // second_argument_type.
  106. template <typename T, typename = void>
  107. struct executor_binder_argument_types {};
  108. template <typename T>
  109. struct executor_binder_argument_types<T,
  110. typename void_type<typename T::first_argument_type>::type>
  111. {
  112. typedef typename T::first_argument_type first_argument_type;
  113. typedef typename T::second_argument_type second_argument_type;
  114. };
  115. template <typename R, typename A1, typename A2>
  116. struct executor_binder_argument_type<R(*)(A1, A2)>
  117. {
  118. typedef A1 first_argument_type;
  119. typedef A2 second_argument_type;
  120. };
  121. template <typename R, typename A1, typename A2>
  122. struct executor_binder_argument_type<R(&)(A1, A2)>
  123. {
  124. typedef A1 first_argument_type;
  125. typedef A2 second_argument_type;
  126. };
  127. // Helper to perform uses_executor construction of the target type, if
  128. // required.
  129. template <typename T, typename Executor, bool UsesExecutor>
  130. class executor_binder_base;
  131. template <typename T, typename Executor>
  132. class executor_binder_base<T, Executor, true>
  133. {
  134. protected:
  135. template <typename E, typename U>
  136. executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u)
  137. : executor_(ASIO_MOVE_CAST(E)(e)),
  138. target_(executor_arg_t(), executor_, ASIO_MOVE_CAST(U)(u))
  139. {
  140. }
  141. Executor executor_;
  142. T target_;
  143. };
  144. template <typename T, typename Executor>
  145. class executor_binder_base<T, Executor, false>
  146. {
  147. protected:
  148. template <typename E, typename U>
  149. executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u)
  150. : executor_(ASIO_MOVE_CAST(E)(e)),
  151. target_(ASIO_MOVE_CAST(U)(u))
  152. {
  153. }
  154. Executor executor_;
  155. T target_;
  156. };
  157. // Helper to enable SFINAE on zero-argument operator() below.
  158. template <typename T, typename = void>
  159. struct executor_binder_result_of0
  160. {
  161. typedef void type;
  162. };
  163. template <typename T>
  164. struct executor_binder_result_of0<T,
  165. typename void_type<typename result_of<T()>::type>::type>
  166. {
  167. typedef typename result_of<T()>::type type;
  168. };
  169. } // namespace detail
  170. /// A call wrapper type to bind an executor of type @c Executor to an object of
  171. /// type @c T.
  172. template <typename T, typename Executor>
  173. class executor_binder
  174. #if !defined(GENERATING_DOCUMENTATION)
  175. : public detail::executor_binder_result_type<T>,
  176. public detail::executor_binder_argument_type<T>,
  177. public detail::executor_binder_argument_types<T>,
  178. private detail::executor_binder_base<
  179. T, Executor, uses_executor<T, Executor>::value>
  180. #endif // !defined(GENERATING_DOCUMENTATION)
  181. {
  182. public:
  183. /// The type of the target object.
  184. typedef T target_type;
  185. /// The type of the associated executor.
  186. typedef Executor executor_type;
  187. #if defined(GENERATING_DOCUMENTATION)
  188. /// The return type if a function.
  189. /**
  190. * The type of @c result_type is based on the type @c T of the wrapper's
  191. * target object:
  192. *
  193. * @li if @c T is a pointer to function type, @c result_type is a synonym for
  194. * the return type of @c T;
  195. *
  196. * @li if @c T is a class type with a member type @c result_type, then @c
  197. * result_type is a synonym for @c T::result_type;
  198. *
  199. * @li otherwise @c result_type is not defined.
  200. */
  201. typedef see_below result_type;
  202. /// The type of the function's argument.
  203. /**
  204. * The type of @c argument_type is based on the type @c T of the wrapper's
  205. * target object:
  206. *
  207. * @li if @c T is a pointer to a function type accepting a single argument,
  208. * @c argument_type is a synonym for the return type of @c T;
  209. *
  210. * @li if @c T is a class type with a member type @c argument_type, then @c
  211. * argument_type is a synonym for @c T::argument_type;
  212. *
  213. * @li otherwise @c argument_type is not defined.
  214. */
  215. typedef see_below argument_type;
  216. /// The type of the function's first argument.
  217. /**
  218. * The type of @c first_argument_type is based on the type @c T of the
  219. * wrapper's target object:
  220. *
  221. * @li if @c T is a pointer to a function type accepting two arguments, @c
  222. * first_argument_type is a synonym for the return type of @c T;
  223. *
  224. * @li if @c T is a class type with a member type @c first_argument_type,
  225. * then @c first_argument_type is a synonym for @c T::first_argument_type;
  226. *
  227. * @li otherwise @c first_argument_type is not defined.
  228. */
  229. typedef see_below first_argument_type;
  230. /// The type of the function's second argument.
  231. /**
  232. * The type of @c second_argument_type is based on the type @c T of the
  233. * wrapper's target object:
  234. *
  235. * @li if @c T is a pointer to a function type accepting two arguments, @c
  236. * second_argument_type is a synonym for the return type of @c T;
  237. *
  238. * @li if @c T is a class type with a member type @c first_argument_type,
  239. * then @c second_argument_type is a synonym for @c T::second_argument_type;
  240. *
  241. * @li otherwise @c second_argument_type is not defined.
  242. */
  243. typedef see_below second_argument_type;
  244. #endif // defined(GENERATING_DOCUMENTATION)
  245. /// Construct an executor wrapper for the specified object.
  246. /**
  247. * This constructor is only valid if the type @c T is constructible from type
  248. * @c U.
  249. */
  250. template <typename U>
  251. executor_binder(executor_arg_t, const executor_type& e,
  252. ASIO_MOVE_ARG(U) u)
  253. : base_type(e, ASIO_MOVE_CAST(U)(u))
  254. {
  255. }
  256. /// Copy constructor.
  257. executor_binder(const executor_binder& other)
  258. : base_type(other.get_executor(), other.get())
  259. {
  260. }
  261. /// Construct a copy, but specify a different executor.
  262. executor_binder(executor_arg_t, const executor_type& e,
  263. const executor_binder& other)
  264. : base_type(e, other.get())
  265. {
  266. }
  267. /// Construct a copy of a different executor wrapper type.
  268. /**
  269. * This constructor is only valid if the @c Executor type is constructible
  270. * from type @c OtherExecutor, and the type @c T is constructible from type
  271. * @c U.
  272. */
  273. template <typename U, typename OtherExecutor>
  274. executor_binder(const executor_binder<U, OtherExecutor>& other)
  275. : base_type(other.get_executor(), other.get())
  276. {
  277. }
  278. /// Construct a copy of a different executor wrapper type, but specify a
  279. /// different executor.
  280. /**
  281. * This constructor is only valid if the type @c T is constructible from type
  282. * @c U.
  283. */
  284. template <typename U, typename OtherExecutor>
  285. executor_binder(executor_arg_t, const executor_type& e,
  286. const executor_binder<U, OtherExecutor>& other)
  287. : base_type(e, other.get())
  288. {
  289. }
  290. #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  291. /// Move constructor.
  292. executor_binder(executor_binder&& other)
  293. : base_type(ASIO_MOVE_CAST(executor_type)(other.get_executor()),
  294. ASIO_MOVE_CAST(T)(other.get()))
  295. {
  296. }
  297. /// Move construct the target object, but specify a different executor.
  298. executor_binder(executor_arg_t, const executor_type& e,
  299. executor_binder&& other)
  300. : base_type(e, ASIO_MOVE_CAST(T)(other.get()))
  301. {
  302. }
  303. /// Move construct from a different executor wrapper type.
  304. template <typename U, typename OtherExecutor>
  305. executor_binder(executor_binder<U, OtherExecutor>&& other)
  306. : base_type(ASIO_MOVE_CAST(OtherExecutor)(other.get_executor()),
  307. ASIO_MOVE_CAST(U)(other.get()))
  308. {
  309. }
  310. /// Move construct from a different executor wrapper type, but specify a
  311. /// different executor.
  312. template <typename U, typename OtherExecutor>
  313. executor_binder(executor_arg_t, const executor_type& e,
  314. executor_binder<U, OtherExecutor>&& other)
  315. : base_type(e, ASIO_MOVE_CAST(U)(other.get()))
  316. {
  317. }
  318. #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  319. /// Destructor.
  320. ~executor_binder()
  321. {
  322. }
  323. /// Obtain a reference to the target object.
  324. target_type& get() ASIO_NOEXCEPT
  325. {
  326. return this->target_;
  327. }
  328. /// Obtain a reference to the target object.
  329. const target_type& get() const ASIO_NOEXCEPT
  330. {
  331. return this->target_;
  332. }
  333. /// Obtain the associated executor.
  334. executor_type get_executor() const ASIO_NOEXCEPT
  335. {
  336. return this->executor_;
  337. }
  338. #if defined(GENERATING_DOCUMENTATION)
  339. template <typename... Args> auto operator()(Args&& ...);
  340. template <typename... Args> auto operator()(Args&& ...) const;
  341. #elif defined(ASIO_HAS_VARIADIC_TEMPLATES)
  342. /// Forwarding function call operator.
  343. template <typename... Args>
  344. typename result_of<T(Args...)>::type operator()(
  345. ASIO_MOVE_ARG(Args)... args)
  346. {
  347. return this->target_(ASIO_MOVE_CAST(Args)(args)...);
  348. }
  349. /// Forwarding function call operator.
  350. template <typename... Args>
  351. typename result_of<T(Args...)>::type operator()(
  352. ASIO_MOVE_ARG(Args)... args) const
  353. {
  354. return this->target_(ASIO_MOVE_CAST(Args)(args)...);
  355. }
  356. #elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
  357. typename detail::executor_binder_result_of0<T>::type operator()()
  358. {
  359. return this->target_();
  360. }
  361. typename detail::executor_binder_result_of0<T>::type operator()() const
  362. {
  363. return this->target_();
  364. }
  365. #define ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \
  366. template <ASIO_VARIADIC_TPARAMS(n)> \
  367. typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \
  368. ASIO_VARIADIC_MOVE_PARAMS(n)) \
  369. { \
  370. return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
  371. } \
  372. \
  373. template <ASIO_VARIADIC_TPARAMS(n)> \
  374. typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \
  375. ASIO_VARIADIC_MOVE_PARAMS(n)) const \
  376. { \
  377. return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
  378. } \
  379. /**/
  380. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF)
  381. #undef ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF
  382. #else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
  383. typedef typename detail::executor_binder_result_type<T>::result_type_or_void
  384. result_type_or_void;
  385. result_type_or_void operator()()
  386. {
  387. return this->target_();
  388. }
  389. result_type_or_void operator()() const
  390. {
  391. return this->target_();
  392. }
  393. #define ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \
  394. template <ASIO_VARIADIC_TPARAMS(n)> \
  395. result_type_or_void operator()( \
  396. ASIO_VARIADIC_MOVE_PARAMS(n)) \
  397. { \
  398. return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
  399. } \
  400. \
  401. template <ASIO_VARIADIC_TPARAMS(n)> \
  402. result_type_or_void operator()( \
  403. ASIO_VARIADIC_MOVE_PARAMS(n)) const \
  404. { \
  405. return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \
  406. } \
  407. /**/
  408. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF)
  409. #undef ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF
  410. #endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
  411. private:
  412. typedef detail::executor_binder_base<T, Executor,
  413. uses_executor<T, Executor>::value> base_type;
  414. };
  415. /// Associate an object of type @c T with an executor of type @c Executor.
  416. template <typename Executor, typename T>
  417. ASIO_NODISCARD inline executor_binder<typename decay<T>::type, Executor>
  418. bind_executor(const Executor& ex, ASIO_MOVE_ARG(T) t,
  419. typename constraint<
  420. is_executor<Executor>::value || execution::is_executor<Executor>::value
  421. >::type = 0)
  422. {
  423. return executor_binder<typename decay<T>::type, Executor>(
  424. executor_arg_t(), ex, ASIO_MOVE_CAST(T)(t));
  425. }
  426. /// Associate an object of type @c T with an execution context's executor.
  427. template <typename ExecutionContext, typename T>
  428. ASIO_NODISCARD inline executor_binder<typename decay<T>::type,
  429. typename ExecutionContext::executor_type>
  430. bind_executor(ExecutionContext& ctx, ASIO_MOVE_ARG(T) t,
  431. typename constraint<is_convertible<
  432. ExecutionContext&, execution_context&>::value>::type = 0)
  433. {
  434. return executor_binder<typename decay<T>::type,
  435. typename ExecutionContext::executor_type>(
  436. executor_arg_t(), ctx.get_executor(), ASIO_MOVE_CAST(T)(t));
  437. }
  438. #if !defined(GENERATING_DOCUMENTATION)
  439. template <typename T, typename Executor>
  440. struct uses_executor<executor_binder<T, Executor>, Executor>
  441. : true_type {};
  442. namespace detail {
  443. template <typename TargetAsyncResult, typename Executor, typename = void>
  444. class executor_binder_completion_handler_async_result
  445. {
  446. public:
  447. template <typename T>
  448. explicit executor_binder_completion_handler_async_result(T&)
  449. {
  450. }
  451. };
  452. template <typename TargetAsyncResult, typename Executor>
  453. class executor_binder_completion_handler_async_result<
  454. TargetAsyncResult, Executor,
  455. typename void_type<
  456. typename TargetAsyncResult::completion_handler_type
  457. >::type>
  458. {
  459. public:
  460. typedef executor_binder<
  461. typename TargetAsyncResult::completion_handler_type, Executor>
  462. completion_handler_type;
  463. explicit executor_binder_completion_handler_async_result(
  464. typename TargetAsyncResult::completion_handler_type& handler)
  465. : target_(handler)
  466. {
  467. }
  468. typename TargetAsyncResult::return_type get()
  469. {
  470. return target_.get();
  471. }
  472. private:
  473. TargetAsyncResult target_;
  474. };
  475. template <typename TargetAsyncResult, typename = void>
  476. struct executor_binder_async_result_return_type
  477. {
  478. };
  479. template <typename TargetAsyncResult>
  480. struct executor_binder_async_result_return_type<
  481. TargetAsyncResult,
  482. typename void_type<
  483. typename TargetAsyncResult::return_type
  484. >::type>
  485. {
  486. typedef typename TargetAsyncResult::return_type return_type;
  487. };
  488. } // namespace detail
  489. template <typename T, typename Executor, typename Signature>
  490. class async_result<executor_binder<T, Executor>, Signature> :
  491. public detail::executor_binder_completion_handler_async_result<
  492. async_result<T, Signature>, Executor>,
  493. public detail::executor_binder_async_result_return_type<
  494. async_result<T, Signature> >
  495. {
  496. public:
  497. explicit async_result(executor_binder<T, Executor>& b)
  498. : detail::executor_binder_completion_handler_async_result<
  499. async_result<T, Signature>, Executor>(b.get())
  500. {
  501. }
  502. template <typename Initiation>
  503. struct init_wrapper
  504. {
  505. template <typename Init>
  506. init_wrapper(const Executor& ex, ASIO_MOVE_ARG(Init) init)
  507. : ex_(ex),
  508. initiation_(ASIO_MOVE_CAST(Init)(init))
  509. {
  510. }
  511. #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  512. template <typename Handler, typename... Args>
  513. void operator()(
  514. ASIO_MOVE_ARG(Handler) handler,
  515. ASIO_MOVE_ARG(Args)... args)
  516. {
  517. ASIO_MOVE_CAST(Initiation)(initiation_)(
  518. executor_binder<typename decay<Handler>::type, Executor>(
  519. executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)),
  520. ASIO_MOVE_CAST(Args)(args)...);
  521. }
  522. template <typename Handler, typename... Args>
  523. void operator()(
  524. ASIO_MOVE_ARG(Handler) handler,
  525. ASIO_MOVE_ARG(Args)... args) const
  526. {
  527. initiation_(
  528. executor_binder<typename decay<Handler>::type, Executor>(
  529. executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)),
  530. ASIO_MOVE_CAST(Args)(args)...);
  531. }
  532. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  533. template <typename Handler>
  534. void operator()(
  535. ASIO_MOVE_ARG(Handler) handler)
  536. {
  537. ASIO_MOVE_CAST(Initiation)(initiation_)(
  538. executor_binder<typename decay<Handler>::type, Executor>(
  539. executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)));
  540. }
  541. template <typename Handler>
  542. void operator()(
  543. ASIO_MOVE_ARG(Handler) handler) const
  544. {
  545. initiation_(
  546. executor_binder<typename decay<Handler>::type, Executor>(
  547. executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)));
  548. }
  549. #define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
  550. template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \
  551. void operator()( \
  552. ASIO_MOVE_ARG(Handler) handler, \
  553. ASIO_VARIADIC_MOVE_PARAMS(n)) \
  554. { \
  555. ASIO_MOVE_CAST(Initiation)(initiation_)( \
  556. executor_binder<typename decay<Handler>::type, Executor>( \
  557. executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), \
  558. ASIO_VARIADIC_MOVE_ARGS(n)); \
  559. } \
  560. \
  561. template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \
  562. void operator()( \
  563. ASIO_MOVE_ARG(Handler) handler, \
  564. ASIO_VARIADIC_MOVE_PARAMS(n)) const \
  565. { \
  566. initiation_( \
  567. executor_binder<typename decay<Handler>::type, Executor>( \
  568. executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), \
  569. ASIO_VARIADIC_MOVE_ARGS(n)); \
  570. } \
  571. /**/
  572. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)
  573. #undef ASIO_PRIVATE_INIT_WRAPPER_DEF
  574. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  575. Executor ex_;
  576. Initiation initiation_;
  577. };
  578. #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  579. template <typename Initiation, typename RawCompletionToken, typename... Args>
  580. static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
  581. (async_initiate<T, Signature>(
  582. declval<init_wrapper<typename decay<Initiation>::type> >(),
  583. declval<RawCompletionToken>().get(),
  584. declval<ASIO_MOVE_ARG(Args)>()...)))
  585. initiate(
  586. ASIO_MOVE_ARG(Initiation) initiation,
  587. ASIO_MOVE_ARG(RawCompletionToken) token,
  588. ASIO_MOVE_ARG(Args)... args)
  589. {
  590. return async_initiate<T, Signature>(
  591. init_wrapper<typename decay<Initiation>::type>(
  592. token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)),
  593. token.get(), ASIO_MOVE_CAST(Args)(args)...);
  594. }
  595. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  596. template <typename Initiation, typename RawCompletionToken>
  597. static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
  598. (async_initiate<T, Signature>(
  599. declval<init_wrapper<typename decay<Initiation>::type> >(),
  600. declval<RawCompletionToken>().get())))
  601. initiate(
  602. ASIO_MOVE_ARG(Initiation) initiation,
  603. ASIO_MOVE_ARG(RawCompletionToken) token)
  604. {
  605. return async_initiate<T, Signature>(
  606. init_wrapper<typename decay<Initiation>::type>(
  607. token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)),
  608. token.get());
  609. }
  610. #define ASIO_PRIVATE_INITIATE_DEF(n) \
  611. template <typename Initiation, typename RawCompletionToken, \
  612. ASIO_VARIADIC_TPARAMS(n)> \
  613. static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \
  614. (async_initiate<T, Signature>( \
  615. declval<init_wrapper<typename decay<Initiation>::type> >(), \
  616. declval<RawCompletionToken>().get(), \
  617. ASIO_VARIADIC_MOVE_DECLVAL(n)))) \
  618. initiate( \
  619. ASIO_MOVE_ARG(Initiation) initiation, \
  620. ASIO_MOVE_ARG(RawCompletionToken) token, \
  621. ASIO_VARIADIC_MOVE_PARAMS(n)) \
  622. { \
  623. return async_initiate<T, Signature>( \
  624. init_wrapper<typename decay<Initiation>::type>( \
  625. token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)), \
  626. token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \
  627. } \
  628. /**/
  629. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)
  630. #undef ASIO_PRIVATE_INITIATE_DEF
  631. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  632. private:
  633. async_result(const async_result&) ASIO_DELETED;
  634. async_result& operator=(const async_result&) ASIO_DELETED;
  635. };
  636. template <template <typename, typename> class Associator,
  637. typename T, typename Executor, typename DefaultCandidate>
  638. struct associator<Associator, executor_binder<T, Executor>, DefaultCandidate>
  639. {
  640. typedef typename Associator<T, DefaultCandidate>::type type;
  641. static type get(const executor_binder<T, Executor>& b,
  642. const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT
  643. {
  644. return Associator<T, DefaultCandidate>::get(b.get(), c);
  645. }
  646. };
  647. template <typename T, typename Executor, typename Executor1>
  648. struct associated_executor<executor_binder<T, Executor>, Executor1>
  649. {
  650. typedef Executor type;
  651. static type get(const executor_binder<T, Executor>& b,
  652. const Executor1& = Executor1()) ASIO_NOEXCEPT
  653. {
  654. return b.get_executor();
  655. }
  656. };
  657. #endif // !defined(GENERATING_DOCUMENTATION)
  658. } // namespace asio
  659. #include "asio/detail/pop_options.hpp"
  660. #endif // ASIO_BIND_EXECUTOR_HPP