any_completion_handler.hpp 22 KB

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