1 | // |
2 | // associated_cancellation_slot.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_ASSOCIATED_CANCELLATION_SLOT_HPP |
12 | #define BOOST_ASIO_ASSOCIATED_CANCELLATION_SLOT_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 <boost/asio/associator.hpp> |
20 | #include <boost/asio/cancellation_signal.hpp> |
21 | #include <boost/asio/detail/functional.hpp> |
22 | #include <boost/asio/detail/type_traits.hpp> |
23 | |
24 | #include <boost/asio/detail/push_options.hpp> |
25 | |
26 | namespace boost { |
27 | namespace asio { |
28 | |
29 | template <typename T, typename CancellationSlot> |
30 | struct associated_cancellation_slot; |
31 | |
32 | namespace detail { |
33 | |
34 | template <typename T, typename = void> |
35 | struct has_cancellation_slot_type : false_type |
36 | { |
37 | }; |
38 | |
39 | template <typename T> |
40 | struct has_cancellation_slot_type<T, void_t<typename T::cancellation_slot_type>> |
41 | : true_type |
42 | { |
43 | }; |
44 | |
45 | template <typename T, typename S, typename = void, typename = void> |
46 | struct associated_cancellation_slot_impl |
47 | { |
48 | typedef void asio_associated_cancellation_slot_is_unspecialised; |
49 | |
50 | typedef S type; |
51 | |
52 | static type get(const T&) noexcept |
53 | { |
54 | return type(); |
55 | } |
56 | |
57 | static const type& get(const T&, const S& s) noexcept |
58 | { |
59 | return s; |
60 | } |
61 | }; |
62 | |
63 | template <typename T, typename S> |
64 | struct associated_cancellation_slot_impl<T, S, |
65 | void_t<typename T::cancellation_slot_type>> |
66 | { |
67 | typedef typename T::cancellation_slot_type type; |
68 | |
69 | static auto get(const T& t) noexcept |
70 | -> decltype(t.get_cancellation_slot()) |
71 | { |
72 | return t.get_cancellation_slot(); |
73 | } |
74 | |
75 | static auto get(const T& t, const S&) noexcept |
76 | -> decltype(t.get_cancellation_slot()) |
77 | { |
78 | return t.get_cancellation_slot(); |
79 | } |
80 | }; |
81 | |
82 | template <typename T, typename S> |
83 | struct associated_cancellation_slot_impl<T, S, |
84 | enable_if_t< |
85 | !has_cancellation_slot_type<T>::value |
86 | >, |
87 | void_t< |
88 | typename associator<associated_cancellation_slot, T, S>::type |
89 | >> : associator<associated_cancellation_slot, T, S> |
90 | { |
91 | }; |
92 | |
93 | } // namespace detail |
94 | |
95 | /// Traits type used to obtain the cancellation_slot associated with an object. |
96 | /** |
97 | * A program may specialise this traits type if the @c T template parameter in |
98 | * the specialisation is a user-defined type. The template parameter @c |
99 | * CancellationSlot shall be a type meeting the CancellationSlot requirements. |
100 | * |
101 | * Specialisations shall meet the following requirements, where @c t is a const |
102 | * reference to an object of type @c T, and @c s is an object of type @c |
103 | * CancellationSlot. |
104 | * |
105 | * @li Provide a nested typedef @c type that identifies a type meeting the |
106 | * CancellationSlot requirements. |
107 | * |
108 | * @li Provide a noexcept static member function named @c get, callable as @c |
109 | * get(t) and with return type @c type or a (possibly const) reference to @c |
110 | * type. |
111 | * |
112 | * @li Provide a noexcept static member function named @c get, callable as @c |
113 | * get(t,s) and with return type @c type or a (possibly const) reference to @c |
114 | * type. |
115 | */ |
116 | template <typename T, typename CancellationSlot = cancellation_slot> |
117 | struct associated_cancellation_slot |
118 | #if !defined(GENERATING_DOCUMENTATION) |
119 | : detail::associated_cancellation_slot_impl<T, CancellationSlot> |
120 | #endif // !defined(GENERATING_DOCUMENTATION) |
121 | { |
122 | #if defined(GENERATING_DOCUMENTATION) |
123 | /// If @c T has a nested type @c cancellation_slot_type, |
124 | /// <tt>T::cancellation_slot_type</tt>. Otherwise |
125 | /// @c CancellationSlot. |
126 | typedef see_below type; |
127 | |
128 | /// If @c T has a nested type @c cancellation_slot_type, returns |
129 | /// <tt>t.get_cancellation_slot()</tt>. Otherwise returns @c type(). |
130 | static decltype(auto) get(const T& t) noexcept; |
131 | |
132 | /// If @c T has a nested type @c cancellation_slot_type, returns |
133 | /// <tt>t.get_cancellation_slot()</tt>. Otherwise returns @c s. |
134 | static decltype(auto) get(const T& t, |
135 | const CancellationSlot& s) noexcept; |
136 | #endif // defined(GENERATING_DOCUMENTATION) |
137 | }; |
138 | |
139 | /// Helper function to obtain an object's associated cancellation_slot. |
140 | /** |
141 | * @returns <tt>associated_cancellation_slot<T>::get(t)</tt> |
142 | */ |
143 | template <typename T> |
144 | BOOST_ASIO_NODISCARD inline typename associated_cancellation_slot<T>::type |
145 | get_associated_cancellation_slot(const T& t) noexcept |
146 | { |
147 | return associated_cancellation_slot<T>::get(t); |
148 | } |
149 | |
150 | /// Helper function to obtain an object's associated cancellation_slot. |
151 | /** |
152 | * @returns <tt>associated_cancellation_slot<T, |
153 | * CancellationSlot>::get(t, st)</tt> |
154 | */ |
155 | template <typename T, typename CancellationSlot> |
156 | BOOST_ASIO_NODISCARD inline auto get_associated_cancellation_slot( |
157 | const T& t, const CancellationSlot& st) noexcept |
158 | -> decltype(associated_cancellation_slot<T, CancellationSlot>::get(t, st)) |
159 | { |
160 | return associated_cancellation_slot<T, CancellationSlot>::get(t, st); |
161 | } |
162 | |
163 | template <typename T, typename CancellationSlot = cancellation_slot> |
164 | using associated_cancellation_slot_t = |
165 | typename associated_cancellation_slot<T, CancellationSlot>::type; |
166 | |
167 | namespace detail { |
168 | |
169 | template <typename T, typename S, typename = void> |
170 | struct associated_cancellation_slot_forwarding_base |
171 | { |
172 | }; |
173 | |
174 | template <typename T, typename S> |
175 | struct associated_cancellation_slot_forwarding_base<T, S, |
176 | enable_if_t< |
177 | is_same< |
178 | typename associated_cancellation_slot<T, |
179 | S>::asio_associated_cancellation_slot_is_unspecialised, |
180 | void |
181 | >::value |
182 | >> |
183 | { |
184 | typedef void asio_associated_cancellation_slot_is_unspecialised; |
185 | }; |
186 | |
187 | } // namespace detail |
188 | |
189 | /// Specialisation of associated_cancellation_slot for @c |
190 | /// std::reference_wrapper. |
191 | template <typename T, typename CancellationSlot> |
192 | struct associated_cancellation_slot<reference_wrapper<T>, CancellationSlot> |
193 | #if !defined(GENERATING_DOCUMENTATION) |
194 | : detail::associated_cancellation_slot_forwarding_base<T, CancellationSlot> |
195 | #endif // !defined(GENERATING_DOCUMENTATION) |
196 | { |
197 | /// Forwards @c type to the associator specialisation for the unwrapped type |
198 | /// @c T. |
199 | typedef typename associated_cancellation_slot<T, CancellationSlot>::type type; |
200 | |
201 | /// Forwards the request to get the cancellation slot to the associator |
202 | /// specialisation for the unwrapped type @c T. |
203 | static type get(reference_wrapper<T> t) noexcept |
204 | { |
205 | return associated_cancellation_slot<T, CancellationSlot>::get(t.get()); |
206 | } |
207 | |
208 | /// Forwards the request to get the cancellation slot to the associator |
209 | /// specialisation for the unwrapped type @c T. |
210 | static auto get(reference_wrapper<T> t, const CancellationSlot& s) noexcept |
211 | -> decltype( |
212 | associated_cancellation_slot<T, CancellationSlot>::get(t.get(), s)) |
213 | { |
214 | return associated_cancellation_slot<T, CancellationSlot>::get(t.get(), s); |
215 | } |
216 | }; |
217 | |
218 | } // namespace asio |
219 | } // namespace boost |
220 | |
221 | #include <boost/asio/detail/pop_options.hpp> |
222 | |
223 | #endif // BOOST_ASIO_ASSOCIATED_CANCELLATION_SLOT_HPP |
224 | |