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