diff options
Diffstat (limited to '3rdparty/asio/include/asio/execution/any_executor.hpp')
-rw-r--r-- | 3rdparty/asio/include/asio/execution/any_executor.hpp | 2346 |
1 files changed, 2346 insertions, 0 deletions
diff --git a/3rdparty/asio/include/asio/execution/any_executor.hpp b/3rdparty/asio/include/asio/execution/any_executor.hpp new file mode 100644 index 00000000000..b5f5233fdfb --- /dev/null +++ b/3rdparty/asio/include/asio/execution/any_executor.hpp @@ -0,0 +1,2346 @@ +// +// execution/any_executor.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_ANY_EXECUTOR_HPP +#define ASIO_EXECUTION_ANY_EXECUTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <new> +#include <typeinfo> +#include "asio/detail/assert.hpp" +#include "asio/detail/cstddef.hpp" +#include "asio/detail/executor_function.hpp" +#include "asio/detail/memory.hpp" +#include "asio/detail/non_const_lvalue.hpp" +#include "asio/detail/scoped_ptr.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/detail/throw_exception.hpp" +#include "asio/detail/variadic_templates.hpp" +#include "asio/execution/bad_executor.hpp" +#include "asio/execution/blocking.hpp" +#include "asio/execution/execute.hpp" +#include "asio/execution/executor.hpp" +#include "asio/prefer.hpp" +#include "asio/query.hpp" +#include "asio/require.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +#if defined(GENERATING_DOCUMENTATION) + +namespace execution { + +/// Polymorphic executor wrapper. +template <typename... SupportableProperties> +class any_executor +{ +public: + /// Default constructor. + any_executor() noexcept; + + /// Construct in an empty state. Equivalent effects to default constructor. + any_executor(nullptr_t) noexcept; + + /// Copy constructor. + any_executor(const any_executor& e) noexcept; + + /// Move constructor. + any_executor(any_executor&& e) noexcept; + + /// Construct to point to the same target as another any_executor. + template <class... OtherSupportableProperties> + any_executor(any_executor<OtherSupportableProperties...> e); + + /// Construct a polymorphic wrapper for the specified executor. + template <typename Executor> + any_executor(Executor e); + + /// Assignment operator. + any_executor& operator=(const any_executor& e) noexcept; + + /// Move assignment operator. + any_executor& operator=(any_executor&& e) noexcept; + + /// Assignment operator that sets the polymorphic wrapper to the empty state. + any_executor& operator=(nullptr_t); + + /// Assignment operator to create a polymorphic wrapper for the specified + /// executor. + template <typename Executor> + any_executor& operator=(Executor e); + + /// Destructor. + ~any_executor(); + + /// Swap targets with another polymorphic wrapper. + void swap(any_executor& other) noexcept; + + /// Obtain a polymorphic wrapper with the specified property. + /** + * Do not call this function directly. It is intended for use with the + * asio::require and asio::prefer customisation points. + * + * For example: + * @code execution::any_executor<execution::blocking_t::possibly_t> ex = ...; + * auto ex2 = asio::requre(ex, execution::blocking.possibly); @endcode + */ + template <typename Property> + any_executor require(Property) const; + + /// Obtain a polymorphic wrapper with the specified property. + /** + * Do not call this function directly. It is intended for use with the + * asio::prefer customisation point. + * + * For example: + * @code execution::any_executor<execution::blocking_t::possibly_t> ex = ...; + * auto ex2 = asio::prefer(ex, execution::blocking.possibly); @endcode + */ + template <typename Property> + any_executor prefer(Property) const; + + /// Obtain the value associated with the specified property. + /** + * Do not call this function directly. It is intended for use with the + * asio::query customisation point. + * + * For example: + * @code execution::any_executor<execution::occupancy_t> ex = ...; + * size_t n = asio::query(ex, execution::occupancy); @endcode + */ + template <typename Property> + typename Property::polymorphic_query_result_type query(Property) const; + + /// Execute the function on the target executor. + /** + * Do not call this function directly. It is intended for use with the + * execution::execute customisation point. + * + * For example: + * @code execution::any_executor<> ex = ...; + * execution::execute(ex, my_function_object); @endcode + * + * Throws asio::bad_executor if the polymorphic wrapper has no target. + */ + template <typename Function> + void execute(Function&& f) const; + + /// Obtain the underlying execution context. + /** + * This function is provided for backward compatibility. It is automatically + * defined when the @c SupportableProperties... list includes a property of + * type <tt>execution::context_as<U></tt>, for some type <tt>U</tt>. + */ + automatically_determined context() const; + + /// Determine whether the wrapper has a target executor. + /** + * @returns @c true if the polymorphic wrapper has a target executor, + * otherwise false. + */ + explicit operator bool() const noexcept; + + /// Get the type of the target executor. + const type_info& target_type() const noexcept; + + /// Get a pointer to the target executor. + template <typename Executor> Executor* target() noexcept; + + /// Get a pointer to the target executor. + template <typename Executor> const Executor* target() const noexcept; +}; + +/// Equality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator==(const any_executor<SupportableProperties...>& a, + const any_executor<SupportableProperties...>& b) noexcept; + +/// Equality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator==(const any_executor<SupportableProperties...>& a, + nullptr_t) noexcept; + +/// Equality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator==(nullptr_t, + const any_executor<SupportableProperties...>& b) noexcept; + +/// Inequality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator!=(const any_executor<SupportableProperties...>& a, + const any_executor<SupportableProperties...>& b) noexcept; + +/// Inequality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator!=(const any_executor<SupportableProperties...>& a, + nullptr_t) noexcept; + +/// Inequality operator. +/** + * @relates any_executor + */ +template <typename... SupportableProperties> +bool operator!=(nullptr_t, + const any_executor<SupportableProperties...>& b) noexcept; + +} // namespace execution + +#else // defined(GENERATING_DOCUMENTATION) + +namespace execution { + +#if !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL) +#define ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL + +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename... SupportableProperties> +class any_executor; + +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename = void, typename = void, typename = void, + typename = void, typename = void, typename = void, + typename = void, typename = void, typename = void> +class any_executor; + +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +#endif // !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL) + +template <typename U> +struct context_as_t; + +namespace detail { + +// Traits used to detect whether a property is requirable or preferable, taking +// into account that T::is_requirable or T::is_preferable may not not be well +// formed. + +template <typename T, typename = void> +struct is_requirable : false_type {}; + +template <typename T> +struct is_requirable<T, typename enable_if<T::is_requirable>::type> : + true_type {}; + +template <typename T, typename = void> +struct is_preferable : false_type {}; + +template <typename T> +struct is_preferable<T, typename enable_if<T::is_preferable>::type> : + true_type {}; + +// Trait used to detect context_as property, for backward compatibility. + +template <typename T> +struct is_context_as : false_type {}; + +template <typename U> +struct is_context_as<context_as_t<U> > : true_type {}; + +// Helper template to: +// - Check if a target can supply the supportable properties. +// - Find the first convertible-from-T property in the list. + +template <std::size_t I, typename Props> +struct supportable_properties; + +template <std::size_t I, typename Prop> +struct supportable_properties<I, void(Prop)> +{ + template <typename T> + struct is_valid_target : integral_constant<bool, + ( + is_requirable<Prop>::value + ? can_require<T, Prop>::value + : true + ) + && + ( + is_preferable<Prop>::value + ? can_prefer<T, Prop>::value + : true + ) + && + ( + !is_requirable<Prop>::value && !is_preferable<Prop>::value + ? can_query<T, Prop>::value + : true + ) + > + { + }; + + struct found + { + ASIO_STATIC_CONSTEXPR(bool, value = true); + typedef Prop type; + typedef typename Prop::polymorphic_query_result_type query_result_type; + ASIO_STATIC_CONSTEXPR(std::size_t, index = I); + }; + + struct not_found + { + ASIO_STATIC_CONSTEXPR(bool, value = false); + }; + + template <typename T> + struct find_convertible_property : + conditional< + is_same<T, Prop>::value || is_convertible<T, Prop>::value, + found, + not_found + >::type {}; + + template <typename T> + struct find_convertible_requirable_property : + conditional< + is_requirable<Prop>::value + && (is_same<T, Prop>::value || is_convertible<T, Prop>::value), + found, + not_found + >::type {}; + + template <typename T> + struct find_convertible_preferable_property : + conditional< + is_preferable<Prop>::value + && (is_same<T, Prop>::value || is_convertible<T, Prop>::value), + found, + not_found + >::type {}; + + struct find_context_as_property : + conditional< + is_context_as<Prop>::value, + found, + not_found + >::type {}; +}; + +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <std::size_t I, typename Head, typename... Tail> +struct supportable_properties<I, void(Head, Tail...)> +{ + template <typename T> + struct is_valid_target : integral_constant<bool, + ( + supportable_properties<I, + void(Head)>::template is_valid_target<T>::value + && + supportable_properties<I + 1, + void(Tail...)>::template is_valid_target<T>::value + ) + > + { + }; + + template <typename T> + struct find_convertible_property : + conditional< + is_convertible<T, Head>::value, + typename supportable_properties<I, void(Head)>::found, + typename supportable_properties<I + 1, + void(Tail...)>::template find_convertible_property<T> + >::type {}; + + template <typename T> + struct find_convertible_requirable_property : + conditional< + is_requirable<Head>::value + && is_convertible<T, Head>::value, + typename supportable_properties<I, void(Head)>::found, + typename supportable_properties<I + 1, + void(Tail...)>::template find_convertible_requirable_property<T> + >::type {}; + + template <typename T> + struct find_convertible_preferable_property : + conditional< + is_preferable<Head>::value + && is_convertible<T, Head>::value, + typename supportable_properties<I, void(Head)>::found, + typename supportable_properties<I + 1, + void(Tail...)>::template find_convertible_preferable_property<T> + >::type {}; + + struct find_context_as_property : + conditional< + is_context_as<Head>::value, + typename supportable_properties<I, void(Head)>::found, + typename supportable_properties<I + 1, + void(Tail...)>::find_context_as_property + >::type {}; +}; + +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +#define ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF(n) \ + template <std::size_t I, \ + typename Head, ASIO_VARIADIC_TPARAMS(n)> \ + struct supportable_properties<I, \ + void(Head, ASIO_VARIADIC_TARGS(n))> \ + { \ + template <typename T> \ + struct is_valid_target : integral_constant<bool, \ + ( \ + supportable_properties<I, \ + void(Head)>::template is_valid_target<T>::value \ + && \ + supportable_properties<I + 1, \ + void(ASIO_VARIADIC_TARGS(n))>::template \ + is_valid_target<T>::value \ + ) \ + > \ + { \ + }; \ + \ + template <typename T> \ + struct find_convertible_property : \ + conditional< \ + is_convertible<T, Head>::value, \ + typename supportable_properties<I, void(Head)>::found, \ + typename supportable_properties<I + 1, \ + void(ASIO_VARIADIC_TARGS(n))>::template \ + find_convertible_property<T> \ + >::type {}; \ + \ + template <typename T> \ + struct find_convertible_requirable_property : \ + conditional< \ + is_requirable<Head>::value \ + && is_convertible<T, Head>::value, \ + typename supportable_properties<I, void(Head)>::found, \ + typename supportable_properties<I + 1, \ + void(ASIO_VARIADIC_TARGS(n))>::template \ + find_convertible_requirable_property<T> \ + >::type {}; \ + \ + template <typename T> \ + struct find_convertible_preferable_property : \ + conditional< \ + is_preferable<Head>::value \ + && is_convertible<T, Head>::value, \ + typename supportable_properties<I, void(Head)>::found, \ + typename supportable_properties<I + 1, \ + void(ASIO_VARIADIC_TARGS(n))>::template \ + find_convertible_preferable_property<T> \ + >::type {}; \ + \ + struct find_context_as_property : \ + conditional< \ + is_context_as<Head>::value, \ + typename supportable_properties<I, void(Head)>::found, \ + typename supportable_properties<I + 1, void( \ + ASIO_VARIADIC_TARGS(n))>::find_context_as_property \ + >::type {}; \ + }; \ + /**/ +ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF) +#undef ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF + +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename T, typename Props> +struct is_valid_target_executor : + conditional< + is_executor<T>::value, + typename supportable_properties<0, Props>::template is_valid_target<T>, + false_type + >::type +{ +}; + +class any_executor_base +{ +public: + any_executor_base() ASIO_NOEXCEPT + : object_fns_(object_fns_table<void>()), + target_(0), + target_fns_(target_fns_table<void>()) + { + } + + template <ASIO_EXECUTION_EXECUTOR Executor> + any_executor_base(Executor ex, false_type) + : target_fns_(target_fns_table<Executor>( + any_executor_base::query_blocking(ex, + can_query<const Executor&, const execution::blocking_t&>()) + == execution::blocking.always)) + { + any_executor_base::construct_object(ex, + integral_constant<bool, + sizeof(Executor) <= sizeof(object_type) + && alignment_of<Executor>::value <= alignment_of<object_type>::value + >()); + } + + template <ASIO_EXECUTION_EXECUTOR Executor> + any_executor_base(Executor other, true_type) + : object_fns_(object_fns_table<asio::detail::shared_ptr<void> >()), + target_fns_(other.target_fns_) + { + asio::detail::shared_ptr<Executor> p = + asio::detail::make_shared<Executor>( + ASIO_MOVE_CAST(Executor)(other)); + target_ = p->template target<void>(); + new (&object_) asio::detail::shared_ptr<void>( + ASIO_MOVE_CAST(asio::detail::shared_ptr<Executor>)(p)); + } + + any_executor_base(const any_executor_base& other) ASIO_NOEXCEPT + : object_fns_(other.object_fns_), + target_fns_(other.target_fns_) + { + object_fns_->copy(*this, other); + } + + ~any_executor_base() ASIO_NOEXCEPT + { + object_fns_->destroy(*this); + } + + any_executor_base& operator=( + const any_executor_base& other) ASIO_NOEXCEPT + { + if (this != &other) + { + object_fns_->destroy(*this); + object_fns_ = other.object_fns_; + target_fns_ = other.target_fns_; + object_fns_->copy(*this, other); + } + return *this; + } + + any_executor_base& operator=(nullptr_t) ASIO_NOEXCEPT + { + object_fns_->destroy(*this); + target_ = 0; + object_fns_ = object_fns_table<void>(); + target_fns_ = target_fns_table<void>(); + return *this; + } + +#if defined(ASIO_HAS_MOVE) + + any_executor_base(any_executor_base&& other) ASIO_NOEXCEPT + : object_fns_(other.object_fns_), + target_fns_(other.target_fns_) + { + other.object_fns_ = object_fns_table<void>(); + other.target_fns_ = target_fns_table<void>(); + object_fns_->move(*this, other); + other.target_ = 0; + } + + any_executor_base& operator=( + any_executor_base&& other) ASIO_NOEXCEPT + { + if (this != &other) + { + object_fns_->destroy(*this); + object_fns_ = other.object_fns_; + other.object_fns_ = object_fns_table<void>(); + target_fns_ = other.target_fns_; + other.target_fns_ = target_fns_table<void>(); + object_fns_->move(*this, other); + other.target_ = 0; + } + return *this; + } + +#endif // defined(ASIO_HAS_MOVE) + + void swap(any_executor_base& other) ASIO_NOEXCEPT + { + if (this != &other) + { + any_executor_base tmp(ASIO_MOVE_CAST(any_executor_base)(other)); + other = ASIO_MOVE_CAST(any_executor_base)(*this); + *this = ASIO_MOVE_CAST(any_executor_base)(tmp); + } + } + + template <typename F> + void execute(ASIO_MOVE_ARG(F) f) const + { + if (target_fns_->blocking_execute != 0) + { + asio::detail::non_const_lvalue<F> f2(f); + target_fns_->blocking_execute(*this, function_view(f2.value)); + } + else + { + target_fns_->execute(*this, + function(ASIO_MOVE_CAST(F)(f), std::allocator<void>())); + } + } + + template <typename Executor> + Executor* target() + { + return static_cast<Executor*>(target_); + } + + template <typename Executor> + const Executor* target() const + { + return static_cast<Executor*>(target_); + } + +#if !defined(ASIO_NO_TYPEID) + const std::type_info& target_type() const +#else // !defined(ASIO_NO_TYPEID) + const void* target_type() const +#endif // !defined(ASIO_NO_TYPEID) + { + return target_fns_->target_type(); + } + + struct unspecified_bool_type_t {}; + typedef void (*unspecified_bool_type)(unspecified_bool_type_t); + static void unspecified_bool_true(unspecified_bool_type_t) {} + + operator unspecified_bool_type() const ASIO_NOEXCEPT + { + return target_ ? &any_executor_base::unspecified_bool_true : 0; + } + + bool operator!() const ASIO_NOEXCEPT + { + return target_ == 0; + } + +protected: + bool equality_helper(const any_executor_base& other) const ASIO_NOEXCEPT + { + if (target_ == other.target_) + return true; + if (target_ && !other.target_) + return false; + if (!target_ && other.target_) + return false; + if (target_fns_ != other.target_fns_) + return false; + return target_fns_->equal(*this, other); + } + + template <typename Ex> + Ex& object() + { + return *static_cast<Ex*>(static_cast<void*>(&object_)); + } + + template <typename Ex> + const Ex& object() const + { + return *static_cast<const Ex*>(static_cast<const void*>(&object_)); + } + + struct object_fns + { + void (*destroy)(any_executor_base&); + void (*copy)(any_executor_base&, const any_executor_base&); + void (*move)(any_executor_base&, any_executor_base&); + const void* (*target)(const any_executor_base&); + }; + + static void destroy_void(any_executor_base&) + { + } + + static void copy_void(any_executor_base& ex1, const any_executor_base&) + { + ex1.target_ = 0; + } + + static void move_void(any_executor_base& ex1, any_executor_base&) + { + ex1.target_ = 0; + } + + static const void* target_void(const any_executor_base&) + { + return 0; + } + + template <typename Obj> + static const object_fns* object_fns_table( + typename enable_if< + is_same<Obj, void>::value + >::type* = 0) + { + static const object_fns fns = + { + &any_executor_base::destroy_void, + &any_executor_base::copy_void, + &any_executor_base::move_void, + &any_executor_base::target_void + }; + return &fns; + } + + static void destroy_shared(any_executor_base& ex) + { + typedef asio::detail::shared_ptr<void> type; + ex.object<type>().~type(); + } + + static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2) + { + typedef asio::detail::shared_ptr<void> type; + new (&ex1.object_) type(ex2.object<type>()); + ex1.target_ = ex2.target_; + } + + static void move_shared(any_executor_base& ex1, any_executor_base& ex2) + { + typedef asio::detail::shared_ptr<void> type; + new (&ex1.object_) type(ASIO_MOVE_CAST(type)(ex2.object<type>())); + ex1.target_ = ex2.target_; + ex2.object<type>().~type(); + } + + static const void* target_shared(const any_executor_base& ex) + { + typedef asio::detail::shared_ptr<void> type; + return ex.object<type>().get(); + } + + template <typename Obj> + static const object_fns* object_fns_table( + typename enable_if< + is_same<Obj, asio::detail::shared_ptr<void> >::value + >::type* = 0) + { + static const object_fns fns = + { + &any_executor_base::destroy_shared, + &any_executor_base::copy_shared, + &any_executor_base::move_shared, + &any_executor_base::target_shared + }; + return &fns; + } + + template <typename Obj> + static void destroy_object(any_executor_base& ex) + { + ex.object<Obj>().~Obj(); + } + + template <typename Obj> + static void copy_object(any_executor_base& ex1, const any_executor_base& ex2) + { + new (&ex1.object_) Obj(ex2.object<Obj>()); + ex1.target_ = &ex1.object<Obj>(); + } + + template <typename Obj> + static void move_object(any_executor_base& ex1, any_executor_base& ex2) + { + new (&ex1.object_) Obj(ASIO_MOVE_CAST(Obj)(ex2.object<Obj>())); + ex1.target_ = &ex1.object<Obj>(); + ex2.object<Obj>().~Obj(); + } + + template <typename Obj> + static const void* target_object(const any_executor_base& ex) + { + return &ex.object<Obj>(); + } + + template <typename Obj> + static const object_fns* object_fns_table( + typename enable_if< + !is_same<Obj, void>::value + && !is_same<Obj, asio::detail::shared_ptr<void> >::value + >::type* = 0) + { + static const object_fns fns = + { + &any_executor_base::destroy_object<Obj>, + &any_executor_base::copy_object<Obj>, + &any_executor_base::move_object<Obj>, + &any_executor_base::target_object<Obj> + }; + return &fns; + } + + typedef asio::detail::executor_function function; + typedef asio::detail::executor_function_view function_view; + + struct target_fns + { +#if !defined(ASIO_NO_TYPEID) + const std::type_info& (*target_type)(); +#else // !defined(ASIO_NO_TYPEID) + const void* (*target_type)(); +#endif // !defined(ASIO_NO_TYPEID) + bool (*equal)(const any_executor_base&, const any_executor_base&); + void (*execute)(const any_executor_base&, ASIO_MOVE_ARG(function)); + void (*blocking_execute)(const any_executor_base&, function_view); + }; + +#if !defined(ASIO_NO_TYPEID) + static const std::type_info& target_type_void() + { + return typeid(void); + } +#else // !defined(ASIO_NO_TYPEID) + static const void* target_type_void() + { + return 0; + } +#endif // !defined(ASIO_NO_TYPEID) + + static bool equal_void(const any_executor_base&, const any_executor_base&) + { + return true; + } + + static void execute_void(const any_executor_base&, + ASIO_MOVE_ARG(function)) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } + + static void blocking_execute_void(const any_executor_base&, function_view) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } + + template <typename Ex> + static const target_fns* target_fns_table( + typename enable_if< + is_same<Ex, void>::value + >::type* = 0) + { + static const target_fns fns = + { + &any_executor_base::target_type_void, + &any_executor_base::equal_void, + &any_executor_base::execute_void, + &any_executor_base::blocking_execute_void + }; + return &fns; + } + +#if !defined(ASIO_NO_TYPEID) + template <typename Ex> + static const std::type_info& target_type_ex() + { + return typeid(Ex); + } +#else // !defined(ASIO_NO_TYPEID) + template <typename Ex> + static const void* target_type_ex() + { + static int unique_id; + return &unique_id; + } +#endif // !defined(ASIO_NO_TYPEID) + + template <typename Ex> + static bool equal_ex(const any_executor_base& ex1, + const any_executor_base& ex2) + { + return *ex1.target<Ex>() == *ex2.target<Ex>(); + } + + template <typename Ex> + static void execute_ex(const any_executor_base& ex, + ASIO_MOVE_ARG(function) f) + { + execution::execute(*ex.target<Ex>(), ASIO_MOVE_CAST(function)(f)); + } + + template <typename Ex> + static void blocking_execute_ex(const any_executor_base& ex, function_view f) + { + execution::execute(*ex.target<Ex>(), f); + } + + template <typename Ex> + static const target_fns* target_fns_table(bool is_always_blocking, + typename enable_if< + !is_same<Ex, void>::value + >::type* = 0) + { + static const target_fns fns_with_execute = + { + &any_executor_base::target_type_ex<Ex>, + &any_executor_base::equal_ex<Ex>, + &any_executor_base::execute_ex<Ex>, + 0 + }; + + static const target_fns fns_with_blocking_execute = + { + &any_executor_base::target_type_ex<Ex>, + &any_executor_base::equal_ex<Ex>, + 0, + &any_executor_base::blocking_execute_ex<Ex> + }; + + return is_always_blocking ? &fns_with_blocking_execute : &fns_with_execute; + } + +#if defined(ASIO_MSVC) +# pragma warning (push) +# pragma warning (disable:4702) +#endif // defined(ASIO_MSVC) + + static void query_fn_void(void*, const void*, const void*) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void*, const void* ex, const void* prop, + typename enable_if< + asio::can_query<const Ex&, const Prop&>::value + && is_same<typename Prop::polymorphic_query_result_type, void>::value + >::type*) + { + asio::query(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop)); + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void*, const void*, const void*, + typename enable_if< + !asio::can_query<const Ex&, const Prop&>::value + && is_same<typename Prop::polymorphic_query_result_type, void>::value + >::type*) + { + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void* result, const void* ex, const void* prop, + typename enable_if< + asio::can_query<const Ex&, const Prop&>::value + && !is_same<typename Prop::polymorphic_query_result_type, void>::value + && is_reference<typename Prop::polymorphic_query_result_type>::value + >::type*) + { + *static_cast<typename remove_reference< + typename Prop::polymorphic_query_result_type>::type**>(result) + = &static_cast<typename Prop::polymorphic_query_result_type>( + asio::query(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop))); + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void*, const void*, const void*, + typename enable_if< + !asio::can_query<const Ex&, const Prop&>::value + && !is_same<typename Prop::polymorphic_query_result_type, void>::value + && is_reference<typename Prop::polymorphic_query_result_type>::value + >::type*) + { + std::terminate(); // Combination should not be possible. + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void* result, const void* ex, const void* prop, + typename enable_if< + asio::can_query<const Ex&, const Prop&>::value + && !is_same<typename Prop::polymorphic_query_result_type, void>::value + && is_scalar<typename Prop::polymorphic_query_result_type>::value + >::type*) + { + *static_cast<typename Prop::polymorphic_query_result_type*>(result) + = static_cast<typename Prop::polymorphic_query_result_type>( + asio::query(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop))); + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void* result, const void*, const void*, + typename enable_if< + !asio::can_query<const Ex&, const Prop&>::value + && !is_same<typename Prop::polymorphic_query_result_type, void>::value + && is_scalar<typename Prop::polymorphic_query_result_type>::value + >::type*) + { + *static_cast<typename Prop::polymorphic_query_result_type*>(result) + = typename Prop::polymorphic_query_result_type(); + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void* result, const void* ex, const void* prop, + typename enable_if< + asio::can_query<const Ex&, const Prop&>::value + && !is_same<typename Prop::polymorphic_query_result_type, void>::value + && !is_reference<typename Prop::polymorphic_query_result_type>::value + && !is_scalar<typename Prop::polymorphic_query_result_type>::value + >::type*) + { + *static_cast<typename Prop::polymorphic_query_result_type**>(result) + = new typename Prop::polymorphic_query_result_type( + asio::query(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop))); + } + + template <typename Ex, class Prop> + static void query_fn_non_void(void* result, const void*, const void*, ...) + { + *static_cast<typename Prop::polymorphic_query_result_type**>(result) + = new typename Prop::polymorphic_query_result_type(); + } + + template <typename Ex, class Prop> + static void query_fn_impl(void* result, const void* ex, const void* prop, + typename enable_if< + is_same<Ex, void>::value + >::type*) + { + query_fn_void(result, ex, prop); + } + + template <typename Ex, class Prop> + static void query_fn_impl(void* result, const void* ex, const void* prop, + typename enable_if< + !is_same<Ex, void>::value + >::type*) + { + query_fn_non_void<Ex, Prop>(result, ex, prop, 0); + } + + template <typename Ex, class Prop> + static void query_fn(void* result, const void* ex, const void* prop) + { + query_fn_impl<Ex, Prop>(result, ex, prop, 0); + } + + template <typename Poly, typename Ex, class Prop> + static Poly require_fn_impl(const void*, const void*, + typename enable_if< + is_same<Ex, void>::value + >::type*) + { + bad_executor ex; + asio::detail::throw_exception(ex); + return Poly(); + } + + template <typename Poly, typename Ex, class Prop> + static Poly require_fn_impl(const void* ex, const void* prop, + typename enable_if< + !is_same<Ex, void>::value && Prop::is_requirable + >::type*) + { + return asio::require(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop)); + } + + template <typename Poly, typename Ex, class Prop> + static Poly require_fn_impl(const void*, const void*, ...) + { + return Poly(); + } + + template <typename Poly, typename Ex, class Prop> + static Poly require_fn(const void* ex, const void* prop) + { + return require_fn_impl<Poly, Ex, Prop>(ex, prop, 0); + } + + template <typename Poly, typename Ex, class Prop> + static Poly prefer_fn_impl(const void*, const void*, + typename enable_if< + is_same<Ex, void>::value + >::type*) + { + bad_executor ex; + asio::detail::throw_exception(ex); + return Poly(); + } + + template <typename Poly, typename Ex, class Prop> + static Poly prefer_fn_impl(const void* ex, const void* prop, + typename enable_if< + !is_same<Ex, void>::value && Prop::is_preferable + >::type*) + { + return asio::prefer(*static_cast<const Ex*>(ex), + *static_cast<const Prop*>(prop)); + } + + template <typename Poly, typename Ex, class Prop> + static Poly prefer_fn_impl(const void*, const void*, ...) + { + return Poly(); + } + + template <typename Poly, typename Ex, class Prop> + static Poly prefer_fn(const void* ex, const void* prop) + { + return prefer_fn_impl<Poly, Ex, Prop>(ex, prop, 0); + } + + template <typename Poly> + struct prop_fns + { + void (*query)(void*, const void*, const void*); + Poly (*require)(const void*, const void*); + Poly (*prefer)(const void*, const void*); + }; + +#if defined(ASIO_MSVC) +# pragma warning (pop) +#endif // defined(ASIO_MSVC) + +private: + template <typename Executor> + static execution::blocking_t query_blocking(const Executor& ex, true_type) + { + return asio::query(ex, execution::blocking); + } + + template <typename Executor> + static execution::blocking_t query_blocking(const Executor&, false_type) + { + return execution::blocking_t(); + } + + template <typename Executor> + void construct_object(Executor& ex, true_type) + { + object_fns_ = object_fns_table<Executor>(); + target_ = new (&object_) Executor(ASIO_MOVE_CAST(Executor)(ex)); + } + + template <typename Executor> + void construct_object(Executor& ex, false_type) + { + object_fns_ = object_fns_table<asio::detail::shared_ptr<void> >(); + asio::detail::shared_ptr<Executor> p = + asio::detail::make_shared<Executor>( + ASIO_MOVE_CAST(Executor)(ex)); + target_ = p.get(); + new (&object_) asio::detail::shared_ptr<void>( + ASIO_MOVE_CAST(asio::detail::shared_ptr<Executor>)(p)); + } + +/*private:*/public: +// template <typename...> friend class any_executor; + + typedef aligned_storage< + sizeof(asio::detail::shared_ptr<void>), + alignment_of<asio::detail::shared_ptr<void> >::value + >::type object_type; + + object_type object_; + const object_fns* object_fns_; + void* target_; + const target_fns* target_fns_; +}; + +template <typename Derived, typename Property, typename = void> +struct any_executor_context +{ +}; + +#if !defined(ASIO_NO_TS_EXECUTORS) + +template <typename Derived, typename Property> +struct any_executor_context<Derived, Property, + typename enable_if<Property::value>::type> +{ + typename Property::query_result_type context() const + { + return static_cast<const Derived*>(this)->query(typename Property::type()); + } +}; + +#endif // !defined(ASIO_NO_TS_EXECUTORS) + +} // namespace detail + +template <> +class any_executor<> : public detail::any_executor_base +{ +public: + any_executor() ASIO_NOEXCEPT + : detail::any_executor_base() + { + } + + any_executor(nullptr_t) ASIO_NOEXCEPT + : detail::any_executor_base() + { + } + + template <typename Executor> + any_executor(Executor ex, + typename enable_if< + conditional< + !is_same<Executor, any_executor>::value + && !is_base_of<detail::any_executor_base, Executor>::value, + is_executor<Executor>, + false_type + >::type::value + >::type* = 0) + : detail::any_executor_base( + ASIO_MOVE_CAST(Executor)(ex), false_type()) + { + } + +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) + + template <typename... OtherSupportableProperties> + any_executor(any_executor<OtherSupportableProperties...> other) + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)) + { + } + +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + + template <typename U0, typename U1, typename U2, typename U3, + typename U4, typename U5, typename U6, typename U7> + any_executor(any_executor<U0, U1, U2, U3, U4, U5, U6, U7> other) + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)) + { + } + +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) + + any_executor(const any_executor& other) ASIO_NOEXCEPT + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)) + { + } + + any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT + { + if (this != &other) + { + detail::any_executor_base::operator=( + static_cast<const detail::any_executor_base&>(other)); + } + return *this; + } + + any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT + { + detail::any_executor_base::operator=(p); + return *this; + } + +#if defined(ASIO_HAS_MOVE) + + any_executor(any_executor&& other) ASIO_NOEXCEPT + : detail::any_executor_base( + static_cast<any_executor_base&&>( + static_cast<any_executor_base&>(other))) + { + } + + any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT + { + if (this != &other) + { + detail::any_executor_base::operator=( + static_cast<detail::any_executor_base&&>( + static_cast<detail::any_executor_base&>(other))); + } + return *this; + } + +#endif // defined(ASIO_HAS_MOVE) + + void swap(any_executor& other) ASIO_NOEXCEPT + { + detail::any_executor_base::swap( + static_cast<detail::any_executor_base&>(other)); + } + + using detail::any_executor_base::execute; + using detail::any_executor_base::target; + using detail::any_executor_base::target_type; + using detail::any_executor_base::operator unspecified_bool_type; + using detail::any_executor_base::operator!; + + bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT + { + return any_executor_base::equality_helper(other); + } + + template <typename AnyExecutor1, typename AnyExecutor2> + friend typename enable_if< + is_base_of<any_executor, AnyExecutor1>::value + || is_base_of<any_executor, AnyExecutor2>::value, + bool + >::type operator==(const AnyExecutor1& a, + const AnyExecutor2& b) ASIO_NOEXCEPT + { + return static_cast<const any_executor&>(a).equality_helper(b); + } + + template <typename AnyExecutor> + friend typename enable_if< + is_same<AnyExecutor, any_executor>::value, + bool + >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT + { + return !a; + } + + template <typename AnyExecutor> + friend typename enable_if< + is_same<AnyExecutor, any_executor>::value, + bool + >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT + { + return !b; + } + + template <typename AnyExecutor1, typename AnyExecutor2> + friend typename enable_if< + is_base_of<any_executor, AnyExecutor1>::value + || is_base_of<any_executor, AnyExecutor2>::value, + bool + >::type operator!=(const AnyExecutor1& a, + const AnyExecutor2& b) ASIO_NOEXCEPT + { + return !static_cast<const any_executor&>(a).equality_helper(b); + } + + template <typename AnyExecutor> + friend typename enable_if< + is_same<AnyExecutor, any_executor>::value, + bool + >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT + { + return !!a; + } + + template <typename AnyExecutor> + friend typename enable_if< + is_same<AnyExecutor, any_executor>::value, + bool + >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT + { + return !!b; + } +}; + +inline void swap(any_executor<>& a, any_executor<>& b) ASIO_NOEXCEPT +{ + return a.swap(b); +} + +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename... SupportableProperties> +class any_executor : + public detail::any_executor_base, + public detail::any_executor_context< + any_executor<SupportableProperties...>, + typename detail::supportable_properties< + 0, void(SupportableProperties...)>::find_context_as_property> +{ +public: + any_executor() ASIO_NOEXCEPT + : detail::any_executor_base(), + prop_fns_(prop_fns_table<void>()) + { + } + + any_executor(nullptr_t) ASIO_NOEXCEPT + : detail::any_executor_base(), + prop_fns_(prop_fns_table<void>()) + { + } + + template <typename Executor> + any_executor(Executor ex, + typename enable_if< + conditional< + !is_same<Executor, any_executor>::value + && !is_base_of<detail::any_executor_base, Executor>::value, + detail::is_valid_target_executor< + Executor, void(SupportableProperties...)>, + false_type + >::type::value + >::type* = 0) + : detail::any_executor_base( + ASIO_MOVE_CAST(Executor)(ex), false_type()), + prop_fns_(prop_fns_table<Executor>()) + { + } + + template <typename... OtherSupportableProperties> + any_executor(any_executor<OtherSupportableProperties...> other, + typename enable_if< + conditional< + !is_same< + any_executor<OtherSupportableProperties...>, + any_executor + >::value, + typename detail::supportable_properties< + 0, void(SupportableProperties...)>::template is_valid_target< + any_executor<OtherSupportableProperties...> >, + false_type + >::type::value + >::type* = 0) + : detail::any_executor_base(ASIO_MOVE_CAST( + any_executor<OtherSupportableProperties...>)(other), true_type()), + prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...> >()) + { + } + + any_executor(const any_executor& other) ASIO_NOEXCEPT + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)), + prop_fns_(other.prop_fns_) + { + } + + any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT + { + if (this != &other) + { + prop_fns_ = other.prop_fns_; + detail::any_executor_base::operator=( + static_cast<const detail::any_executor_base&>(other)); + } + return *this; + } + + any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT + { + prop_fns_ = prop_fns_table<void>(); + detail::any_executor_base::operator=(p); + return *this; + } + +#if defined(ASIO_HAS_MOVE) + + any_executor(any_executor&& other) ASIO_NOEXCEPT + : detail::any_executor_base( + static_cast<any_executor_base&&>( + static_cast<any_executor_base&>(other))), + prop_fns_(other.prop_fns_) + { + other.prop_fns_ = prop_fns_table<void>(); + } + + any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT + { + if (this != &other) + { + prop_fns_ = other.prop_fns_; + detail::any_executor_base::operator=( + static_cast<detail::any_executor_base&&>( + static_cast<detail::any_executor_base&>(other))); + } + return *this; + } + +#endif // defined(ASIO_HAS_MOVE) + + void swap(any_executor& other) ASIO_NOEXCEPT + { + if (this != &other) + { + detail::any_executor_base::swap( + static_cast<detail::any_executor_base&>(other)); + const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_; + other.prop_fns_ = prop_fns_; + prop_fns_ = tmp_prop_fns; + } + } + + using detail::any_executor_base::execute; + using detail::any_executor_base::target; + using detail::any_executor_base::target_type; + using detail::any_executor_base::operator unspecified_bool_type; + using detail::any_executor_base::operator!; + + bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT + { + return any_executor_base::equality_helper(other); + } + + template <typename AnyExecutor1, typename AnyExecutor2> + friend typename enable_if< + is_base_of<any_executor, AnyExecutor1>::value + || is_base_of<any_executor, AnyExecutor2>::value, + bool + >::type operator==(const AnyExecutor1& a, + const AnyExecutor2& b) ASIO_NOEXCEPT + { + return static_cast<const any_executor&>(a).equality_helper(b); + } + + template <typename AnyExecutor> + friend typename enable_if< + is_same<AnyExecutor, any_executor>::value, + bool + >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT + { + return !a; + } + + template <typename AnyExecutor> + friend typename enable_if< + is_same<AnyExecutor, any_executor>::value, + bool + >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT + { + return !b; + } + + template <typename AnyExecutor1, typename AnyExecutor2> + friend typename enable_if< + is_base_of<any_executor, AnyExecutor1>::value + || is_base_of<any_executor, AnyExecutor2>::value, + bool + >::type operator!=(const AnyExecutor1& a, + const AnyExecutor2& b) ASIO_NOEXCEPT + { + return !static_cast<const any_executor&>(a).equality_helper(b); + } + + template <typename AnyExecutor> + friend typename enable_if< + is_same<AnyExecutor, any_executor>::value, + bool + >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT + { + return !!a; + } + + template <typename AnyExecutor> + friend typename enable_if< + is_same<AnyExecutor, any_executor>::value, + bool + >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT + { + return !!b; + } + + template <typename T> + struct find_convertible_property : + detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_property<T> {}; + + template <typename Property> + void query(const Property& p, + typename enable_if< + is_same< + typename find_convertible_property<Property>::query_result_type, + void + >::value + >::type* = 0) const + { + typedef find_convertible_property<Property> found; + prop_fns_[found::index].query(0, object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + } + + template <typename Property> + typename find_convertible_property<Property>::query_result_type + query(const Property& p, + typename enable_if< + !is_same< + typename find_convertible_property<Property>::query_result_type, + void + >::value + && + is_reference< + typename find_convertible_property<Property>::query_result_type + >::value + >::type* = 0) const + { + typedef find_convertible_property<Property> found; + typename remove_reference< + typename found::query_result_type>::type* result = 0; + prop_fns_[found::index].query(&result, object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + return *result; + } + + template <typename Property> + typename find_convertible_property<Property>::query_result_type + query(const Property& p, + typename enable_if< + !is_same< + typename find_convertible_property<Property>::query_result_type, + void + >::value + && + is_scalar< + typename find_convertible_property<Property>::query_result_type + >::value + >::type* = 0) const + { + typedef find_convertible_property<Property> found; + typename found::query_result_type result; + prop_fns_[found::index].query(&result, object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + return result; + } + + template <typename Property> + typename find_convertible_property<Property>::query_result_type + query(const Property& p, + typename enable_if< + !is_same< + typename find_convertible_property<Property>::query_result_type, + void + >::value + && + !is_reference< + typename find_convertible_property<Property>::query_result_type + >::value + && + !is_scalar< + typename find_convertible_property<Property>::query_result_type + >::value + >::type* = 0) const + { + typedef find_convertible_property<Property> found; + typename found::query_result_type* result; + prop_fns_[found::index].query(&result, object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + return *asio::detail::scoped_ptr< + typename found::query_result_type>(result); + } + + template <typename T> + struct find_convertible_requirable_property : + detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_requirable_property<T> {}; + + template <typename Property> + any_executor require(const Property& p, + typename enable_if< + find_convertible_requirable_property<Property>::value + >::type* = 0) const + { + typedef find_convertible_requirable_property<Property> found; + return prop_fns_[found::index].require(object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + } + + template <typename T> + struct find_convertible_preferable_property : + detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_preferable_property<T> {}; + + template <typename Property> + any_executor prefer(const Property& p, + typename enable_if< + find_convertible_preferable_property<Property>::value + >::type* = 0) const + { + typedef find_convertible_preferable_property<Property> found; + return prop_fns_[found::index].prefer(object_fns_->target(*this), + &static_cast<const typename found::type&>(p)); + } + +//private: + template <typename Ex> + static const prop_fns<any_executor>* prop_fns_table() + { + static const prop_fns<any_executor> fns[] = + { + { + &detail::any_executor_base::query_fn< + Ex, SupportableProperties>, + &detail::any_executor_base::require_fn< + any_executor, Ex, SupportableProperties>, + &detail::any_executor_base::prefer_fn< + any_executor, Ex, SupportableProperties> + }... + }; + return fns; + } + + const prop_fns<any_executor>* prop_fns_; +}; + +template <typename... SupportableProperties> +inline void swap(any_executor<SupportableProperties...>& a, + any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT +{ + return a.swap(b); +} + +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \ + ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_##n + +#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 \ + { \ + &detail::any_executor_base::query_fn<Ex, T1>, \ + &detail::any_executor_base::require_fn<any_executor, Ex, T1>, \ + &detail::any_executor_base::prefer_fn<any_executor, Ex, T1> \ + } +#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 \ + ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1, \ + { \ + &detail::any_executor_base::query_fn<Ex, T2>, \ + &detail::any_executor_base::require_fn<any_executor, Ex, T2>, \ + &detail::any_executor_base::prefer_fn<any_executor, Ex, T2> \ + } +#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 \ + ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2, \ + { \ + &detail::any_executor_base::query_fn<Ex, T3>, \ + &detail::any_executor_base::require_fn<any_executor, Ex, T3>, \ + &detail::any_executor_base::prefer_fn<any_executor, Ex, T3> \ + } +#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 \ + ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3, \ + { \ + &detail::any_executor_base::query_fn<Ex, T4>, \ + &detail::any_executor_base::require_fn<any_executor, Ex, T4>, \ + &detail::any_executor_base::prefer_fn<any_executor, Ex, T4> \ + } +#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 \ + ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4, \ + { \ + &detail::any_executor_base::query_fn<Ex, T5>, \ + &detail::any_executor_base::require_fn<any_executor, Ex, T5>, \ + &detail::any_executor_base::prefer_fn<any_executor, Ex, T5> \ + } +#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 \ + ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5, \ + { \ + &detail::any_executor_base::query_fn<Ex, T6>, \ + &detail::any_executor_base::require_fn<any_executor, Ex, T6>, \ + &detail::any_executor_base::prefer_fn<any_executor, Ex, T6> \ + } +#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 \ + ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6, \ + { \ + &detail::any_executor_base::query_fn<Ex, T7>, \ + &detail::any_executor_base::require_fn<any_executor, Ex, T7>, \ + &detail::any_executor_base::prefer_fn<any_executor, Ex, T7> \ + } +#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 \ + ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7, \ + { \ + &detail::any_executor_base::query_fn<Ex, T8>, \ + &detail::any_executor_base::require_fn<any_executor, Ex, T8>, \ + &detail::any_executor_base::prefer_fn<any_executor, Ex, T8> \ + } + +#if defined(ASIO_HAS_MOVE) + +# define ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \ + any_executor(any_executor&& other) ASIO_NOEXCEPT \ + : detail::any_executor_base( \ + static_cast<any_executor_base&&>( \ + static_cast<any_executor_base&>(other))), \ + prop_fns_(other.prop_fns_) \ + { \ + other.prop_fns_ = prop_fns_table<void>(); \ + } \ + \ + any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT \ + { \ + if (this != &other) \ + { \ + prop_fns_ = other.prop_fns_; \ + detail::any_executor_base::operator=( \ + static_cast<detail::any_executor_base&&>( \ + static_cast<detail::any_executor_base&>(other))); \ + } \ + return *this; \ + } \ + /**/ +#else // defined(ASIO_HAS_MOVE) + +# define ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS + +#endif // defined(ASIO_HAS_MOVE) + +#define ASIO_PRIVATE_ANY_EXECUTOR_DEF(n) \ + template <ASIO_VARIADIC_TPARAMS(n)> \ + class any_executor<ASIO_VARIADIC_TARGS(n)> : \ + public detail::any_executor_base, \ + public detail::any_executor_context< \ + any_executor<ASIO_VARIADIC_TARGS(n)>, \ + typename detail::supportable_properties< \ + 0, void(ASIO_VARIADIC_TARGS(n))>::find_context_as_property> \ + { \ + public: \ + any_executor() ASIO_NOEXCEPT \ + : detail::any_executor_base(), \ + prop_fns_(prop_fns_table<void>()) \ + { \ + } \ + \ + any_executor(nullptr_t) ASIO_NOEXCEPT \ + : detail::any_executor_base(), \ + prop_fns_(prop_fns_table<void>()) \ + { \ + } \ + \ + template <ASIO_EXECUTION_EXECUTOR Executor> \ + any_executor(Executor ex, \ + typename enable_if< \ + conditional< \ + !is_same<Executor, any_executor>::value \ + && !is_base_of<detail::any_executor_base, Executor>::value, \ + detail::is_valid_target_executor< \ + Executor, void(ASIO_VARIADIC_TARGS(n))>, \ + false_type \ + >::type::value \ + >::type* = 0) \ + : detail::any_executor_base(ASIO_MOVE_CAST( \ + Executor)(ex), false_type()), \ + prop_fns_(prop_fns_table<Executor>()) \ + { \ + } \ + \ + any_executor(const any_executor& other) ASIO_NOEXCEPT \ + : detail::any_executor_base( \ + static_cast<const detail::any_executor_base&>(other)), \ + prop_fns_(other.prop_fns_) \ + { \ + } \ + \ + any_executor(any_executor<> other) \ + : detail::any_executor_base(ASIO_MOVE_CAST( \ + any_executor<>)(other), true_type()), \ + prop_fns_(prop_fns_table<any_executor<> >()) \ + { \ + } \ + \ + template <typename OtherAnyExecutor> \ + any_executor(OtherAnyExecutor other, \ + typename enable_if< \ + conditional< \ + !is_same<OtherAnyExecutor, any_executor>::value \ + && is_base_of<detail::any_executor_base, \ + OtherAnyExecutor>::value, \ + typename detail::supportable_properties< \ + 0, void(ASIO_VARIADIC_TARGS(n))>::template \ + is_valid_target<OtherAnyExecutor>, \ + false_type \ + >::type::value \ + >::type* = 0) \ + : detail::any_executor_base(ASIO_MOVE_CAST( \ + OtherAnyExecutor)(other), true_type()), \ + prop_fns_(prop_fns_table<OtherAnyExecutor>()) \ + { \ + } \ + \ + any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT \ + { \ + if (this != &other) \ + { \ + prop_fns_ = other.prop_fns_; \ + detail::any_executor_base::operator=( \ + static_cast<const detail::any_executor_base&>(other)); \ + } \ + return *this; \ + } \ + \ + any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT \ + { \ + prop_fns_ = prop_fns_table<void>(); \ + detail::any_executor_base::operator=(p); \ + return *this; \ + } \ + \ + ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \ + \ + void swap(any_executor& other) ASIO_NOEXCEPT \ + { \ + if (this != &other) \ + { \ + detail::any_executor_base::swap( \ + static_cast<detail::any_executor_base&>(other)); \ + const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_; \ + other.prop_fns_ = prop_fns_; \ + prop_fns_ = tmp_prop_fns; \ + } \ + } \ + \ + using detail::any_executor_base::execute; \ + using detail::any_executor_base::target; \ + using detail::any_executor_base::target_type; \ + using detail::any_executor_base::operator unspecified_bool_type; \ + using detail::any_executor_base::operator!; \ + \ + bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT \ + { \ + return any_executor_base::equality_helper(other); \ + } \ + \ + template <typename AnyExecutor1, typename AnyExecutor2> \ + friend typename enable_if< \ + is_base_of<any_executor, AnyExecutor1>::value \ + || is_base_of<any_executor, AnyExecutor2>::value, \ + bool \ + >::type operator==(const AnyExecutor1& a, \ + const AnyExecutor2& b) ASIO_NOEXCEPT \ + { \ + return static_cast<const any_executor&>(a).equality_helper(b); \ + } \ + \ + template <typename AnyExecutor> \ + friend typename enable_if< \ + is_same<AnyExecutor, any_executor>::value, \ + bool \ + >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT \ + { \ + return !a; \ + } \ + \ + template <typename AnyExecutor> \ + friend typename enable_if< \ + is_same<AnyExecutor, any_executor>::value, \ + bool \ + >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT \ + { \ + return !b; \ + } \ + \ + template <typename AnyExecutor1, typename AnyExecutor2> \ + friend typename enable_if< \ + is_base_of<any_executor, AnyExecutor1>::value \ + || is_base_of<any_executor, AnyExecutor2>::value, \ + bool \ + >::type operator!=(const AnyExecutor1& a, \ + const AnyExecutor2& b) ASIO_NOEXCEPT \ + { \ + return !static_cast<const any_executor&>(a).equality_helper(b); \ + } \ + \ + template <typename AnyExecutor> \ + friend typename enable_if< \ + is_same<AnyExecutor, any_executor>::value, \ + bool \ + >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT \ + { \ + return !!a; \ + } \ + \ + template <typename AnyExecutor> \ + friend typename enable_if< \ + is_same<AnyExecutor, any_executor>::value, \ + bool \ + >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT \ + { \ + return !!b; \ + } \ + \ + template <typename T> \ + struct find_convertible_property : \ + detail::supportable_properties< \ + 0, void(ASIO_VARIADIC_TARGS(n))>::template \ + find_convertible_property<T> {}; \ + \ + template <typename Property> \ + void query(const Property& p, \ + typename enable_if< \ + is_same< \ + typename find_convertible_property<Property>::query_result_type, \ + void \ + >::value \ + >::type* = 0) const \ + { \ + typedef find_convertible_property<Property> found; \ + prop_fns_[found::index].query(0, object_fns_->target(*this), \ + &static_cast<const typename found::type&>(p)); \ + } \ + \ + template <typename Property> \ + typename find_convertible_property<Property>::query_result_type \ + query(const Property& p, \ + typename enable_if< \ + !is_same< \ + typename find_convertible_property<Property>::query_result_type, \ + void \ + >::value \ + && \ + is_reference< \ + typename find_convertible_property<Property>::query_result_type \ + >::value \ + >::type* = 0) const \ + { \ + typedef find_convertible_property<Property> found; \ + typename remove_reference< \ + typename found::query_result_type>::type* result; \ + prop_fns_[found::index].query(&result, object_fns_->target(*this), \ + &static_cast<const typename found::type&>(p)); \ + return *result; \ + } \ + \ + template <typename Property> \ + typename find_convertible_property<Property>::query_result_type \ + query(const Property& p, \ + typename enable_if< \ + !is_same< \ + typename find_convertible_property<Property>::query_result_type, \ + void \ + >::value \ + && \ + is_scalar< \ + typename find_convertible_property<Property>::query_result_type \ + >::value \ + >::type* = 0) const \ + { \ + typedef find_convertible_property<Property> found; \ + typename found::query_result_type result; \ + prop_fns_[found::index].query(&result, object_fns_->target(*this), \ + &static_cast<const typename found::type&>(p)); \ + return result; \ + } \ + \ + template <typename Property> \ + typename find_convertible_property<Property>::query_result_type \ + query(const Property& p, \ + typename enable_if< \ + !is_same< \ + typename find_convertible_property<Property>::query_result_type, \ + void \ + >::value \ + && \ + !is_reference< \ + typename find_convertible_property<Property>::query_result_type \ + >::value \ + && \ + !is_scalar< \ + typename find_convertible_property<Property>::query_result_type \ + >::value \ + >::type* = 0) const \ + { \ + typedef find_convertible_property<Property> found; \ + typename found::query_result_type* result; \ + prop_fns_[found::index].query(&result, object_fns_->target(*this), \ + &static_cast<const typename found::type&>(p)); \ + return *asio::detail::scoped_ptr< \ + typename found::query_result_type>(result); \ + } \ + \ + template <typename T> \ + struct find_convertible_requirable_property : \ + detail::supportable_properties< \ + 0, void(ASIO_VARIADIC_TARGS(n))>::template \ + find_convertible_requirable_property<T> {}; \ + \ + template <typename Property> \ + any_executor require(const Property& p, \ + typename enable_if< \ + find_convertible_requirable_property<Property>::value \ + >::type* = 0) const \ + { \ + typedef find_convertible_requirable_property<Property> found; \ + return prop_fns_[found::index].require(object_fns_->target(*this), \ + &static_cast<const typename found::type&>(p)); \ + } \ + \ + template <typename T> \ + struct find_convertible_preferable_property : \ + detail::supportable_properties< \ + 0, void(ASIO_VARIADIC_TARGS(n))>::template \ + find_convertible_preferable_property<T> {}; \ + \ + template <typename Property> \ + any_executor prefer(const Property& p, \ + typename enable_if< \ + find_convertible_preferable_property<Property>::value \ + >::type* = 0) const \ + { \ + typedef find_convertible_preferable_property<Property> found; \ + return prop_fns_[found::index].prefer(object_fns_->target(*this), \ + &static_cast<const typename found::type&>(p)); \ + } \ + \ + template <typename Ex> \ + static const prop_fns<any_executor>* prop_fns_table() \ + { \ + static const prop_fns<any_executor> fns[] = \ + { \ + ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \ + }; \ + return fns; \ + } \ + \ + const prop_fns<any_executor>* prop_fns_; \ + typedef detail::supportable_properties<0, \ + void(ASIO_VARIADIC_TARGS(n))> supportable_properties_type; \ + }; \ + \ + template <ASIO_VARIADIC_TPARAMS(n)> \ + inline void swap(any_executor<ASIO_VARIADIC_TARGS(n)>& a, \ + any_executor<ASIO_VARIADIC_TARGS(n)>& b) ASIO_NOEXCEPT \ + { \ + return a.swap(b); \ + } \ + /**/ + ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_DEF) +#undef ASIO_PRIVATE_ANY_EXECUTOR_DEF +#undef ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS +#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS +#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 +#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 +#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 +#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 +#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 +#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 +#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 +#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 + +#endif // if defined(ASIO_HAS_VARIADIC_TEMPLATES) + +} // namespace execution +namespace traits { + +#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename... SupportableProperties> +struct equality_comparable<execution::any_executor<SupportableProperties...> > +{ + static const bool is_valid = true; + static const bool is_noexcept = true; +}; + +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <> +struct equality_comparable<execution::any_executor<> > +{ + static const bool is_valid = true; + static const bool is_noexcept = true; +}; + +#define ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF(n) \ + template <ASIO_VARIADIC_TPARAMS(n)> \ + struct equality_comparable< \ + execution::any_executor<ASIO_VARIADIC_TARGS(n)> > \ + { \ + static const bool is_valid = true; \ + static const bool is_noexcept = true; \ + }; \ + /**/ + ASIO_VARIADIC_GENERATE( + ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF) +#undef ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF + +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) +#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename F, typename... SupportableProperties> +struct execute_member<execution::any_executor<SupportableProperties...>, F> +{ + static const bool is_valid = true; + static const bool is_noexcept = false; + typedef void result_type; +}; + +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename F> +struct execute_member<execution::any_executor<>, F> +{ + static const bool is_valid = true; + static const bool is_noexcept = false; + typedef void result_type; +}; + +#define ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF(n) \ + template <typename F, ASIO_VARIADIC_TPARAMS(n)> \ + struct execute_member< \ + execution::any_executor<ASIO_VARIADIC_TARGS(n)>, F> \ + { \ + static const bool is_valid = true; \ + static const bool is_noexcept = false; \ + typedef void result_type; \ + }; \ + /**/ + ASIO_VARIADIC_GENERATE( + ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF) +#undef ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF + +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) +#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename Prop, typename... SupportableProperties> +struct query_member< + execution::any_executor<SupportableProperties...>, Prop, + typename enable_if< + execution::detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_property<Prop>::value + >::type> +{ + static const bool is_valid = true; + static const bool is_noexcept = false; + typedef typename execution::detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_property<Prop>::query_result_type result_type; +}; + +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +#define ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF(n) \ + template <typename Prop, ASIO_VARIADIC_TPARAMS(n)> \ + struct query_member< \ + execution::any_executor<ASIO_VARIADIC_TARGS(n)>, Prop, \ + typename enable_if< \ + execution::detail::supportable_properties< \ + 0, void(ASIO_VARIADIC_TARGS(n))>::template \ + find_convertible_property<Prop>::value \ + >::type> \ + { \ + static const bool is_valid = true; \ + static const bool is_noexcept = false; \ + typedef typename execution::detail::supportable_properties< \ + 0, void(ASIO_VARIADIC_TARGS(n))>::template \ + find_convertible_property<Prop>::query_result_type result_type; \ + }; \ + /**/ + ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF) +#undef ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF + +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) +#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename Prop, typename... SupportableProperties> +struct require_member< + execution::any_executor<SupportableProperties...>, Prop, + typename enable_if< + execution::detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_requirable_property<Prop>::value + >::type> +{ + static const bool is_valid = true; + static const bool is_noexcept = false; + typedef execution::any_executor<SupportableProperties...> result_type; +}; + +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +#define ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF(n) \ + template <typename Prop, ASIO_VARIADIC_TPARAMS(n)> \ + struct require_member< \ + execution::any_executor<ASIO_VARIADIC_TARGS(n)>, Prop, \ + typename enable_if< \ + execution::detail::supportable_properties< \ + 0, void(ASIO_VARIADIC_TARGS(n))>::template \ + find_convertible_requirable_property<Prop>::value \ + >::type> \ + { \ + static const bool is_valid = true; \ + static const bool is_noexcept = false; \ + typedef execution::any_executor<ASIO_VARIADIC_TARGS(n)> result_type; \ + }; \ + /**/ + ASIO_VARIADIC_GENERATE( + ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF) +#undef ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF + +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) +#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) +#if defined(ASIO_HAS_VARIADIC_TEMPLATES) + +template <typename Prop, typename... SupportableProperties> +struct prefer_member< + execution::any_executor<SupportableProperties...>, Prop, + typename enable_if< + execution::detail::supportable_properties< + 0, void(SupportableProperties...)>::template + find_convertible_preferable_property<Prop>::value + >::type> +{ + static const bool is_valid = true; + static const bool is_noexcept = false; + typedef execution::any_executor<SupportableProperties...> result_type; +}; + +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) + +#define ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF(n) \ + template <typename Prop, ASIO_VARIADIC_TPARAMS(n)> \ + struct prefer_member< \ + execution::any_executor<ASIO_VARIADIC_TARGS(n)>, Prop, \ + typename enable_if< \ + execution::detail::supportable_properties< \ + 0, void(ASIO_VARIADIC_TARGS(n))>::template \ + find_convertible_preferable_property<Prop>::value \ + >::type> \ + { \ + static const bool is_valid = true; \ + static const bool is_noexcept = false; \ + typedef execution::any_executor<ASIO_VARIADIC_TARGS(n)> result_type; \ + }; \ + /**/ + ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF) +#undef ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF + +#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) +#endif // !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) + +} // namespace traits + +#endif // defined(GENERATING_DOCUMENTATION) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXECUTION_ANY_EXECUTOR_HPP |