cancellation_signal.hpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. //
  2. // cancellation_signal.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_CANCELLATION_SIGNAL_HPP
  11. #define ASIO_CANCELLATION_SIGNAL_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 <cassert>
  17. #include <new>
  18. #include <utility>
  19. #include "asio/cancellation_type.hpp"
  20. #include "asio/detail/cstddef.hpp"
  21. #include "asio/detail/type_traits.hpp"
  22. #include "asio/detail/variadic_templates.hpp"
  23. #include "asio/detail/push_options.hpp"
  24. namespace asio {
  25. namespace detail {
  26. class cancellation_handler_base
  27. {
  28. public:
  29. virtual void call(cancellation_type_t) = 0;
  30. virtual std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT = 0;
  31. protected:
  32. ~cancellation_handler_base() {}
  33. };
  34. template <typename Handler>
  35. class cancellation_handler
  36. : public cancellation_handler_base
  37. {
  38. public:
  39. #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  40. template <typename... Args>
  41. cancellation_handler(std::size_t size, ASIO_MOVE_ARG(Args)... args)
  42. : handler_(ASIO_MOVE_CAST(Args)(args)...),
  43. size_(size)
  44. {
  45. }
  46. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  47. cancellation_handler(std::size_t size)
  48. : handler_(),
  49. size_(size)
  50. {
  51. }
  52. #define ASIO_PRIVATE_HANDLER_CTOR_DEF(n) \
  53. template <ASIO_VARIADIC_TPARAMS(n)> \
  54. cancellation_handler(std::size_t size, ASIO_VARIADIC_MOVE_PARAMS(n)) \
  55. : handler_(ASIO_VARIADIC_MOVE_ARGS(n)), \
  56. size_(size) \
  57. { \
  58. } \
  59. /**/
  60. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_CTOR_DEF)
  61. #undef ASIO_PRIVATE_HANDLER_CTOR_DEF
  62. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  63. void call(cancellation_type_t type)
  64. {
  65. handler_(type);
  66. }
  67. std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT
  68. {
  69. std::pair<void*, std::size_t> mem(this, size_);
  70. this->cancellation_handler::~cancellation_handler();
  71. return mem;
  72. }
  73. Handler& handler() ASIO_NOEXCEPT
  74. {
  75. return handler_;
  76. }
  77. private:
  78. ~cancellation_handler()
  79. {
  80. }
  81. Handler handler_;
  82. std::size_t size_;
  83. };
  84. } // namespace detail
  85. class cancellation_slot;
  86. /// A cancellation signal with a single slot.
  87. class cancellation_signal
  88. {
  89. public:
  90. ASIO_CONSTEXPR cancellation_signal()
  91. : handler_(0)
  92. {
  93. }
  94. ASIO_DECL ~cancellation_signal();
  95. /// Emits the signal and causes invocation of the slot's handler, if any.
  96. void emit(cancellation_type_t type)
  97. {
  98. if (handler_)
  99. handler_->call(type);
  100. }
  101. /// Returns the single slot associated with the signal.
  102. /**
  103. * The signal object must remain valid for as long the slot may be used.
  104. * Destruction of the signal invalidates the slot.
  105. */
  106. cancellation_slot slot() ASIO_NOEXCEPT;
  107. private:
  108. cancellation_signal(const cancellation_signal&) ASIO_DELETED;
  109. cancellation_signal& operator=(const cancellation_signal&) ASIO_DELETED;
  110. detail::cancellation_handler_base* handler_;
  111. };
  112. /// A slot associated with a cancellation signal.
  113. class cancellation_slot
  114. {
  115. public:
  116. /// Creates a slot that is not connected to any cancellation signal.
  117. ASIO_CONSTEXPR cancellation_slot()
  118. : handler_(0)
  119. {
  120. }
  121. #if defined(ASIO_HAS_VARIADIC_TEMPLATES) \
  122. || defined(GENERATING_DOCUMENTATION)
  123. /// Installs a handler into the slot, constructing the new object directly.
  124. /**
  125. * Destroys any existing handler in the slot, then installs the new handler,
  126. * constructing it with the supplied @c args.
  127. *
  128. * The handler is a function object to be called when the signal is emitted.
  129. * The signature of the handler must be
  130. * @code void handler(asio::cancellation_type_t); @endcode
  131. *
  132. * @param args Arguments to be passed to the @c CancellationHandler object's
  133. * constructor.
  134. *
  135. * @returns A reference to the newly installed handler.
  136. *
  137. * @note Handlers installed into the slot via @c emplace are not required to
  138. * be copy constructible or move constructible.
  139. */
  140. template <typename CancellationHandler, typename... Args>
  141. CancellationHandler& emplace(ASIO_MOVE_ARG(Args)... args)
  142. {
  143. typedef detail::cancellation_handler<CancellationHandler>
  144. cancellation_handler_type;
  145. auto_delete_helper del = { prepare_memory(
  146. sizeof(cancellation_handler_type),
  147. ASIO_ALIGNOF(CancellationHandler)) };
  148. cancellation_handler_type* handler_obj =
  149. new (del.mem.first) cancellation_handler_type(
  150. del.mem.second, ASIO_MOVE_CAST(Args)(args)...);
  151. del.mem.first = 0;
  152. *handler_ = handler_obj;
  153. return handler_obj->handler();
  154. }
  155. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  156. // || defined(GENERATING_DOCUMENTATION)
  157. template <typename CancellationHandler>
  158. CancellationHandler& emplace()
  159. {
  160. typedef detail::cancellation_handler<CancellationHandler>
  161. cancellation_handler_type;
  162. auto_delete_helper del = { prepare_memory(
  163. sizeof(cancellation_handler_type),
  164. ASIO_ALIGNOF(CancellationHandler)) };
  165. cancellation_handler_type* handler_obj =
  166. new (del.mem.first) cancellation_handler_type(del.mem.second);
  167. del.mem.first = 0;
  168. *handler_ = handler_obj;
  169. return handler_obj->handler();
  170. }
  171. #define ASIO_PRIVATE_HANDLER_EMPLACE_DEF(n) \
  172. template <typename CancellationHandler, ASIO_VARIADIC_TPARAMS(n)> \
  173. CancellationHandler& emplace(ASIO_VARIADIC_MOVE_PARAMS(n)) \
  174. { \
  175. typedef detail::cancellation_handler<CancellationHandler> \
  176. cancellation_handler_type; \
  177. auto_delete_helper del = { prepare_memory( \
  178. sizeof(cancellation_handler_type), \
  179. ASIO_ALIGNOF(CancellationHandler)) }; \
  180. cancellation_handler_type* handler_obj = \
  181. new (del.mem.first) cancellation_handler_type( \
  182. del.mem.second, ASIO_VARIADIC_MOVE_ARGS(n)); \
  183. del.mem.first = 0; \
  184. *handler_ = handler_obj; \
  185. return handler_obj->handler(); \
  186. } \
  187. /**/
  188. ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_EMPLACE_DEF)
  189. #undef ASIO_PRIVATE_HANDLER_EMPLACE_DEF
  190. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  191. /// Installs a handler into the slot.
  192. /**
  193. * Destroys any existing handler in the slot, then installs the new handler,
  194. * constructing it as a decay-copy of the supplied handler.
  195. *
  196. * The handler is a function object to be called when the signal is emitted.
  197. * The signature of the handler must be
  198. * @code void handler(asio::cancellation_type_t); @endcode
  199. *
  200. * @param handler The handler to be installed.
  201. *
  202. * @returns A reference to the newly installed handler.
  203. */
  204. template <typename CancellationHandler>
  205. typename decay<CancellationHandler>::type& assign(
  206. ASIO_MOVE_ARG(CancellationHandler) handler)
  207. {
  208. return this->emplace<typename decay<CancellationHandler>::type>(
  209. ASIO_MOVE_CAST(CancellationHandler)(handler));
  210. }
  211. /// Clears the slot.
  212. /**
  213. * Destroys any existing handler in the slot.
  214. */
  215. ASIO_DECL void clear();
  216. /// Returns whether the slot is connected to a signal.
  217. ASIO_CONSTEXPR bool is_connected() const ASIO_NOEXCEPT
  218. {
  219. return handler_ != 0;
  220. }
  221. /// Returns whether the slot is connected and has an installed handler.
  222. ASIO_CONSTEXPR bool has_handler() const ASIO_NOEXCEPT
  223. {
  224. return handler_ != 0 && *handler_ != 0;
  225. }
  226. /// Compare two slots for equality.
  227. friend ASIO_CONSTEXPR bool operator==(const cancellation_slot& lhs,
  228. const cancellation_slot& rhs) ASIO_NOEXCEPT
  229. {
  230. return lhs.handler_ == rhs.handler_;
  231. }
  232. /// Compare two slots for inequality.
  233. friend ASIO_CONSTEXPR bool operator!=(const cancellation_slot& lhs,
  234. const cancellation_slot& rhs) ASIO_NOEXCEPT
  235. {
  236. return lhs.handler_ != rhs.handler_;
  237. }
  238. private:
  239. friend class cancellation_signal;
  240. ASIO_CONSTEXPR cancellation_slot(int,
  241. detail::cancellation_handler_base** handler)
  242. : handler_(handler)
  243. {
  244. }
  245. ASIO_DECL std::pair<void*, std::size_t> prepare_memory(
  246. std::size_t size, std::size_t align);
  247. struct auto_delete_helper
  248. {
  249. std::pair<void*, std::size_t> mem;
  250. ASIO_DECL ~auto_delete_helper();
  251. };
  252. detail::cancellation_handler_base** handler_;
  253. };
  254. inline cancellation_slot cancellation_signal::slot() ASIO_NOEXCEPT
  255. {
  256. return cancellation_slot(0, &handler_);
  257. }
  258. } // namespace asio
  259. #include "asio/detail/pop_options.hpp"
  260. #if defined(ASIO_HEADER_ONLY)
  261. # include "asio/impl/cancellation_signal.ipp"
  262. #endif // defined(ASIO_HEADER_ONLY)
  263. #endif // ASIO_CANCELLATION_SIGNAL_HPP