2 // bind_cancellation_slot.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_BIND_CANCELLATION_SLOT_HPP
12 #define BOOST_ASIO_BIND_CANCELLATION_SLOT_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
19 #include <boost/asio/detail/type_traits.hpp>
20 #include <boost/asio/detail/variadic_templates.hpp>
21 #include <boost/asio/associated_cancellation_slot.hpp>
22 #include <boost/asio/associator.hpp>
23 #include <boost/asio/async_result.hpp>
25 #include <boost/asio/detail/push_options.hpp>
31 // Helper to automatically define nested typedef result_type.
33 template <typename T, typename = void>
34 struct cancellation_slot_binder_result_type
37 typedef void result_type_or_void;
41 struct cancellation_slot_binder_result_type<T,
42 typename void_type<typename T::result_type>::type>
44 typedef typename T::result_type result_type;
46 typedef result_type result_type_or_void;
50 struct cancellation_slot_binder_result_type<R(*)()>
52 typedef R result_type;
54 typedef result_type result_type_or_void;
58 struct cancellation_slot_binder_result_type<R(&)()>
60 typedef R result_type;
62 typedef result_type result_type_or_void;
65 template <typename R, typename A1>
66 struct cancellation_slot_binder_result_type<R(*)(A1)>
68 typedef R result_type;
70 typedef result_type result_type_or_void;
73 template <typename R, typename A1>
74 struct cancellation_slot_binder_result_type<R(&)(A1)>
76 typedef R result_type;
78 typedef result_type result_type_or_void;
81 template <typename R, typename A1, typename A2>
82 struct cancellation_slot_binder_result_type<R(*)(A1, A2)>
84 typedef R result_type;
86 typedef result_type result_type_or_void;
89 template <typename R, typename A1, typename A2>
90 struct cancellation_slot_binder_result_type<R(&)(A1, A2)>
92 typedef R result_type;
94 typedef result_type result_type_or_void;
97 // Helper to automatically define nested typedef argument_type.
99 template <typename T, typename = void>
100 struct cancellation_slot_binder_argument_type {};
102 template <typename T>
103 struct cancellation_slot_binder_argument_type<T,
104 typename void_type<typename T::argument_type>::type>
106 typedef typename T::argument_type argument_type;
109 template <typename R, typename A1>
110 struct cancellation_slot_binder_argument_type<R(*)(A1)>
112 typedef A1 argument_type;
115 template <typename R, typename A1>
116 struct cancellation_slot_binder_argument_type<R(&)(A1)>
118 typedef A1 argument_type;
121 // Helper to automatically define nested typedefs first_argument_type and
122 // second_argument_type.
124 template <typename T, typename = void>
125 struct cancellation_slot_binder_argument_types {};
127 template <typename T>
128 struct cancellation_slot_binder_argument_types<T,
129 typename void_type<typename T::first_argument_type>::type>
131 typedef typename T::first_argument_type first_argument_type;
132 typedef typename T::second_argument_type second_argument_type;
135 template <typename R, typename A1, typename A2>
136 struct cancellation_slot_binder_argument_type<R(*)(A1, A2)>
138 typedef A1 first_argument_type;
139 typedef A2 second_argument_type;
142 template <typename R, typename A1, typename A2>
143 struct cancellation_slot_binder_argument_type<R(&)(A1, A2)>
145 typedef A1 first_argument_type;
146 typedef A2 second_argument_type;
149 // Helper to enable SFINAE on zero-argument operator() below.
151 template <typename T, typename = void>
152 struct cancellation_slot_binder_result_of0
157 template <typename T>
158 struct cancellation_slot_binder_result_of0<T,
159 typename void_type<typename result_of<T()>::type>::type>
161 typedef typename result_of<T()>::type type;
164 } // namespace detail
166 /// A call wrapper type to bind a cancellation slot of type @c CancellationSlot
167 /// to an object of type @c T.
168 template <typename T, typename CancellationSlot>
169 class cancellation_slot_binder
170 #if !defined(GENERATING_DOCUMENTATION)
171 : public detail::cancellation_slot_binder_result_type<T>,
172 public detail::cancellation_slot_binder_argument_type<T>,
173 public detail::cancellation_slot_binder_argument_types<T>
174 #endif // !defined(GENERATING_DOCUMENTATION)
177 /// The type of the target object.
178 typedef T target_type;
180 /// The type of the associated cancellation slot.
181 typedef CancellationSlot cancellation_slot_type;
183 #if defined(GENERATING_DOCUMENTATION)
184 /// The return type if a function.
186 * The type of @c result_type is based on the type @c T of the wrapper's
189 * @li if @c T is a pointer to function type, @c result_type is a synonym for
190 * the return type of @c T;
192 * @li if @c T is a class type with a member type @c result_type, then @c
193 * result_type is a synonym for @c T::result_type;
195 * @li otherwise @c result_type is not defined.
197 typedef see_below result_type;
199 /// The type of the function's argument.
201 * The type of @c argument_type is based on the type @c T of the wrapper's
204 * @li if @c T is a pointer to a function type accepting a single argument,
205 * @c argument_type is a synonym for the return type of @c T;
207 * @li if @c T is a class type with a member type @c argument_type, then @c
208 * argument_type is a synonym for @c T::argument_type;
210 * @li otherwise @c argument_type is not defined.
212 typedef see_below argument_type;
214 /// The type of the function's first argument.
216 * The type of @c first_argument_type is based on the type @c T of the
217 * wrapper's target object:
219 * @li if @c T is a pointer to a function type accepting two arguments, @c
220 * first_argument_type is a synonym for the return type of @c T;
222 * @li if @c T is a class type with a member type @c first_argument_type,
223 * then @c first_argument_type is a synonym for @c T::first_argument_type;
225 * @li otherwise @c first_argument_type is not defined.
227 typedef see_below first_argument_type;
229 /// The type of the function's second argument.
231 * The type of @c second_argument_type is based on the type @c T of the
232 * wrapper's target object:
234 * @li if @c T is a pointer to a function type accepting two arguments, @c
235 * second_argument_type is a synonym for the return type of @c T;
237 * @li if @c T is a class type with a member type @c first_argument_type,
238 * then @c second_argument_type is a synonym for @c T::second_argument_type;
240 * @li otherwise @c second_argument_type is not defined.
242 typedef see_below second_argument_type;
243 #endif // defined(GENERATING_DOCUMENTATION)
245 /// Construct a cancellation slot wrapper for the specified object.
247 * This constructor is only valid if the type @c T is constructible from type
250 template <typename U>
251 cancellation_slot_binder(const cancellation_slot_type& s,
252 BOOST_ASIO_MOVE_ARG(U) u)
254 target_(BOOST_ASIO_MOVE_CAST(U)(u))
258 /// Copy constructor.
259 cancellation_slot_binder(const cancellation_slot_binder& other)
260 : slot_(other.get_cancellation_slot()),
265 /// Construct a copy, but specify a different cancellation slot.
266 cancellation_slot_binder(const cancellation_slot_type& s,
267 const cancellation_slot_binder& other)
273 /// Construct a copy of a different cancellation slot wrapper type.
275 * This constructor is only valid if the @c CancellationSlot type is
276 * constructible from type @c OtherCancellationSlot, and the type @c T is
277 * constructible from type @c U.
279 template <typename U, typename OtherCancellationSlot>
280 cancellation_slot_binder(
281 const cancellation_slot_binder<U, OtherCancellationSlot>& other)
282 : slot_(other.get_cancellation_slot()),
287 /// Construct a copy of a different cancellation slot wrapper type, but
288 /// specify a different cancellation slot.
290 * This constructor is only valid if the type @c T is constructible from type
293 template <typename U, typename OtherCancellationSlot>
294 cancellation_slot_binder(const cancellation_slot_type& s,
295 const cancellation_slot_binder<U, OtherCancellationSlot>& other)
301 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
303 /// Move constructor.
304 cancellation_slot_binder(cancellation_slot_binder&& other)
305 : slot_(BOOST_ASIO_MOVE_CAST(cancellation_slot_type)(
306 other.get_cancellation_slot())),
307 target_(BOOST_ASIO_MOVE_CAST(T)(other.get()))
311 /// Move construct the target object, but specify a different cancellation
313 cancellation_slot_binder(const cancellation_slot_type& s,
314 cancellation_slot_binder&& other)
316 target_(BOOST_ASIO_MOVE_CAST(T)(other.get()))
320 /// Move construct from a different cancellation slot wrapper type.
321 template <typename U, typename OtherCancellationSlot>
322 cancellation_slot_binder(
323 cancellation_slot_binder<U, OtherCancellationSlot>&& other)
324 : slot_(BOOST_ASIO_MOVE_CAST(OtherCancellationSlot)(
325 other.get_cancellation_slot())),
326 target_(BOOST_ASIO_MOVE_CAST(U)(other.get()))
330 /// Move construct from a different cancellation slot wrapper type, but
331 /// specify a different cancellation slot.
332 template <typename U, typename OtherCancellationSlot>
333 cancellation_slot_binder(const cancellation_slot_type& s,
334 cancellation_slot_binder<U, OtherCancellationSlot>&& other)
336 target_(BOOST_ASIO_MOVE_CAST(U)(other.get()))
340 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
343 ~cancellation_slot_binder()
347 /// Obtain a reference to the target object.
348 target_type& get() BOOST_ASIO_NOEXCEPT
353 /// Obtain a reference to the target object.
354 const target_type& get() const BOOST_ASIO_NOEXCEPT
359 /// Obtain the associated cancellation slot.
360 cancellation_slot_type get_cancellation_slot() const BOOST_ASIO_NOEXCEPT
365 #if defined(GENERATING_DOCUMENTATION)
367 template <typename... Args> auto operator()(Args&& ...);
368 template <typename... Args> auto operator()(Args&& ...) const;
370 #elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
372 /// Forwarding function call operator.
373 template <typename... Args>
374 typename result_of<T(Args...)>::type operator()(
375 BOOST_ASIO_MOVE_ARG(Args)... args)
377 return target_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
380 /// Forwarding function call operator.
381 template <typename... Args>
382 typename result_of<T(Args...)>::type operator()(
383 BOOST_ASIO_MOVE_ARG(Args)... args) const
385 return target_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
388 #elif defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
390 typename detail::cancellation_slot_binder_result_of0<T>::type operator()()
395 typename detail::cancellation_slot_binder_result_of0<T>::type
401 #define BOOST_ASIO_PRIVATE_BINDER_CALL_DEF(n) \
402 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
403 typename result_of<T(BOOST_ASIO_VARIADIC_TARGS(n))>::type operator()( \
404 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
406 return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
409 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
410 typename result_of<T(BOOST_ASIO_VARIADIC_TARGS(n))>::type operator()( \
411 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
413 return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
416 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_BINDER_CALL_DEF)
417 #undef BOOST_ASIO_PRIVATE_BINDER_CALL_DEF
419 #else // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
421 typedef typename detail::cancellation_slot_binder_result_type<
422 T>::result_type_or_void result_type_or_void;
424 result_type_or_void operator()()
429 result_type_or_void operator()() const
434 #define BOOST_ASIO_PRIVATE_BINDER_CALL_DEF(n) \
435 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
436 result_type_or_void operator()( \
437 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
439 return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
442 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
443 result_type_or_void operator()( \
444 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
446 return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
449 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_BINDER_CALL_DEF)
450 #undef BOOST_ASIO_PRIVATE_BINDER_CALL_DEF
452 #endif // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
455 CancellationSlot slot_;
459 /// Associate an object of type @c T with a cancellation slot of type
460 /// @c CancellationSlot.
461 template <typename CancellationSlot, typename T>
462 BOOST_ASIO_NODISCARD inline
463 cancellation_slot_binder<typename decay<T>::type, CancellationSlot>
464 bind_cancellation_slot(const CancellationSlot& s, BOOST_ASIO_MOVE_ARG(T) t)
466 return cancellation_slot_binder<
467 typename decay<T>::type, CancellationSlot>(
468 s, BOOST_ASIO_MOVE_CAST(T)(t));
471 #if !defined(GENERATING_DOCUMENTATION)
475 template <typename TargetAsyncResult,
476 typename CancellationSlot, typename = void>
477 struct cancellation_slot_binder_async_result_completion_handler_type
481 template <typename TargetAsyncResult, typename CancellationSlot>
482 struct cancellation_slot_binder_async_result_completion_handler_type<
483 TargetAsyncResult, CancellationSlot,
485 typename TargetAsyncResult::completion_handler_type
488 typedef cancellation_slot_binder<
489 typename TargetAsyncResult::completion_handler_type, CancellationSlot>
490 completion_handler_type;
493 template <typename TargetAsyncResult, typename = void>
494 struct cancellation_slot_binder_async_result_return_type
498 template <typename TargetAsyncResult>
499 struct cancellation_slot_binder_async_result_return_type<
502 typename TargetAsyncResult::return_type
505 typedef typename TargetAsyncResult::return_type return_type;
508 } // namespace detail
510 template <typename T, typename CancellationSlot, typename Signature>
511 class async_result<cancellation_slot_binder<T, CancellationSlot>, Signature> :
512 public detail::cancellation_slot_binder_async_result_completion_handler_type<
513 async_result<T, Signature>, CancellationSlot>,
514 public detail::cancellation_slot_binder_async_result_return_type<
515 async_result<T, Signature> >
518 explicit async_result(cancellation_slot_binder<T, CancellationSlot>& b)
523 typename async_result<T, Signature>::return_type get()
525 return target_.get();
528 template <typename Initiation>
531 template <typename Init>
532 init_wrapper(const CancellationSlot& slot, BOOST_ASIO_MOVE_ARG(Init) init)
534 initiation_(BOOST_ASIO_MOVE_CAST(Init)(init))
538 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
540 template <typename Handler, typename... Args>
542 BOOST_ASIO_MOVE_ARG(Handler) handler,
543 BOOST_ASIO_MOVE_ARG(Args)... args)
545 BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
546 cancellation_slot_binder<
547 typename decay<Handler>::type, CancellationSlot>(
548 slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
549 BOOST_ASIO_MOVE_CAST(Args)(args)...);
552 template <typename Handler, typename... Args>
554 BOOST_ASIO_MOVE_ARG(Handler) handler,
555 BOOST_ASIO_MOVE_ARG(Args)... args) const
558 cancellation_slot_binder<
559 typename decay<Handler>::type, CancellationSlot>(
560 slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
561 BOOST_ASIO_MOVE_CAST(Args)(args)...);
564 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
566 template <typename Handler>
568 BOOST_ASIO_MOVE_ARG(Handler) handler)
570 BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
571 cancellation_slot_binder<
572 typename decay<Handler>::type, CancellationSlot>(
573 slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
576 template <typename Handler>
578 BOOST_ASIO_MOVE_ARG(Handler) handler) const
581 cancellation_slot_binder<
582 typename decay<Handler>::type, CancellationSlot>(
583 slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
586 #define BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
587 template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
589 BOOST_ASIO_MOVE_ARG(Handler) handler, \
590 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
592 BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( \
593 cancellation_slot_binder< \
594 typename decay<Handler>::type, CancellationSlot>( \
595 slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
596 BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
599 template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
601 BOOST_ASIO_MOVE_ARG(Handler) handler, \
602 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
605 cancellation_slot_binder< \
606 typename decay<Handler>::type, CancellationSlot>( \
607 slot_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
608 BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
611 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF)
612 #undef BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF
614 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
616 CancellationSlot slot_;
617 Initiation initiation_;
620 #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
622 template <typename Initiation, typename RawCompletionToken, typename... Args>
623 static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
624 (async_initiate<T, Signature>(
625 declval<init_wrapper<typename decay<Initiation>::type> >(),
626 declval<RawCompletionToken>().get(),
627 declval<BOOST_ASIO_MOVE_ARG(Args)>()...)))
629 BOOST_ASIO_MOVE_ARG(Initiation) initiation,
630 BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
631 BOOST_ASIO_MOVE_ARG(Args)... args)
633 return async_initiate<T, Signature>(
634 init_wrapper<typename decay<Initiation>::type>(
635 token.get_cancellation_slot(),
636 BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
637 token.get(), BOOST_ASIO_MOVE_CAST(Args)(args)...);
640 #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
642 template <typename Initiation, typename RawCompletionToken>
643 static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
644 (async_initiate<T, Signature>(
645 declval<init_wrapper<typename decay<Initiation>::type> >(),
646 declval<RawCompletionToken>().get())))
648 BOOST_ASIO_MOVE_ARG(Initiation) initiation,
649 BOOST_ASIO_MOVE_ARG(RawCompletionToken) token)
651 return async_initiate<T, Signature>(
652 init_wrapper<typename decay<Initiation>::type>(
653 token.get_cancellation_slot(),
654 BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
658 #define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \
659 template <typename Initiation, typename RawCompletionToken, \
660 BOOST_ASIO_VARIADIC_TPARAMS(n)> \
661 static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \
662 (async_initiate<T, Signature>( \
663 declval<init_wrapper<typename decay<Initiation>::type> >(), \
664 declval<RawCompletionToken>().get(), \
665 BOOST_ASIO_VARIADIC_MOVE_DECLVAL(n)))) \
667 BOOST_ASIO_MOVE_ARG(Initiation) initiation, \
668 BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, \
669 BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
671 return async_initiate<T, Signature>( \
672 init_wrapper<typename decay<Initiation>::type>( \
673 token.get_cancellation_slot(), \
674 BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), \
675 token.get(), BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
678 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF)
679 #undef BOOST_ASIO_PRIVATE_INITIATE_DEF
681 #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
684 async_result(const async_result&) BOOST_ASIO_DELETED;
685 async_result& operator=(const async_result&) BOOST_ASIO_DELETED;
687 async_result<T, Signature> target_;
690 template <template <typename, typename> class Associator,
691 typename T, typename CancellationSlot, typename DefaultCandidate>
692 struct associator<Associator,
693 cancellation_slot_binder<T, CancellationSlot>,
696 typedef typename Associator<T, DefaultCandidate>::type type;
698 static type get(const cancellation_slot_binder<T, CancellationSlot>& b,
699 const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
701 return Associator<T, DefaultCandidate>::get(b.get(), c);
705 template <typename T, typename CancellationSlot, typename CancellationSlot1>
706 struct associated_cancellation_slot<
707 cancellation_slot_binder<T, CancellationSlot>,
710 typedef CancellationSlot type;
712 static type get(const cancellation_slot_binder<T, CancellationSlot>& b,
713 const CancellationSlot1& = CancellationSlot1()) BOOST_ASIO_NOEXCEPT
715 return b.get_cancellation_slot();
719 #endif // !defined(GENERATING_DOCUMENTATION)
724 #include <boost/asio/detail/pop_options.hpp>
726 #endif // BOOST_ASIO_BIND_CANCELLATION_SLOT_HPP