any_completion_handler.hpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824
  1. //
  2. // any_completion_handler.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_ANY_COMPLETION_HANDLER_HPP
  11. #define BOOST_ASIO_ANY_COMPLETION_HANDLER_HPP
  12. #include <boost/asio/detail/config.hpp>
  13. #include <cstring>
  14. #include <functional>
  15. #include <memory>
  16. #include <utility>
  17. #include <boost/asio/any_completion_executor.hpp>
  18. #include <boost/asio/any_io_executor.hpp>
  19. #include <boost/asio/associated_allocator.hpp>
  20. #include <boost/asio/associated_cancellation_slot.hpp>
  21. #include <boost/asio/associated_executor.hpp>
  22. #include <boost/asio/associated_immediate_executor.hpp>
  23. #include <boost/asio/cancellation_state.hpp>
  24. #include <boost/asio/recycling_allocator.hpp>
  25. #include <boost/asio/detail/push_options.hpp>
  26. namespace boost {
  27. namespace asio {
  28. namespace detail {
  29. class any_completion_handler_impl_base
  30. {
  31. public:
  32. template <typename S>
  33. explicit any_completion_handler_impl_base(S&& slot)
  34. : cancel_state_(static_cast<S&&>(slot), enable_total_cancellation())
  35. {
  36. }
  37. cancellation_slot get_cancellation_slot() const noexcept
  38. {
  39. return cancel_state_.slot();
  40. }
  41. private:
  42. cancellation_state cancel_state_;
  43. };
  44. template <typename Handler>
  45. class any_completion_handler_impl :
  46. public any_completion_handler_impl_base
  47. {
  48. public:
  49. template <typename S, typename H>
  50. any_completion_handler_impl(S&& slot, H&& h)
  51. : any_completion_handler_impl_base(static_cast<S&&>(slot)),
  52. handler_(static_cast<H&&>(h))
  53. {
  54. }
  55. struct uninit_deleter
  56. {
  57. typename std::allocator_traits<
  58. associated_allocator_t<Handler,
  59. boost::asio::recycling_allocator<void>>>::template
  60. rebind_alloc<any_completion_handler_impl> alloc;
  61. void operator()(any_completion_handler_impl* ptr)
  62. {
  63. std::allocator_traits<decltype(alloc)>::deallocate(alloc, ptr, 1);
  64. }
  65. };
  66. struct deleter
  67. {
  68. typename std::allocator_traits<
  69. associated_allocator_t<Handler,
  70. boost::asio::recycling_allocator<void>>>::template
  71. rebind_alloc<any_completion_handler_impl> alloc;
  72. void operator()(any_completion_handler_impl* ptr)
  73. {
  74. std::allocator_traits<decltype(alloc)>::destroy(alloc, ptr);
  75. std::allocator_traits<decltype(alloc)>::deallocate(alloc, ptr, 1);
  76. }
  77. };
  78. template <typename S, typename H>
  79. static any_completion_handler_impl* create(S&& slot, H&& h)
  80. {
  81. uninit_deleter d{
  82. (get_associated_allocator)(h,
  83. boost::asio::recycling_allocator<void>())};
  84. std::unique_ptr<any_completion_handler_impl, uninit_deleter> uninit_ptr(
  85. std::allocator_traits<decltype(d.alloc)>::allocate(d.alloc, 1), d);
  86. any_completion_handler_impl* ptr =
  87. new (uninit_ptr.get()) any_completion_handler_impl(
  88. static_cast<S&&>(slot), static_cast<H&&>(h));
  89. uninit_ptr.release();
  90. return ptr;
  91. }
  92. void destroy()
  93. {
  94. deleter d{
  95. (get_associated_allocator)(handler_,
  96. boost::asio::recycling_allocator<void>())};
  97. d(this);
  98. }
  99. any_completion_executor executor(
  100. const any_completion_executor& candidate) const noexcept
  101. {
  102. return any_completion_executor(std::nothrow,
  103. (get_associated_executor)(handler_, candidate));
  104. }
  105. any_completion_executor immediate_executor(
  106. const any_io_executor& candidate) const noexcept
  107. {
  108. return any_completion_executor(std::nothrow,
  109. (get_associated_immediate_executor)(handler_, candidate));
  110. }
  111. void* allocate(std::size_t size, std::size_t align) const
  112. {
  113. typename std::allocator_traits<
  114. associated_allocator_t<Handler,
  115. boost::asio::recycling_allocator<void>>>::template
  116. rebind_alloc<unsigned char> alloc(
  117. (get_associated_allocator)(handler_,
  118. boost::asio::recycling_allocator<void>()));
  119. std::size_t space = size + align - 1;
  120. unsigned char* base =
  121. std::allocator_traits<decltype(alloc)>::allocate(
  122. alloc, space + sizeof(std::ptrdiff_t));
  123. void* p = base;
  124. if (detail::align(align, size, p, space))
  125. {
  126. std::ptrdiff_t off = static_cast<unsigned char*>(p) - base;
  127. std::memcpy(static_cast<unsigned char*>(p) + size, &off, sizeof(off));
  128. return p;
  129. }
  130. std::bad_alloc ex;
  131. boost::asio::detail::throw_exception(ex);
  132. return nullptr;
  133. }
  134. void deallocate(void* p, std::size_t size, std::size_t align) const
  135. {
  136. if (p)
  137. {
  138. typename std::allocator_traits<
  139. associated_allocator_t<Handler,
  140. boost::asio::recycling_allocator<void>>>::template
  141. rebind_alloc<unsigned char> alloc(
  142. (get_associated_allocator)(handler_,
  143. boost::asio::recycling_allocator<void>()));
  144. std::ptrdiff_t off;
  145. std::memcpy(&off, static_cast<unsigned char*>(p) + size, sizeof(off));
  146. unsigned char* base = static_cast<unsigned char*>(p) - off;
  147. std::allocator_traits<decltype(alloc)>::deallocate(
  148. alloc, base, size + align -1 + sizeof(std::ptrdiff_t));
  149. }
  150. }
  151. template <typename... Args>
  152. void call(Args&&... args)
  153. {
  154. deleter d{
  155. (get_associated_allocator)(handler_,
  156. boost::asio::recycling_allocator<void>())};
  157. std::unique_ptr<any_completion_handler_impl, deleter> ptr(this, d);
  158. Handler handler(static_cast<Handler&&>(handler_));
  159. ptr.reset();
  160. static_cast<Handler&&>(handler)(
  161. static_cast<Args&&>(args)...);
  162. }
  163. private:
  164. Handler handler_;
  165. };
  166. template <typename Signature>
  167. class any_completion_handler_call_fn;
  168. template <typename R, typename... Args>
  169. class any_completion_handler_call_fn<R(Args...)>
  170. {
  171. public:
  172. using type = void(*)(any_completion_handler_impl_base*, Args...);
  173. constexpr any_completion_handler_call_fn(type fn)
  174. : call_fn_(fn)
  175. {
  176. }
  177. void call(any_completion_handler_impl_base* impl, Args... args) const
  178. {
  179. call_fn_(impl, static_cast<Args&&>(args)...);
  180. }
  181. template <typename Handler>
  182. static void impl(any_completion_handler_impl_base* impl, Args... args)
  183. {
  184. static_cast<any_completion_handler_impl<Handler>*>(impl)->call(
  185. static_cast<Args&&>(args)...);
  186. }
  187. private:
  188. type call_fn_;
  189. };
  190. template <typename... Signatures>
  191. class any_completion_handler_call_fns;
  192. template <typename Signature>
  193. class any_completion_handler_call_fns<Signature> :
  194. public any_completion_handler_call_fn<Signature>
  195. {
  196. public:
  197. using any_completion_handler_call_fn<
  198. Signature>::any_completion_handler_call_fn;
  199. using any_completion_handler_call_fn<Signature>::call;
  200. };
  201. template <typename Signature, typename... Signatures>
  202. class any_completion_handler_call_fns<Signature, Signatures...> :
  203. public any_completion_handler_call_fn<Signature>,
  204. public any_completion_handler_call_fns<Signatures...>
  205. {
  206. public:
  207. template <typename CallFn, typename... CallFns>
  208. constexpr any_completion_handler_call_fns(CallFn fn, CallFns... fns)
  209. : any_completion_handler_call_fn<Signature>(fn),
  210. any_completion_handler_call_fns<Signatures...>(fns...)
  211. {
  212. }
  213. using any_completion_handler_call_fn<Signature>::call;
  214. using any_completion_handler_call_fns<Signatures...>::call;
  215. };
  216. class any_completion_handler_destroy_fn
  217. {
  218. public:
  219. using type = void(*)(any_completion_handler_impl_base*);
  220. constexpr any_completion_handler_destroy_fn(type fn)
  221. : destroy_fn_(fn)
  222. {
  223. }
  224. void destroy(any_completion_handler_impl_base* impl) const
  225. {
  226. destroy_fn_(impl);
  227. }
  228. template <typename Handler>
  229. static void impl(any_completion_handler_impl_base* impl)
  230. {
  231. static_cast<any_completion_handler_impl<Handler>*>(impl)->destroy();
  232. }
  233. private:
  234. type destroy_fn_;
  235. };
  236. class any_completion_handler_executor_fn
  237. {
  238. public:
  239. using type = any_completion_executor(*)(
  240. any_completion_handler_impl_base*, const any_completion_executor&);
  241. constexpr any_completion_handler_executor_fn(type fn)
  242. : executor_fn_(fn)
  243. {
  244. }
  245. any_completion_executor executor(any_completion_handler_impl_base* impl,
  246. const any_completion_executor& candidate) const
  247. {
  248. return executor_fn_(impl, candidate);
  249. }
  250. template <typename Handler>
  251. static any_completion_executor impl(any_completion_handler_impl_base* impl,
  252. const any_completion_executor& candidate)
  253. {
  254. return static_cast<any_completion_handler_impl<Handler>*>(impl)->executor(
  255. candidate);
  256. }
  257. private:
  258. type executor_fn_;
  259. };
  260. class any_completion_handler_immediate_executor_fn
  261. {
  262. public:
  263. using type = any_completion_executor(*)(
  264. any_completion_handler_impl_base*, const any_io_executor&);
  265. constexpr any_completion_handler_immediate_executor_fn(type fn)
  266. : immediate_executor_fn_(fn)
  267. {
  268. }
  269. any_completion_executor immediate_executor(
  270. any_completion_handler_impl_base* impl,
  271. const any_io_executor& candidate) const
  272. {
  273. return immediate_executor_fn_(impl, candidate);
  274. }
  275. template <typename Handler>
  276. static any_completion_executor impl(any_completion_handler_impl_base* impl,
  277. const any_io_executor& candidate)
  278. {
  279. return static_cast<any_completion_handler_impl<Handler>*>(
  280. impl)->immediate_executor(candidate);
  281. }
  282. private:
  283. type immediate_executor_fn_;
  284. };
  285. class any_completion_handler_allocate_fn
  286. {
  287. public:
  288. using type = void*(*)(any_completion_handler_impl_base*,
  289. std::size_t, std::size_t);
  290. constexpr any_completion_handler_allocate_fn(type fn)
  291. : allocate_fn_(fn)
  292. {
  293. }
  294. void* allocate(any_completion_handler_impl_base* impl,
  295. std::size_t size, std::size_t align) const
  296. {
  297. return allocate_fn_(impl, size, align);
  298. }
  299. template <typename Handler>
  300. static void* impl(any_completion_handler_impl_base* impl,
  301. std::size_t size, std::size_t align)
  302. {
  303. return static_cast<any_completion_handler_impl<Handler>*>(impl)->allocate(
  304. size, align);
  305. }
  306. private:
  307. type allocate_fn_;
  308. };
  309. class any_completion_handler_deallocate_fn
  310. {
  311. public:
  312. using type = void(*)(any_completion_handler_impl_base*,
  313. void*, std::size_t, std::size_t);
  314. constexpr any_completion_handler_deallocate_fn(type fn)
  315. : deallocate_fn_(fn)
  316. {
  317. }
  318. void deallocate(any_completion_handler_impl_base* impl,
  319. void* p, std::size_t size, std::size_t align) const
  320. {
  321. deallocate_fn_(impl, p, size, align);
  322. }
  323. template <typename Handler>
  324. static void impl(any_completion_handler_impl_base* impl,
  325. void* p, std::size_t size, std::size_t align)
  326. {
  327. static_cast<any_completion_handler_impl<Handler>*>(impl)->deallocate(
  328. p, size, align);
  329. }
  330. private:
  331. type deallocate_fn_;
  332. };
  333. template <typename... Signatures>
  334. class any_completion_handler_fn_table
  335. : private any_completion_handler_destroy_fn,
  336. private any_completion_handler_executor_fn,
  337. private any_completion_handler_immediate_executor_fn,
  338. private any_completion_handler_allocate_fn,
  339. private any_completion_handler_deallocate_fn,
  340. private any_completion_handler_call_fns<Signatures...>
  341. {
  342. public:
  343. template <typename... CallFns>
  344. constexpr any_completion_handler_fn_table(
  345. any_completion_handler_destroy_fn::type destroy_fn,
  346. any_completion_handler_executor_fn::type executor_fn,
  347. any_completion_handler_immediate_executor_fn::type immediate_executor_fn,
  348. any_completion_handler_allocate_fn::type allocate_fn,
  349. any_completion_handler_deallocate_fn::type deallocate_fn,
  350. CallFns... call_fns)
  351. : any_completion_handler_destroy_fn(destroy_fn),
  352. any_completion_handler_executor_fn(executor_fn),
  353. any_completion_handler_immediate_executor_fn(immediate_executor_fn),
  354. any_completion_handler_allocate_fn(allocate_fn),
  355. any_completion_handler_deallocate_fn(deallocate_fn),
  356. any_completion_handler_call_fns<Signatures...>(call_fns...)
  357. {
  358. }
  359. using any_completion_handler_destroy_fn::destroy;
  360. using any_completion_handler_executor_fn::executor;
  361. using any_completion_handler_immediate_executor_fn::immediate_executor;
  362. using any_completion_handler_allocate_fn::allocate;
  363. using any_completion_handler_deallocate_fn::deallocate;
  364. using any_completion_handler_call_fns<Signatures...>::call;
  365. };
  366. template <typename Handler, typename... Signatures>
  367. struct any_completion_handler_fn_table_instance
  368. {
  369. static constexpr any_completion_handler_fn_table<Signatures...>
  370. value = any_completion_handler_fn_table<Signatures...>(
  371. &any_completion_handler_destroy_fn::impl<Handler>,
  372. &any_completion_handler_executor_fn::impl<Handler>,
  373. &any_completion_handler_immediate_executor_fn::impl<Handler>,
  374. &any_completion_handler_allocate_fn::impl<Handler>,
  375. &any_completion_handler_deallocate_fn::impl<Handler>,
  376. &any_completion_handler_call_fn<Signatures>::template impl<Handler>...);
  377. };
  378. template <typename Handler, typename... Signatures>
  379. constexpr any_completion_handler_fn_table<Signatures...>
  380. any_completion_handler_fn_table_instance<Handler, Signatures...>::value;
  381. } // namespace detail
  382. template <typename... Signatures>
  383. class any_completion_handler;
  384. /// An allocator type that forwards memory allocation operations through an
  385. /// instance of @c any_completion_handler.
  386. template <typename T, typename... Signatures>
  387. class any_completion_handler_allocator
  388. {
  389. private:
  390. template <typename...>
  391. friend class any_completion_handler;
  392. template <typename, typename...>
  393. friend class any_completion_handler_allocator;
  394. const detail::any_completion_handler_fn_table<Signatures...>* fn_table_;
  395. detail::any_completion_handler_impl_base* impl_;
  396. constexpr any_completion_handler_allocator(int,
  397. const any_completion_handler<Signatures...>& h) noexcept
  398. : fn_table_(h.fn_table_),
  399. impl_(h.impl_)
  400. {
  401. }
  402. public:
  403. /// The type of objects that may be allocated by the allocator.
  404. typedef T value_type;
  405. /// Rebinds an allocator to another value type.
  406. template <typename U>
  407. struct rebind
  408. {
  409. /// Specifies the type of the rebound allocator.
  410. typedef any_completion_handler_allocator<U, Signatures...> other;
  411. };
  412. /// Construct from another @c any_completion_handler_allocator.
  413. template <typename U>
  414. constexpr any_completion_handler_allocator(
  415. const any_completion_handler_allocator<U, Signatures...>& a)
  416. noexcept
  417. : fn_table_(a.fn_table_),
  418. impl_(a.impl_)
  419. {
  420. }
  421. /// Equality operator.
  422. constexpr bool operator==(
  423. const any_completion_handler_allocator& other) const noexcept
  424. {
  425. return fn_table_ == other.fn_table_ && impl_ == other.impl_;
  426. }
  427. /// Inequality operator.
  428. constexpr bool operator!=(
  429. const any_completion_handler_allocator& other) const noexcept
  430. {
  431. return fn_table_ != other.fn_table_ || impl_ != other.impl_;
  432. }
  433. /// Allocate space for @c n objects of the allocator's value type.
  434. T* allocate(std::size_t n) const
  435. {
  436. if (fn_table_)
  437. {
  438. return static_cast<T*>(
  439. fn_table_->allocate(
  440. impl_, sizeof(T) * n, alignof(T)));
  441. }
  442. std::bad_alloc ex;
  443. boost::asio::detail::throw_exception(ex);
  444. return nullptr;
  445. }
  446. /// Deallocate space for @c n objects of the allocator's value type.
  447. void deallocate(T* p, std::size_t n) const
  448. {
  449. fn_table_->deallocate(impl_, p, sizeof(T) * n, alignof(T));
  450. }
  451. };
  452. /// A protoco-allocator type that may be rebound to obtain an allocator that
  453. /// forwards memory allocation operations through an instance of
  454. /// @c any_completion_handler.
  455. template <typename... Signatures>
  456. class any_completion_handler_allocator<void, Signatures...>
  457. {
  458. private:
  459. template <typename...>
  460. friend class any_completion_handler;
  461. template <typename, typename...>
  462. friend class any_completion_handler_allocator;
  463. const detail::any_completion_handler_fn_table<Signatures...>* fn_table_;
  464. detail::any_completion_handler_impl_base* impl_;
  465. constexpr any_completion_handler_allocator(int,
  466. const any_completion_handler<Signatures...>& h) noexcept
  467. : fn_table_(h.fn_table_),
  468. impl_(h.impl_)
  469. {
  470. }
  471. public:
  472. /// @c void as no objects can be allocated through a proto-allocator.
  473. typedef void value_type;
  474. /// Rebinds an allocator to another value type.
  475. template <typename U>
  476. struct rebind
  477. {
  478. /// Specifies the type of the rebound allocator.
  479. typedef any_completion_handler_allocator<U, Signatures...> other;
  480. };
  481. /// Construct from another @c any_completion_handler_allocator.
  482. template <typename U>
  483. constexpr any_completion_handler_allocator(
  484. const any_completion_handler_allocator<U, Signatures...>& a)
  485. noexcept
  486. : fn_table_(a.fn_table_),
  487. impl_(a.impl_)
  488. {
  489. }
  490. /// Equality operator.
  491. constexpr bool operator==(
  492. const any_completion_handler_allocator& other) const noexcept
  493. {
  494. return fn_table_ == other.fn_table_ && impl_ == other.impl_;
  495. }
  496. /// Inequality operator.
  497. constexpr bool operator!=(
  498. const any_completion_handler_allocator& other) const noexcept
  499. {
  500. return fn_table_ != other.fn_table_ || impl_ != other.impl_;
  501. }
  502. };
  503. /// Polymorphic wrapper for completion handlers.
  504. /**
  505. * The @c any_completion_handler class template is a polymorphic wrapper for
  506. * completion handlers that propagates the associated executor, associated
  507. * allocator, and associated cancellation slot through a type-erasing interface.
  508. *
  509. * When using @c any_completion_handler, specify one or more completion
  510. * signatures as template parameters. These will dictate the arguments that may
  511. * be passed to the handler through the polymorphic interface.
  512. *
  513. * Typical uses for @c any_completion_handler include:
  514. *
  515. * @li Separate compilation of asynchronous operation implementations.
  516. *
  517. * @li Enabling interoperability between asynchronous operations and virtual
  518. * functions.
  519. */
  520. template <typename... Signatures>
  521. class any_completion_handler
  522. {
  523. #if !defined(GENERATING_DOCUMENTATION)
  524. private:
  525. template <typename, typename...>
  526. friend class any_completion_handler_allocator;
  527. template <typename, typename>
  528. friend struct associated_executor;
  529. template <typename, typename>
  530. friend struct associated_immediate_executor;
  531. const detail::any_completion_handler_fn_table<Signatures...>* fn_table_;
  532. detail::any_completion_handler_impl_base* impl_;
  533. #endif // !defined(GENERATING_DOCUMENTATION)
  534. public:
  535. /// The associated allocator type.
  536. using allocator_type = any_completion_handler_allocator<void, Signatures...>;
  537. /// The associated cancellation slot type.
  538. using cancellation_slot_type = cancellation_slot;
  539. /// Construct an @c any_completion_handler in an empty state, without a target
  540. /// object.
  541. constexpr any_completion_handler()
  542. : fn_table_(nullptr),
  543. impl_(nullptr)
  544. {
  545. }
  546. /// Construct an @c any_completion_handler in an empty state, without a target
  547. /// object.
  548. constexpr any_completion_handler(nullptr_t)
  549. : fn_table_(nullptr),
  550. impl_(nullptr)
  551. {
  552. }
  553. /// Construct an @c any_completion_handler to contain the specified target.
  554. template <typename H, typename Handler = decay_t<H>>
  555. any_completion_handler(H&& h,
  556. constraint_t<
  557. !is_same<decay_t<H>, any_completion_handler>::value
  558. > = 0)
  559. : fn_table_(
  560. &detail::any_completion_handler_fn_table_instance<
  561. Handler, Signatures...>::value),
  562. impl_(detail::any_completion_handler_impl<Handler>::create(
  563. (get_associated_cancellation_slot)(h), static_cast<H&&>(h)))
  564. {
  565. }
  566. /// Move-construct an @c any_completion_handler from another.
  567. /**
  568. * After the operation, the moved-from object @c other has no target.
  569. */
  570. any_completion_handler(any_completion_handler&& other) noexcept
  571. : fn_table_(other.fn_table_),
  572. impl_(other.impl_)
  573. {
  574. other.fn_table_ = nullptr;
  575. other.impl_ = nullptr;
  576. }
  577. /// Move-assign an @c any_completion_handler from another.
  578. /**
  579. * After the operation, the moved-from object @c other has no target.
  580. */
  581. any_completion_handler& operator=(
  582. any_completion_handler&& other) noexcept
  583. {
  584. any_completion_handler(
  585. static_cast<any_completion_handler&&>(other)).swap(*this);
  586. return *this;
  587. }
  588. /// Assignment operator that sets the polymorphic wrapper to the empty state.
  589. any_completion_handler& operator=(nullptr_t) noexcept
  590. {
  591. any_completion_handler().swap(*this);
  592. return *this;
  593. }
  594. /// Destructor.
  595. ~any_completion_handler()
  596. {
  597. if (impl_)
  598. fn_table_->destroy(impl_);
  599. }
  600. /// Test if the polymorphic wrapper is empty.
  601. constexpr explicit operator bool() const noexcept
  602. {
  603. return impl_ != nullptr;
  604. }
  605. /// Test if the polymorphic wrapper is non-empty.
  606. constexpr bool operator!() const noexcept
  607. {
  608. return impl_ == nullptr;
  609. }
  610. /// Swap the content of an @c any_completion_handler with another.
  611. void swap(any_completion_handler& other) noexcept
  612. {
  613. std::swap(fn_table_, other.fn_table_);
  614. std::swap(impl_, other.impl_);
  615. }
  616. /// Get the associated allocator.
  617. allocator_type get_allocator() const noexcept
  618. {
  619. return allocator_type(0, *this);
  620. }
  621. /// Get the associated cancellation slot.
  622. cancellation_slot_type get_cancellation_slot() const noexcept
  623. {
  624. return impl_ ? impl_->get_cancellation_slot() : cancellation_slot_type();
  625. }
  626. /// Function call operator.
  627. /**
  628. * Invokes target completion handler with the supplied arguments.
  629. *
  630. * This function may only be called once, as the target handler is moved from.
  631. * The polymorphic wrapper is left in an empty state.
  632. *
  633. * Throws @c std::bad_function_call if the polymorphic wrapper is empty.
  634. */
  635. template <typename... Args>
  636. auto operator()(Args&&... args)
  637. -> decltype(fn_table_->call(impl_, static_cast<Args&&>(args)...))
  638. {
  639. if (detail::any_completion_handler_impl_base* impl = impl_)
  640. {
  641. impl_ = nullptr;
  642. return fn_table_->call(impl, static_cast<Args&&>(args)...);
  643. }
  644. std::bad_function_call ex;
  645. boost::asio::detail::throw_exception(ex);
  646. }
  647. /// Equality operator.
  648. friend constexpr bool operator==(
  649. const any_completion_handler& a, nullptr_t) noexcept
  650. {
  651. return a.impl_ == nullptr;
  652. }
  653. /// Equality operator.
  654. friend constexpr bool operator==(
  655. nullptr_t, const any_completion_handler& b) noexcept
  656. {
  657. return nullptr == b.impl_;
  658. }
  659. /// Inequality operator.
  660. friend constexpr bool operator!=(
  661. const any_completion_handler& a, nullptr_t) noexcept
  662. {
  663. return a.impl_ != nullptr;
  664. }
  665. /// Inequality operator.
  666. friend constexpr bool operator!=(
  667. nullptr_t, const any_completion_handler& b) noexcept
  668. {
  669. return nullptr != b.impl_;
  670. }
  671. };
  672. template <typename... Signatures, typename Candidate>
  673. struct associated_executor<any_completion_handler<Signatures...>, Candidate>
  674. {
  675. using type = any_completion_executor;
  676. static type get(const any_completion_handler<Signatures...>& handler,
  677. const Candidate& candidate = Candidate()) noexcept
  678. {
  679. any_completion_executor any_candidate(std::nothrow, candidate);
  680. return handler.fn_table_
  681. ? handler.fn_table_->executor(handler.impl_, any_candidate)
  682. : any_candidate;
  683. }
  684. };
  685. template <typename... Signatures, typename Candidate>
  686. struct associated_immediate_executor<
  687. any_completion_handler<Signatures...>, Candidate>
  688. {
  689. using type = any_completion_executor;
  690. static type get(const any_completion_handler<Signatures...>& handler,
  691. const Candidate& candidate = Candidate()) noexcept
  692. {
  693. any_io_executor any_candidate(std::nothrow, candidate);
  694. return handler.fn_table_
  695. ? handler.fn_table_->immediate_executor(handler.impl_, any_candidate)
  696. : any_candidate;
  697. }
  698. };
  699. } // namespace asio
  700. } // namespace boost
  701. #include <boost/asio/detail/pop_options.hpp>
  702. #endif // BOOST_ASIO_ANY_COMPLETION_HANDLER_HPP