cancellation_state.hpp 7.1 KB

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