cancellation_state.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. //
  2. // cancellation_state.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 ASIO_CANCELLATION_STATE_HPP
  11. #define ASIO_CANCELLATION_STATE_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_signal.hpp"
  20. #include "asio/detail/cstddef.hpp"
  21. #include "asio/detail/push_options.hpp"
  22. namespace asio {
  23. /// A simple cancellation signal propagation filter.
  24. template <cancellation_type_t Mask>
  25. struct cancellation_filter
  26. {
  27. /// Returns <tt>type & Mask</tt>.
  28. cancellation_type_t operator()(
  29. cancellation_type_t type) const noexcept
  30. {
  31. return type & Mask;
  32. }
  33. };
  34. /// A cancellation filter that disables cancellation.
  35. typedef cancellation_filter<cancellation_type::none>
  36. disable_cancellation;
  37. /// A cancellation filter that enables terminal cancellation only.
  38. typedef cancellation_filter<cancellation_type::terminal>
  39. enable_terminal_cancellation;
  40. #if defined(GENERATING_DOCUMENTATION)
  41. /// A cancellation filter that enables terminal and partial cancellation.
  42. typedef cancellation_filter<
  43. cancellation_type::terminal | cancellation_type::partial>
  44. enable_partial_cancellation;
  45. /// A cancellation filter that enables terminal, partial and total cancellation.
  46. typedef cancellation_filter<cancellation_type::terminal
  47. | cancellation_type::partial | cancellation_type::total>
  48. enable_total_cancellation;
  49. #else // defined(GENERATING_DOCUMENTATION)
  50. typedef cancellation_filter<
  51. static_cast<cancellation_type_t>(
  52. static_cast<unsigned int>(cancellation_type::terminal)
  53. | static_cast<unsigned int>(cancellation_type::partial))>
  54. enable_partial_cancellation;
  55. typedef cancellation_filter<
  56. static_cast<cancellation_type_t>(
  57. static_cast<unsigned int>(cancellation_type::terminal)
  58. | static_cast<unsigned int>(cancellation_type::partial)
  59. | static_cast<unsigned int>(cancellation_type::total))>
  60. enable_total_cancellation;
  61. #endif // defined(GENERATING_DOCUMENTATION)
  62. /// A cancellation state is used for chaining signals and slots in compositions.
  63. class cancellation_state
  64. {
  65. public:
  66. /// Construct a disconnected cancellation state.
  67. constexpr cancellation_state() noexcept
  68. : impl_(0)
  69. {
  70. }
  71. /// Construct and attach to a parent slot to create a new child slot.
  72. /**
  73. * Initialises the cancellation state so that it allows terminal cancellation
  74. * only. Equivalent to <tt>cancellation_state(slot,
  75. * enable_terminal_cancellation())</tt>.
  76. *
  77. * @param slot The parent cancellation slot to which the state will be
  78. * attached.
  79. */
  80. template <typename CancellationSlot>
  81. constexpr explicit cancellation_state(CancellationSlot slot)
  82. : impl_(slot.is_connected() ? &slot.template emplace<impl<>>() : 0)
  83. {
  84. }
  85. /// Construct and attach to a parent slot to create a new child slot.
  86. /**
  87. * @param slot The parent cancellation slot to which the state will be
  88. * attached.
  89. *
  90. * @param filter A function object that is used to transform incoming
  91. * cancellation signals as they are received from the parent slot. This
  92. * function object must have the signature:
  93. * @code asio::cancellation_type_t filter(
  94. * asio::cancellation_type_t); @endcode
  95. *
  96. * The library provides the following pre-defined cancellation filters:
  97. *
  98. * @li asio::disable_cancellation
  99. * @li asio::enable_terminal_cancellation
  100. * @li asio::enable_partial_cancellation
  101. * @li asio::enable_total_cancellation
  102. */
  103. template <typename CancellationSlot, typename Filter>
  104. constexpr cancellation_state(CancellationSlot slot, Filter filter)
  105. : impl_(slot.is_connected()
  106. ? &slot.template emplace<impl<Filter, Filter>>(filter, filter)
  107. : 0)
  108. {
  109. }
  110. /// Construct and attach to a parent slot to create a new child slot.
  111. /**
  112. * @param slot The parent cancellation slot to which the state will be
  113. * attached.
  114. *
  115. * @param in_filter A function object that is used to transform incoming
  116. * cancellation signals as they are received from the parent slot. This
  117. * function object must have the signature:
  118. * @code asio::cancellation_type_t in_filter(
  119. * asio::cancellation_type_t); @endcode
  120. *
  121. * @param out_filter A function object that is used to transform outcoming
  122. * cancellation signals as they are relayed to the child slot. This function
  123. * object must have the signature:
  124. * @code asio::cancellation_type_t out_filter(
  125. * asio::cancellation_type_t); @endcode
  126. *
  127. * The library provides the following pre-defined cancellation filters:
  128. *
  129. * @li asio::disable_cancellation
  130. * @li asio::enable_terminal_cancellation
  131. * @li asio::enable_partial_cancellation
  132. * @li asio::enable_total_cancellation
  133. */
  134. template <typename CancellationSlot, typename InFilter, typename OutFilter>
  135. constexpr cancellation_state(CancellationSlot slot,
  136. InFilter in_filter, OutFilter out_filter)
  137. : impl_(slot.is_connected()
  138. ? &slot.template emplace<impl<InFilter, OutFilter>>(
  139. static_cast<InFilter&&>(in_filter),
  140. static_cast<OutFilter&&>(out_filter))
  141. : 0)
  142. {
  143. }
  144. /// Returns the single child slot associated with the state.
  145. /**
  146. * This sub-slot is used with the operations that are being composed.
  147. */
  148. constexpr cancellation_slot slot() const noexcept
  149. {
  150. return impl_ ? impl_->signal_.slot() : cancellation_slot();
  151. }
  152. /// Returns the cancellation types that have been triggered.
  153. cancellation_type_t cancelled() const noexcept
  154. {
  155. return impl_ ? impl_->cancelled_ : cancellation_type_t();
  156. }
  157. /// Clears the specified cancellation types, if they have been triggered.
  158. void clear(cancellation_type_t mask = cancellation_type::all)
  159. noexcept
  160. {
  161. if (impl_)
  162. impl_->cancelled_ &= ~mask;
  163. }
  164. private:
  165. struct impl_base
  166. {
  167. impl_base()
  168. : cancelled_()
  169. {
  170. }
  171. cancellation_signal signal_;
  172. cancellation_type_t cancelled_;
  173. };
  174. template <
  175. typename InFilter = enable_terminal_cancellation,
  176. typename OutFilter = InFilter>
  177. struct impl : impl_base
  178. {
  179. impl()
  180. : in_filter_(),
  181. out_filter_()
  182. {
  183. }
  184. impl(InFilter in_filter, OutFilter out_filter)
  185. : in_filter_(static_cast<InFilter&&>(in_filter)),
  186. out_filter_(static_cast<OutFilter&&>(out_filter))
  187. {
  188. }
  189. void operator()(cancellation_type_t in)
  190. {
  191. this->cancelled_ = in_filter_(in);
  192. cancellation_type_t out = out_filter_(this->cancelled_);
  193. if (out != cancellation_type::none)
  194. this->signal_.emit(out);
  195. }
  196. InFilter in_filter_;
  197. OutFilter out_filter_;
  198. };
  199. impl_base* impl_;
  200. };
  201. } // namespace asio
  202. #include "asio/detail/pop_options.hpp"
  203. #endif // ASIO_CANCELLATION_STATE_HPP