cancellation_signal.hpp 8.8 KB

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