1//
2// bind_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_BIND_CANCELLATION_SLOT_HPP
12#define BOOST_ASIO_BIND_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/detail/type_traits.hpp>
20#include <boost/asio/associated_cancellation_slot.hpp>
21#include <boost/asio/associator.hpp>
22#include <boost/asio/async_result.hpp>
23
24#include <boost/asio/detail/push_options.hpp>
25
26namespace boost {
27namespace asio {
28namespace detail {
29
30// Helper to automatically define nested typedef result_type.
31
32template <typename T, typename = void>
33struct cancellation_slot_binder_result_type
34{
35protected:
36 typedef void result_type_or_void;
37};
38
39template <typename T>
40struct cancellation_slot_binder_result_type<T, void_t<typename T::result_type>>
41{
42 typedef typename T::result_type result_type;
43protected:
44 typedef result_type result_type_or_void;
45};
46
47template <typename R>
48struct cancellation_slot_binder_result_type<R(*)()>
49{
50 typedef R result_type;
51protected:
52 typedef result_type result_type_or_void;
53};
54
55template <typename R>
56struct cancellation_slot_binder_result_type<R(&)()>
57{
58 typedef R result_type;
59protected:
60 typedef result_type result_type_or_void;
61};
62
63template <typename R, typename A1>
64struct cancellation_slot_binder_result_type<R(*)(A1)>
65{
66 typedef R result_type;
67protected:
68 typedef result_type result_type_or_void;
69};
70
71template <typename R, typename A1>
72struct cancellation_slot_binder_result_type<R(&)(A1)>
73{
74 typedef R result_type;
75protected:
76 typedef result_type result_type_or_void;
77};
78
79template <typename R, typename A1, typename A2>
80struct cancellation_slot_binder_result_type<R(*)(A1, A2)>
81{
82 typedef R result_type;
83protected:
84 typedef result_type result_type_or_void;
85};
86
87template <typename R, typename A1, typename A2>
88struct cancellation_slot_binder_result_type<R(&)(A1, A2)>
89{
90 typedef R result_type;
91protected:
92 typedef result_type result_type_or_void;
93};
94
95// Helper to automatically define nested typedef argument_type.
96
97template <typename T, typename = void>
98struct cancellation_slot_binder_argument_type {};
99
100template <typename T>
101struct cancellation_slot_binder_argument_type<T,
102 void_t<typename T::argument_type>>
103{
104 typedef typename T::argument_type argument_type;
105};
106
107template <typename R, typename A1>
108struct cancellation_slot_binder_argument_type<R(*)(A1)>
109{
110 typedef A1 argument_type;
111};
112
113template <typename R, typename A1>
114struct cancellation_slot_binder_argument_type<R(&)(A1)>
115{
116 typedef A1 argument_type;
117};
118
119// Helper to automatically define nested typedefs first_argument_type and
120// second_argument_type.
121
122template <typename T, typename = void>
123struct cancellation_slot_binder_argument_types {};
124
125template <typename T>
126struct cancellation_slot_binder_argument_types<T,
127 void_t<typename T::first_argument_type>>
128{
129 typedef typename T::first_argument_type first_argument_type;
130 typedef typename T::second_argument_type second_argument_type;
131};
132
133template <typename R, typename A1, typename A2>
134struct cancellation_slot_binder_argument_type<R(*)(A1, A2)>
135{
136 typedef A1 first_argument_type;
137 typedef A2 second_argument_type;
138};
139
140template <typename R, typename A1, typename A2>
141struct cancellation_slot_binder_argument_type<R(&)(A1, A2)>
142{
143 typedef A1 first_argument_type;
144 typedef A2 second_argument_type;
145};
146
147} // namespace detail
148
149/// A call wrapper type to bind a cancellation slot of type @c CancellationSlot
150/// to an object of type @c T.
151template <typename T, typename CancellationSlot>
152class cancellation_slot_binder
153#if !defined(GENERATING_DOCUMENTATION)
154 : public detail::cancellation_slot_binder_result_type<T>,
155 public detail::cancellation_slot_binder_argument_type<T>,
156 public detail::cancellation_slot_binder_argument_types<T>
157#endif // !defined(GENERATING_DOCUMENTATION)
158{
159public:
160 /// The type of the target object.
161 typedef T target_type;
162
163 /// The type of the associated cancellation slot.
164 typedef CancellationSlot cancellation_slot_type;
165
166#if defined(GENERATING_DOCUMENTATION)
167 /// The return type if a function.
168 /**
169 * The type of @c result_type is based on the type @c T of the wrapper's
170 * target object:
171 *
172 * @li if @c T is a pointer to function type, @c result_type is a synonym for
173 * the return type of @c T;
174 *
175 * @li if @c T is a class type with a member type @c result_type, then @c
176 * result_type is a synonym for @c T::result_type;
177 *
178 * @li otherwise @c result_type is not defined.
179 */
180 typedef see_below result_type;
181
182 /// The type of the function's argument.
183 /**
184 * The type of @c argument_type is based on the type @c T of the wrapper's
185 * target object:
186 *
187 * @li if @c T is a pointer to a function type accepting a single argument,
188 * @c argument_type is a synonym for the return type of @c T;
189 *
190 * @li if @c T is a class type with a member type @c argument_type, then @c
191 * argument_type is a synonym for @c T::argument_type;
192 *
193 * @li otherwise @c argument_type is not defined.
194 */
195 typedef see_below argument_type;
196
197 /// The type of the function's first argument.
198 /**
199 * The type of @c first_argument_type is based on the type @c T of the
200 * wrapper's target object:
201 *
202 * @li if @c T is a pointer to a function type accepting two arguments, @c
203 * first_argument_type is a synonym for the return type of @c T;
204 *
205 * @li if @c T is a class type with a member type @c first_argument_type,
206 * then @c first_argument_type is a synonym for @c T::first_argument_type;
207 *
208 * @li otherwise @c first_argument_type is not defined.
209 */
210 typedef see_below first_argument_type;
211
212 /// The type of the function's second argument.
213 /**
214 * The type of @c second_argument_type is based on the type @c T of the
215 * wrapper's target object:
216 *
217 * @li if @c T is a pointer to a function type accepting two arguments, @c
218 * second_argument_type is a synonym for the return type of @c T;
219 *
220 * @li if @c T is a class type with a member type @c first_argument_type,
221 * then @c second_argument_type is a synonym for @c T::second_argument_type;
222 *
223 * @li otherwise @c second_argument_type is not defined.
224 */
225 typedef see_below second_argument_type;
226#endif // defined(GENERATING_DOCUMENTATION)
227
228 /// Construct a cancellation slot wrapper for the specified object.
229 /**
230 * This constructor is only valid if the type @c T is constructible from type
231 * @c U.
232 */
233 template <typename U>
234 cancellation_slot_binder(const cancellation_slot_type& s, U&& u)
235 : slot_(s),
236 target_(static_cast<U&&>(u))
237 {
238 }
239
240 /// Copy constructor.
241 cancellation_slot_binder(const cancellation_slot_binder& other)
242 : slot_(other.get_cancellation_slot()),
243 target_(other.get())
244 {
245 }
246
247 /// Construct a copy, but specify a different cancellation slot.
248 cancellation_slot_binder(const cancellation_slot_type& s,
249 const cancellation_slot_binder& other)
250 : slot_(s),
251 target_(other.get())
252 {
253 }
254
255 /// Construct a copy of a different cancellation slot wrapper type.
256 /**
257 * This constructor is only valid if the @c CancellationSlot type is
258 * constructible from type @c OtherCancellationSlot, and the type @c T is
259 * constructible from type @c U.
260 */
261 template <typename U, typename OtherCancellationSlot>
262 cancellation_slot_binder(
263 const cancellation_slot_binder<U, OtherCancellationSlot>& other,
264 constraint_t<is_constructible<CancellationSlot,
265 OtherCancellationSlot>::value> = 0,
266 constraint_t<is_constructible<T, U>::value> = 0)
267 : slot_(other.get_cancellation_slot()),
268 target_(other.get())
269 {
270 }
271
272 /// Construct a copy of a different cancellation slot wrapper type, but
273 /// specify a different cancellation slot.
274 /**
275 * This constructor is only valid if the type @c T is constructible from type
276 * @c U.
277 */
278 template <typename U, typename OtherCancellationSlot>
279 cancellation_slot_binder(const cancellation_slot_type& s,
280 const cancellation_slot_binder<U, OtherCancellationSlot>& other,
281 constraint_t<is_constructible<T, U>::value> = 0)
282 : slot_(s),
283 target_(other.get())
284 {
285 }
286
287 /// Move constructor.
288 cancellation_slot_binder(cancellation_slot_binder&& other)
289 : slot_(static_cast<cancellation_slot_type&&>(
290 other.get_cancellation_slot())),
291 target_(static_cast<T&&>(other.get()))
292 {
293 }
294
295 /// Move construct the target object, but specify a different cancellation
296 /// slot.
297 cancellation_slot_binder(const cancellation_slot_type& s,
298 cancellation_slot_binder&& other)
299 : slot_(s),
300 target_(static_cast<T&&>(other.get()))
301 {
302 }
303
304 /// Move construct from a different cancellation slot wrapper type.
305 template <typename U, typename OtherCancellationSlot>
306 cancellation_slot_binder(
307 cancellation_slot_binder<U, OtherCancellationSlot>&& other,
308 constraint_t<is_constructible<CancellationSlot,
309 OtherCancellationSlot>::value> = 0,
310 constraint_t<is_constructible<T, U>::value> = 0)
311 : slot_(static_cast<OtherCancellationSlot&&>(
312 other.get_cancellation_slot())),
313 target_(static_cast<U&&>(other.get()))
314 {
315 }
316
317 /// Move construct from a different cancellation slot wrapper type, but
318 /// specify a different cancellation slot.
319 template <typename U, typename OtherCancellationSlot>
320 cancellation_slot_binder(const cancellation_slot_type& s,
321 cancellation_slot_binder<U, OtherCancellationSlot>&& other,
322 constraint_t<is_constructible<T, U>::value> = 0)
323 : slot_(s),
324 target_(static_cast<U&&>(other.get()))
325 {
326 }
327
328 /// Destructor.
329 ~cancellation_slot_binder()
330 {
331 }
332
333 /// Obtain a reference to the target object.
334 target_type& get() noexcept
335 {
336 return target_;
337 }
338
339 /// Obtain a reference to the target object.
340 const target_type& get() const noexcept
341 {
342 return target_;
343 }
344
345 /// Obtain the associated cancellation slot.
346 cancellation_slot_type get_cancellation_slot() const noexcept
347 {
348 return slot_;
349 }
350
351 /// Forwarding function call operator.
352 template <typename... Args>
353 result_of_t<T(Args...)> operator()(Args&&... args)
354 {
355 return target_(static_cast<Args&&>(args)...);
356 }
357
358 /// Forwarding function call operator.
359 template <typename... Args>
360 result_of_t<T(Args...)> operator()(Args&&... args) const
361 {
362 return target_(static_cast<Args&&>(args)...);
363 }
364
365private:
366 CancellationSlot slot_;
367 T target_;
368};
369
370/// Associate an object of type @c T with a cancellation slot of type
371/// @c CancellationSlot.
372template <typename CancellationSlot, typename T>
373BOOST_ASIO_NODISCARD inline
374cancellation_slot_binder<decay_t<T>, CancellationSlot>
375bind_cancellation_slot(const CancellationSlot& s, T&& t)
376{
377 return cancellation_slot_binder<decay_t<T>, CancellationSlot>(
378 s, static_cast<T&&>(t));
379}
380
381#if !defined(GENERATING_DOCUMENTATION)
382
383namespace detail {
384
385template <typename TargetAsyncResult,
386 typename CancellationSlot, typename = void>
387class cancellation_slot_binder_completion_handler_async_result
388{
389public:
390 template <typename T>
391 explicit cancellation_slot_binder_completion_handler_async_result(T&)
392 {
393 }
394};
395
396template <typename TargetAsyncResult, typename CancellationSlot>
397class cancellation_slot_binder_completion_handler_async_result<
398 TargetAsyncResult, CancellationSlot,
399 void_t<typename TargetAsyncResult::completion_handler_type>>
400{
401private:
402 TargetAsyncResult target_;
403
404public:
405 typedef cancellation_slot_binder<
406 typename TargetAsyncResult::completion_handler_type, CancellationSlot>
407 completion_handler_type;
408
409 explicit cancellation_slot_binder_completion_handler_async_result(
410 typename TargetAsyncResult::completion_handler_type& handler)
411 : target_(handler)
412 {
413 }
414
415 auto get() -> decltype(target_.get())
416 {
417 return target_.get();
418 }
419};
420
421template <typename TargetAsyncResult, typename = void>
422struct cancellation_slot_binder_async_result_return_type
423{
424};
425
426template <typename TargetAsyncResult>
427struct cancellation_slot_binder_async_result_return_type<
428 TargetAsyncResult, void_t<typename TargetAsyncResult::return_type>>
429{
430 typedef typename TargetAsyncResult::return_type return_type;
431};
432
433} // namespace detail
434
435template <typename T, typename CancellationSlot, typename Signature>
436class async_result<cancellation_slot_binder<T, CancellationSlot>, Signature> :
437 public detail::cancellation_slot_binder_completion_handler_async_result<
438 async_result<T, Signature>, CancellationSlot>,
439 public detail::cancellation_slot_binder_async_result_return_type<
440 async_result<T, Signature>>
441{
442public:
443 explicit async_result(cancellation_slot_binder<T, CancellationSlot>& b)
444 : detail::cancellation_slot_binder_completion_handler_async_result<
445 async_result<T, Signature>, CancellationSlot>(b.get())
446 {
447 }
448
449 template <typename Initiation>
450 struct init_wrapper
451 {
452 template <typename Init>
453 init_wrapper(const CancellationSlot& slot, Init&& init)
454 : slot_(slot),
455 initiation_(static_cast<Init&&>(init))
456 {
457 }
458
459 template <typename Handler, typename... Args>
460 void operator()(Handler&& handler, Args&&... args)
461 {
462 static_cast<Initiation&&>(initiation_)(
463 cancellation_slot_binder<decay_t<Handler>, CancellationSlot>(
464 slot_, static_cast<Handler&&>(handler)),
465 static_cast<Args&&>(args)...);
466 }
467
468 template <typename Handler, typename... Args>
469 void operator()(Handler&& handler, Args&&... args) const
470 {
471 initiation_(
472 cancellation_slot_binder<decay_t<Handler>, CancellationSlot>(
473 slot_, static_cast<Handler&&>(handler)),
474 static_cast<Args&&>(args)...);
475 }
476
477 CancellationSlot slot_;
478 Initiation initiation_;
479 };
480
481 template <typename Initiation, typename RawCompletionToken, typename... Args>
482 static auto initiate(Initiation&& initiation,
483 RawCompletionToken&& token, Args&&... args)
484 -> decltype(
485 async_initiate<T, Signature>(
486 declval<init_wrapper<decay_t<Initiation>>>(),
487 token.get(), static_cast<Args&&>(args)...))
488 {
489 return async_initiate<T, Signature>(
490 init_wrapper<decay_t<Initiation>>(
491 token.get_cancellation_slot(),
492 static_cast<Initiation&&>(initiation)),
493 token.get(), static_cast<Args&&>(args)...);
494 }
495
496private:
497 async_result(const async_result&) = delete;
498 async_result& operator=(const async_result&) = delete;
499
500 async_result<T, Signature> target_;
501};
502
503template <template <typename, typename> class Associator,
504 typename T, typename CancellationSlot, typename DefaultCandidate>
505struct associator<Associator,
506 cancellation_slot_binder<T, CancellationSlot>,
507 DefaultCandidate>
508 : Associator<T, DefaultCandidate>
509{
510 static typename Associator<T, DefaultCandidate>::type get(
511 const cancellation_slot_binder<T, CancellationSlot>& b) noexcept
512 {
513 return Associator<T, DefaultCandidate>::get(b.get());
514 }
515
516 static auto get(const cancellation_slot_binder<T, CancellationSlot>& b,
517 const DefaultCandidate& c) noexcept
518 -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c))
519 {
520 return Associator<T, DefaultCandidate>::get(b.get(), c);
521 }
522};
523
524template <typename T, typename CancellationSlot, typename CancellationSlot1>
525struct associated_cancellation_slot<
526 cancellation_slot_binder<T, CancellationSlot>,
527 CancellationSlot1>
528{
529 typedef CancellationSlot type;
530
531 static auto get(const cancellation_slot_binder<T, CancellationSlot>& b,
532 const CancellationSlot1& = CancellationSlot1()) noexcept
533 -> decltype(b.get_cancellation_slot())
534 {
535 return b.get_cancellation_slot();
536 }
537};
538
539#endif // !defined(GENERATING_DOCUMENTATION)
540
541} // namespace asio
542} // namespace boost
543
544#include <boost/asio/detail/pop_options.hpp>
545
546#endif // BOOST_ASIO_BIND_CANCELLATION_SLOT_HPP
547

source code of boost/libs/asio/include/boost/asio/bind_cancellation_slot.hpp