| // |
| // execution/sender.hpp |
| // ~~~~~~~~~~~~~~~~~~~~ |
| // |
| // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
| // |
| // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| // |
| |
| #ifndef ASIO_EXECUTION_SENDER_HPP |
| #define ASIO_EXECUTION_SENDER_HPP |
| |
| #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
| # pragma once |
| #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
| |
| #include "asio/detail/config.hpp" |
| #include "asio/detail/type_traits.hpp" |
| #include "asio/execution/detail/as_invocable.hpp" |
| #include "asio/execution/detail/void_receiver.hpp" |
| #include "asio/execution/executor.hpp" |
| #include "asio/execution/receiver.hpp" |
| |
| #include "asio/detail/push_options.hpp" |
| |
| #if defined(ASIO_HAS_ALIAS_TEMPLATES) \ |
| && defined(ASIO_HAS_VARIADIC_TEMPLATES) \ |
| && defined(ASIO_HAS_DECLTYPE) \ |
| && !defined(ASIO_MSVC) || (_MSC_VER >= 1910) |
| # define ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT 1 |
| #endif // defined(ASIO_HAS_ALIAS_TEMPLATES) |
| // && defined(ASIO_HAS_VARIADIC_TEMPLATES) |
| // && defined(ASIO_HAS_DECLTYPE) |
| // && !defined(ASIO_MSVC) || (_MSC_VER >= 1910) |
| |
| namespace asio { |
| namespace execution { |
| namespace detail { |
| |
| namespace sender_base_ns { struct sender_base {}; } |
| |
| template <typename S, typename = void> |
| struct sender_traits_base |
| { |
| typedef void asio_execution_sender_traits_base_is_unspecialised; |
| }; |
| |
| template <typename S> |
| struct sender_traits_base<S, |
| typename enable_if< |
| is_base_of<sender_base_ns::sender_base, S>::value |
| >::type> |
| { |
| }; |
| |
| template <typename S, typename = void, typename = void, typename = void> |
| struct has_sender_types : false_type |
| { |
| }; |
| |
| #if defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) |
| |
| template < |
| template < |
| template <typename...> class Tuple, |
| template <typename...> class Variant |
| > class> |
| struct has_value_types |
| { |
| typedef void type; |
| }; |
| |
| template < |
| template < |
| template <typename...> class Variant |
| > class> |
| struct has_error_types |
| { |
| typedef void type; |
| }; |
| |
| template <typename S> |
| struct has_sender_types<S, |
| typename has_value_types<S::template value_types>::type, |
| typename has_error_types<S::template error_types>::type, |
| typename conditional<S::sends_done, void, void>::type> : true_type |
| { |
| }; |
| |
| template <typename S> |
| struct sender_traits_base<S, |
| typename enable_if< |
| has_sender_types<S>::value |
| >::type> |
| { |
| template < |
| template <typename...> class Tuple, |
| template <typename...> class Variant> |
| using value_types = typename S::template value_types<Tuple, Variant>; |
| |
| template <template <typename...> class Variant> |
| using error_types = typename S::template error_types<Variant>; |
| |
| ASIO_STATIC_CONSTEXPR(bool, sends_done = S::sends_done); |
| }; |
| |
| #endif // defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) |
| |
| template <typename S> |
| struct sender_traits_base<S, |
| typename enable_if< |
| !has_sender_types<S>::value |
| && detail::is_executor_of_impl<S, |
| as_invocable<void_receiver, S> >::value |
| >::type> |
| { |
| #if defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) \ |
| && defined(ASIO_HAS_STD_EXCEPTION_PTR) |
| |
| template < |
| template <typename...> class Tuple, |
| template <typename...> class Variant> |
| using value_types = Variant<Tuple<>>; |
| |
| template <template <typename...> class Variant> |
| using error_types = Variant<std::exception_ptr>; |
| |
| ASIO_STATIC_CONSTEXPR(bool, sends_done = true); |
| |
| #endif // defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) |
| // && defined(ASIO_HAS_STD_EXCEPTION_PTR) |
| }; |
| |
| } // namespace detail |
| |
| /// Base class used for tagging senders. |
| #if defined(GENERATING_DOCUMENTATION) |
| typedef unspecified sender_base; |
| #else // defined(GENERATING_DOCUMENTATION) |
| typedef detail::sender_base_ns::sender_base sender_base; |
| #endif // defined(GENERATING_DOCUMENTATION) |
| |
| /// Traits for senders. |
| template <typename S> |
| struct sender_traits |
| #if !defined(GENERATING_DOCUMENTATION) |
| : detail::sender_traits_base<S> |
| #endif // !defined(GENERATING_DOCUMENTATION) |
| { |
| }; |
| |
| namespace detail { |
| |
| template <typename S, typename = void> |
| struct has_sender_traits : true_type |
| { |
| }; |
| |
| template <typename S> |
| struct has_sender_traits<S, |
| typename enable_if< |
| is_same< |
| typename asio::execution::sender_traits< |
| S>::asio_execution_sender_traits_base_is_unspecialised, |
| void |
| >::value |
| >::type> : false_type |
| { |
| }; |
| |
| } // namespace detail |
| |
| /// The is_sender trait detects whether a type T satisfies the |
| /// execution::sender concept. |
| |
| /** |
| * Class template @c is_sender is a type trait that is derived from @c |
| * true_type if the type @c T meets the concept definition for a sender, |
| * otherwise @c false_type. |
| */ |
| template <typename T> |
| struct is_sender : |
| #if defined(GENERATING_DOCUMENTATION) |
| integral_constant<bool, automatically_determined> |
| #else // defined(GENERATING_DOCUMENTATION) |
| conditional< |
| detail::has_sender_traits<typename remove_cvref<T>::type>::value, |
| is_move_constructible<typename remove_cvref<T>::type>, |
| false_type |
| >::type |
| #endif // defined(GENERATING_DOCUMENTATION) |
| { |
| }; |
| |
| #if defined(ASIO_HAS_VARIABLE_TEMPLATES) |
| |
| template <typename T> |
| ASIO_CONSTEXPR const bool is_sender_v = is_sender<T>::value; |
| |
| #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) |
| |
| #if defined(ASIO_HAS_CONCEPTS) |
| |
| template <typename T> |
| ASIO_CONCEPT sender = is_sender<T>::value; |
| |
| #define ASIO_EXECUTION_SENDER ::asio::execution::sender |
| |
| #else // defined(ASIO_HAS_CONCEPTS) |
| |
| #define ASIO_EXECUTION_SENDER typename |
| |
| #endif // defined(ASIO_HAS_CONCEPTS) |
| |
| template <typename S, typename R> |
| struct can_connect; |
| |
| /// The is_sender_to trait detects whether a type T satisfies the |
| /// execution::sender_to concept for some receiver. |
| /** |
| * Class template @c is_sender_to is a type trait that is derived from @c |
| * true_type if the type @c T meets the concept definition for a sender |
| * for some receiver type R, otherwise @c false. |
| */ |
| template <typename T, typename R> |
| struct is_sender_to : |
| #if defined(GENERATING_DOCUMENTATION) |
| integral_constant<bool, automatically_determined> |
| #else // defined(GENERATING_DOCUMENTATION) |
| integral_constant<bool, |
| is_sender<T>::value |
| && is_receiver<R>::value |
| && can_connect<T, R>::value |
| > |
| #endif // defined(GENERATING_DOCUMENTATION) |
| { |
| }; |
| |
| #if defined(ASIO_HAS_VARIABLE_TEMPLATES) |
| |
| template <typename T, typename R> |
| ASIO_CONSTEXPR const bool is_sender_to_v = |
| is_sender_to<T, R>::value; |
| |
| #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) |
| |
| #if defined(ASIO_HAS_CONCEPTS) |
| |
| template <typename T, typename R> |
| ASIO_CONCEPT sender_to = is_sender_to<T, R>::value; |
| |
| #define ASIO_EXECUTION_SENDER_TO(r) \ |
| ::asio::execution::sender_to<r> |
| |
| #else // defined(ASIO_HAS_CONCEPTS) |
| |
| #define ASIO_EXECUTION_SENDER_TO(r) typename |
| |
| #endif // defined(ASIO_HAS_CONCEPTS) |
| |
| /// The is_typed_sender trait detects whether a type T satisfies the |
| /// execution::typed_sender concept. |
| /** |
| * Class template @c is_typed_sender is a type trait that is derived from @c |
| * true_type if the type @c T meets the concept definition for a typed sender, |
| * otherwise @c false. |
| */ |
| template <typename T> |
| struct is_typed_sender : |
| #if defined(GENERATING_DOCUMENTATION) |
| integral_constant<bool, automatically_determined> |
| #else // defined(GENERATING_DOCUMENTATION) |
| integral_constant<bool, |
| is_sender<T>::value |
| && detail::has_sender_types< |
| sender_traits<typename remove_cvref<T>::type> >::value |
| > |
| #endif // defined(GENERATING_DOCUMENTATION) |
| { |
| }; |
| |
| #if defined(ASIO_HAS_VARIABLE_TEMPLATES) |
| |
| template <typename T> |
| ASIO_CONSTEXPR const bool is_typed_sender_v = is_typed_sender<T>::value; |
| |
| #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) |
| |
| #if defined(ASIO_HAS_CONCEPTS) |
| |
| template <typename T> |
| ASIO_CONCEPT typed_sender = is_typed_sender<T>::value; |
| |
| #define ASIO_EXECUTION_TYPED_SENDER \ |
| ::asio::execution::typed_sender |
| |
| #else // defined(ASIO_HAS_CONCEPTS) |
| |
| #define ASIO_EXECUTION_TYPED_SENDER typename |
| |
| #endif // defined(ASIO_HAS_CONCEPTS) |
| |
| } // namespace execution |
| } // namespace asio |
| |
| #include "asio/detail/pop_options.hpp" |
| |
| #include "asio/execution/connect.hpp" |
| |
| #endif // ASIO_EXECUTION_SENDER_HPP |