// // execution/any_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2023 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 #include #include "asio/detail/assert.hpp" #include "asio/detail/atomic_count.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 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 any_executor(any_executor e); /// Construct to point to the same target as another any_executor. template any_executor(std::nothrow_t, any_executor e) noexcept; /// Construct to point to the same target as another any_executor. any_executor(std::nothrow_t, const any_executor& e) noexcept; /// Construct to point to the same target as another any_executor. any_executor(std::nothrow_t, any_executor&& e) noexcept; /// Construct a polymorphic wrapper for the specified executor. template any_executor(Executor e); /// Construct a polymorphic wrapper for the specified executor. template any_executor(std::nothrow_t, Executor e) noexcept; /// 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 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 ex = ...; * auto ex2 = asio::requre(ex, execution::blocking.possibly); @endcode */ template 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 ex = ...; * auto ex2 = asio::prefer(ex, execution::blocking.possibly); @endcode */ template 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 ex = ...; * size_t n = asio::query(ex, execution::occupancy); @endcode */ template typename Property::polymorphic_query_result_type query(Property) const; /// Execute the function on the target executor. /** * Throws asio::bad_executor if the polymorphic wrapper has no target. */ template 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 execution::context_as, for some type U. */ 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 Executor* target() noexcept; /// Get a pointer to the target executor. template const Executor* target() const noexcept; }; /// Equality operator. /** * @relates any_executor */ template bool operator==(const any_executor& a, const any_executor& b) noexcept; /// Equality operator. /** * @relates any_executor */ template bool operator==(const any_executor& a, nullptr_t) noexcept; /// Equality operator. /** * @relates any_executor */ template bool operator==(nullptr_t, const any_executor& b) noexcept; /// Inequality operator. /** * @relates any_executor */ template bool operator!=(const any_executor& a, const any_executor& b) noexcept; /// Inequality operator. /** * @relates any_executor */ template bool operator!=(const any_executor& a, nullptr_t) noexcept; /// Inequality operator. /** * @relates any_executor */ template bool operator!=(nullptr_t, const any_executor& 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 class any_executor; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template class any_executor; #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL) template 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 struct is_requirable : false_type {}; template struct is_requirable::type> : true_type {}; template struct is_preferable : false_type {}; template struct is_preferable::type> : true_type {}; // Trait used to detect context_as property, for backward compatibility. template struct is_context_as : false_type {}; template struct is_context_as > : 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 struct supportable_properties; template struct supportable_properties { template struct is_valid_target : integral_constant::value ? can_require::value : true ) && ( is_preferable::value ? can_prefer::value : true ) && ( !is_requirable::value && !is_preferable::value ? can_query::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 struct find_convertible_property : conditional< is_same::value || is_convertible::value, found, not_found >::type {}; template struct find_convertible_requirable_property : conditional< is_requirable::value && (is_same::value || is_convertible::value), found, not_found >::type {}; template struct find_convertible_preferable_property : conditional< is_preferable::value && (is_same::value || is_convertible::value), found, not_found >::type {}; struct find_context_as_property : conditional< is_context_as::value, found, not_found >::type {}; }; #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template struct supportable_properties { template struct is_valid_target : integral_constant::template is_valid_target::value && supportable_properties::template is_valid_target::value ) > { }; template struct find_convertible_property : conditional< is_convertible::value, typename supportable_properties::found, typename supportable_properties::template find_convertible_property >::type {}; template struct find_convertible_requirable_property : conditional< is_requirable::value && is_convertible::value, typename supportable_properties::found, typename supportable_properties::template find_convertible_requirable_property >::type {}; template struct find_convertible_preferable_property : conditional< is_preferable::value && is_convertible::value, typename supportable_properties::found, typename supportable_properties::template find_convertible_preferable_property >::type {}; struct find_context_as_property : conditional< is_context_as::value, typename supportable_properties::found, typename supportable_properties::find_context_as_property >::type {}; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) #define ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF(n) \ template \ struct supportable_properties \ { \ template \ struct is_valid_target : integral_constant::template is_valid_target::value \ && \ supportable_properties::template \ is_valid_target::value \ ) \ > \ { \ }; \ \ template \ struct find_convertible_property : \ conditional< \ is_convertible::value, \ typename supportable_properties::found, \ typename supportable_properties::template \ find_convertible_property \ >::type {}; \ \ template \ struct find_convertible_requirable_property : \ conditional< \ is_requirable::value \ && is_convertible::value, \ typename supportable_properties::found, \ typename supportable_properties::template \ find_convertible_requirable_property \ >::type {}; \ \ template \ struct find_convertible_preferable_property : \ conditional< \ is_preferable::value \ && is_convertible::value, \ typename supportable_properties::found, \ typename supportable_properties::template \ find_convertible_preferable_property \ >::type {}; \ \ struct find_context_as_property : \ conditional< \ is_context_as::value, \ typename supportable_properties::found, \ typename supportable_properties::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 struct is_valid_target_executor : conditional< is_executor::value, typename supportable_properties<0, Props>::template is_valid_target, false_type >::type { }; template struct is_valid_target_executor : false_type { }; class shared_target_executor { public: template shared_target_executor(ASIO_MOVE_ARG(E) e, typename decay::type*& target) { impl::type>* i = new impl::type>(ASIO_MOVE_CAST(E)(e)); target = &i->ex_; impl_ = i; } template shared_target_executor(std::nothrow_t, ASIO_MOVE_ARG(E) e, typename decay::type*& target) ASIO_NOEXCEPT { impl::type>* i = new (std::nothrow) impl::type>( ASIO_MOVE_CAST(E)(e)); target = i ? &i->ex_ : 0; impl_ = i; } shared_target_executor( const shared_target_executor& other) ASIO_NOEXCEPT : impl_(other.impl_) { if (impl_) asio::detail::ref_count_up(impl_->ref_count_); } shared_target_executor& operator=( const shared_target_executor& other) ASIO_NOEXCEPT { impl_ = other.impl_; if (impl_) asio::detail::ref_count_up(impl_->ref_count_); return *this; } #if defined(ASIO_HAS_MOVE) shared_target_executor( shared_target_executor&& other) ASIO_NOEXCEPT : impl_(other.impl_) { other.impl_ = 0; } shared_target_executor& operator=( shared_target_executor&& other) ASIO_NOEXCEPT { impl_ = other.impl_; other.impl_ = 0; return *this; } #endif // defined(ASIO_HAS_MOVE) ~shared_target_executor() { if (impl_) if (asio::detail::ref_count_down(impl_->ref_count_)) delete impl_; } void* get() const ASIO_NOEXCEPT { return impl_ ? impl_->get() : 0; } private: struct impl_base { impl_base() : ref_count_(1) {} virtual ~impl_base() {} virtual void* get() = 0; asio::detail::atomic_count ref_count_; }; template struct impl : impl_base { impl(Executor ex) : ex_(ASIO_MOVE_CAST(Executor)(ex)) {} virtual void* get() { return &ex_; } Executor ex_; }; impl_base* impl_; }; class any_executor_base { public: any_executor_base() ASIO_NOEXCEPT : object_fns_(0), target_(0), target_fns_(0) { } template any_executor_base(Executor ex, false_type) : target_fns_(target_fns_table( any_executor_base::query_blocking(ex, can_query()) == execution::blocking.always)) { any_executor_base::construct_object(ex, integral_constant::value <= alignment_of::value >()); } template any_executor_base(std::nothrow_t, Executor ex, false_type) ASIO_NOEXCEPT : target_fns_(target_fns_table( any_executor_base::query_blocking(ex, can_query()) == execution::blocking.always)) { any_executor_base::construct_object(std::nothrow, ex, integral_constant::value <= alignment_of::value >()); if (target_ == 0) { object_fns_ = 0; target_fns_ = 0; } } template any_executor_base(Executor other, true_type) : object_fns_(object_fns_table()), target_fns_(other.target_fns_) { Executor* p = 0; new (&object_) shared_target_executor( ASIO_MOVE_CAST(Executor)(other), p); target_ = p->template target(); } template any_executor_base(std::nothrow_t, Executor other, true_type) ASIO_NOEXCEPT : object_fns_(object_fns_table()), target_fns_(other.target_fns_) { Executor* p = 0; new (&object_) shared_target_executor( std::nothrow, ASIO_MOVE_CAST(Executor)(other), p); if (p) target_ = p->template target(); else { target_ = 0; object_fns_ = 0; target_fns_ = 0; } } any_executor_base(const any_executor_base& other) ASIO_NOEXCEPT { if (!!other) { object_fns_ = other.object_fns_; target_fns_ = other.target_fns_; object_fns_->copy(*this, other); } else { object_fns_ = 0; target_ = 0; target_fns_ = 0; } } ~any_executor_base() ASIO_NOEXCEPT { if (!!*this) object_fns_->destroy(*this); } any_executor_base& operator=( const any_executor_base& other) ASIO_NOEXCEPT { if (this != &other) { if (!!*this) object_fns_->destroy(*this); if (!!other) { object_fns_ = other.object_fns_; target_fns_ = other.target_fns_; object_fns_->copy(*this, other); } else { object_fns_ = 0; target_ = 0; target_fns_ = 0; } } return *this; } any_executor_base& operator=(nullptr_t) ASIO_NOEXCEPT { if (target_) object_fns_->destroy(*this); target_ = 0; object_fns_ = 0; target_fns_ = 0; return *this; } #if defined(ASIO_HAS_MOVE) any_executor_base(any_executor_base&& other) ASIO_NOEXCEPT { if (other.target_) { object_fns_ = other.object_fns_; target_fns_ = other.target_fns_; other.object_fns_ = 0; other.target_fns_ = 0; object_fns_->move(*this, other); other.target_ = 0; } else { object_fns_ = 0; target_ = 0; target_fns_ = 0; } } any_executor_base& operator=( any_executor_base&& other) ASIO_NOEXCEPT { if (this != &other) { if (!!*this) object_fns_->destroy(*this); if (!!other) { object_fns_ = other.object_fns_; target_fns_ = other.target_fns_; other.object_fns_ = 0; other.target_fns_ = 0; object_fns_->move(*this, other); other.target_ = 0; } else { object_fns_ = 0; target_ = 0; target_fns_ = 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 void execute(ASIO_MOVE_ARG(F) f) const { if (target_) { if (target_fns_->blocking_execute != 0) { asio::detail::non_const_lvalue f2(f); target_fns_->blocking_execute(*this, function_view(f2.value)); } else { target_fns_->execute(*this, function(ASIO_MOVE_CAST(F)(f), std::allocator())); } } else { bad_executor ex; asio::detail::throw_exception(ex); } } template Executor* target() { return target_ && (is_same::value || target_fns_->target_type() == target_type_ex()) ? static_cast(target_) : 0; } template const Executor* target() const { return target_ && (is_same::value || target_fns_->target_type() == target_type_ex()) ? static_cast(target_) : 0; } #if !defined(ASIO_NO_TYPEID) const std::type_info& target_type() const { return target_ ? target_fns_->target_type() : typeid(void); } #else // !defined(ASIO_NO_TYPEID) const void* target_type() const { return target_ ? target_fns_->target_type() : 0; } #endif // !defined(ASIO_NO_TYPEID) 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 Ex& object() { return *static_cast(static_cast(&object_)); } template const Ex& object() const { return *static_cast(static_cast(&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_shared(any_executor_base& ex) { typedef shared_target_executor type; ex.object().~type(); } static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2) { typedef shared_target_executor type; new (&ex1.object_) type(ex2.object()); ex1.target_ = ex2.target_; } static void move_shared(any_executor_base& ex1, any_executor_base& ex2) { typedef shared_target_executor type; new (&ex1.object_) type(ASIO_MOVE_CAST(type)(ex2.object())); ex1.target_ = ex2.target_; ex2.object().~type(); } static const void* target_shared(const any_executor_base& ex) { typedef shared_target_executor type; return ex.object().get(); } template static const object_fns* object_fns_table( typename enable_if< is_same::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 static void destroy_object(any_executor_base& ex) { ex.object().~Obj(); } template static void copy_object(any_executor_base& ex1, const any_executor_base& ex2) { new (&ex1.object_) Obj(ex2.object()); ex1.target_ = &ex1.object(); } template static void move_object(any_executor_base& ex1, any_executor_base& ex2) { new (&ex1.object_) Obj(ASIO_MOVE_CAST(Obj)(ex2.object())); ex1.target_ = &ex1.object(); ex2.object().~Obj(); } template static const void* target_object(const any_executor_base& ex) { return &ex.object(); } template static const object_fns* object_fns_table( typename enable_if< !is_same::value && !is_same::value >::type* = 0) { static const object_fns fns = { &any_executor_base::destroy_object, &any_executor_base::copy_object, &any_executor_base::move_object, &any_executor_base::target_object }; 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) template static const std::type_info& target_type_ex() { return typeid(Ex); } #else // !defined(ASIO_NO_TYPEID) template static const void* target_type_ex() { static int unique_id; return &unique_id; } #endif // !defined(ASIO_NO_TYPEID) template static bool equal_ex(const any_executor_base& ex1, const any_executor_base& ex2) { const Ex* p1 = ex1.target(); const Ex* p2 = ex2.target(); ASIO_ASSUME(p1 != 0 && p2 != 0); return *p1 == *p2; } template static void execute_ex(const any_executor_base& ex, ASIO_MOVE_ARG(function) f) { const Ex* p = ex.target(); ASIO_ASSUME(p != 0); #if defined(ASIO_NO_DEPRECATED) p->execute(ASIO_MOVE_CAST(function)(f)); #else // defined(ASIO_NO_DEPRECATED) execution::execute(*p, ASIO_MOVE_CAST(function)(f)); #endif // defined(ASIO_NO_DEPRECATED) } template static void blocking_execute_ex(const any_executor_base& ex, function_view f) { const Ex* p = ex.target(); ASIO_ASSUME(p != 0); #if defined(ASIO_NO_DEPRECATED) p->execute(f); #else // defined(ASIO_NO_DEPRECATED) execution::execute(*p, f); #endif // defined(ASIO_NO_DEPRECATED) } template static const target_fns* target_fns_table(bool is_always_blocking, typename enable_if< !is_same::value >::type* = 0) { static const target_fns fns_with_execute = { &any_executor_base::target_type_ex, &any_executor_base::equal_ex, &any_executor_base::execute_ex, 0 }; static const target_fns fns_with_blocking_execute = { &any_executor_base::target_type_ex, &any_executor_base::equal_ex, 0, &any_executor_base::blocking_execute_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 static void query_fn_non_void(void*, const void* ex, const void* prop, typename enable_if< asio::can_query::value && is_same::value >::type*) { asio::query(*static_cast(ex), *static_cast(prop)); } template static void query_fn_non_void(void*, const void*, const void*, typename enable_if< !asio::can_query::value && is_same::value >::type*) { } template static void query_fn_non_void(void* result, const void* ex, const void* prop, typename enable_if< asio::can_query::value && !is_same::value && is_reference::value >::type*) { *static_cast::type**>(result) = &static_cast( asio::query(*static_cast(ex), *static_cast(prop))); } template static void query_fn_non_void(void*, const void*, const void*, typename enable_if< !asio::can_query::value && !is_same::value && is_reference::value >::type*) { std::terminate(); // Combination should not be possible. } template static void query_fn_non_void(void* result, const void* ex, const void* prop, typename enable_if< asio::can_query::value && !is_same::value && is_scalar::value >::type*) { *static_cast(result) = static_cast( asio::query(*static_cast(ex), *static_cast(prop))); } template static void query_fn_non_void(void* result, const void*, const void*, typename enable_if< !asio::can_query::value && !is_same::value && is_scalar::value >::type*) { *static_cast(result) = typename Prop::polymorphic_query_result_type(); } template static void query_fn_non_void(void* result, const void* ex, const void* prop, typename enable_if< asio::can_query::value && !is_same::value && !is_reference::value && !is_scalar::value >::type*) { *static_cast(result) = new typename Prop::polymorphic_query_result_type( asio::query(*static_cast(ex), *static_cast(prop))); } template static void query_fn_non_void(void* result, const void*, const void*, ...) { *static_cast(result) = new typename Prop::polymorphic_query_result_type(); } template static void query_fn_impl(void* result, const void* ex, const void* prop, typename enable_if< is_same::value >::type*) { query_fn_void(result, ex, prop); } template static void query_fn_impl(void* result, const void* ex, const void* prop, typename enable_if< !is_same::value >::type*) { query_fn_non_void(result, ex, prop, 0); } template static void query_fn(void* result, const void* ex, const void* prop) { query_fn_impl(result, ex, prop, 0); } template static Poly require_fn_impl(const void*, const void*, typename enable_if< is_same::value >::type*) { bad_executor ex; asio::detail::throw_exception(ex); return Poly(); } template static Poly require_fn_impl(const void* ex, const void* prop, typename enable_if< !is_same::value && Prop::is_requirable >::type*) { return asio::require(*static_cast(ex), *static_cast(prop)); } template static Poly require_fn_impl(const void*, const void*, ...) { return Poly(); } template static Poly require_fn(const void* ex, const void* prop) { return require_fn_impl(ex, prop, 0); } template static Poly prefer_fn_impl(const void*, const void*, typename enable_if< is_same::value >::type*) { bad_executor ex; asio::detail::throw_exception(ex); return Poly(); } template static Poly prefer_fn_impl(const void* ex, const void* prop, typename enable_if< !is_same::value && Prop::is_preferable >::type*) { return asio::prefer(*static_cast(ex), *static_cast(prop)); } template static Poly prefer_fn_impl(const void*, const void*, ...) { return Poly(); } template static Poly prefer_fn(const void* ex, const void* prop) { return prefer_fn_impl(ex, prop, 0); } template 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 static execution::blocking_t query_blocking(const Executor& ex, true_type) { return asio::query(ex, execution::blocking); } template static execution::blocking_t query_blocking(const Executor&, false_type) { return execution::blocking_t(); } template void construct_object(Executor& ex, true_type) { object_fns_ = object_fns_table(); target_ = new (&object_) Executor(ASIO_MOVE_CAST(Executor)(ex)); } template void construct_object(Executor& ex, false_type) { object_fns_ = object_fns_table(); Executor* p = 0; new (&object_) shared_target_executor( ASIO_MOVE_CAST(Executor)(ex), p); target_ = p; } template void construct_object(std::nothrow_t, Executor& ex, true_type) ASIO_NOEXCEPT { object_fns_ = object_fns_table(); target_ = new (&object_) Executor(ASIO_MOVE_CAST(Executor)(ex)); } template void construct_object(std::nothrow_t, Executor& ex, false_type) ASIO_NOEXCEPT { object_fns_ = object_fns_table(); Executor* p = 0; new (&object_) shared_target_executor( std::nothrow, ASIO_MOVE_CAST(Executor)(ex), p); target_ = p; } /*private:*/public: // template friend class any_executor; typedef aligned_storage< sizeof(asio::detail::shared_ptr) + sizeof(void*), alignment_of >::value >::type object_type; object_type object_; const object_fns* object_fns_; void* target_; const target_fns* target_fns_; }; template struct any_executor_context { }; #if !defined(ASIO_NO_TS_EXECUTORS) template struct any_executor_context::type> { typename Property::query_result_type context() const { return static_cast(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 any_executor(Executor ex, typename enable_if< conditional< !is_same::value && !is_base_of::value, is_executor, false_type >::type::value >::type* = 0) : detail::any_executor_base( ASIO_MOVE_CAST(Executor)(ex), false_type()) { } template any_executor(std::nothrow_t, Executor ex, typename enable_if< conditional< !is_same::value && !is_base_of::value, is_executor, false_type >::type::value >::type* = 0) ASIO_NOEXCEPT : detail::any_executor_base(std::nothrow, ASIO_MOVE_CAST(Executor)(ex), false_type()) { } #if defined(ASIO_HAS_VARIADIC_TEMPLATES) template any_executor(any_executor other) : detail::any_executor_base( static_cast(other)) { } template any_executor(std::nothrow_t, any_executor other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast(other)) { } #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template any_executor(any_executor other) : detail::any_executor_base( static_cast(other)) { } template any_executor(std::nothrow_t, any_executor other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast(other)) { } #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) any_executor(const any_executor& other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast(other)) { } any_executor(std::nothrow_t, const any_executor& other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast(other)) { } any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT { if (this != &other) { detail::any_executor_base::operator=( static_cast(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( static_cast(other))) { } any_executor(std::nothrow_t, any_executor&& other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast( static_cast(other))) { } any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT { if (this != &other) { detail::any_executor_base::operator=( static_cast( static_cast(other))); } return *this; } #endif // defined(ASIO_HAS_MOVE) void swap(any_executor& other) ASIO_NOEXCEPT { detail::any_executor_base::swap( static_cast(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 friend typename enable_if< is_base_of::value || is_base_of::value, bool >::type operator==(const AnyExecutor1& a, const AnyExecutor2& b) ASIO_NOEXCEPT { return static_cast(a).equality_helper(b); } template friend typename enable_if< is_same::value, bool >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT { return !a; } template friend typename enable_if< is_same::value, bool >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT { return !b; } template friend typename enable_if< is_base_of::value || is_base_of::value, bool >::type operator!=(const AnyExecutor1& a, const AnyExecutor2& b) ASIO_NOEXCEPT { return !static_cast(a).equality_helper(b); } template friend typename enable_if< is_same::value, bool >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT { return !!a; } template friend typename enable_if< is_same::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 class any_executor : public detail::any_executor_base, public detail::any_executor_context< any_executor, 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()) { } any_executor(nullptr_t) ASIO_NOEXCEPT : detail::any_executor_base(), prop_fns_(prop_fns_table()) { } template any_executor(Executor ex, typename enable_if< conditional< !is_same::value && !is_base_of::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()) { } template any_executor(std::nothrow_t, Executor ex, typename enable_if< conditional< !is_same::value && !is_base_of::value, detail::is_valid_target_executor< Executor, void(SupportableProperties...)>, false_type >::type::value >::type* = 0) ASIO_NOEXCEPT : detail::any_executor_base(std::nothrow, ASIO_MOVE_CAST(Executor)(ex), false_type()), prop_fns_(prop_fns_table()) { if (this->template target() == 0) prop_fns_ = prop_fns_table(); } template any_executor(any_executor other, typename enable_if< conditional< !is_same< any_executor, any_executor >::value, typename detail::supportable_properties< 0, void(SupportableProperties...)>::template is_valid_target< any_executor >, false_type >::type::value >::type* = 0) : detail::any_executor_base(ASIO_MOVE_CAST( any_executor)(other), true_type()), prop_fns_(prop_fns_table >()) { } template any_executor(std::nothrow_t, any_executor other, typename enable_if< conditional< !is_same< any_executor, any_executor >::value, typename detail::supportable_properties< 0, void(SupportableProperties...)>::template is_valid_target< any_executor >, false_type >::type::value >::type* = 0) ASIO_NOEXCEPT : detail::any_executor_base(std::nothrow, ASIO_MOVE_CAST( any_executor)(other), true_type()), prop_fns_(prop_fns_table >()) { if (this->template target() == 0) prop_fns_ = prop_fns_table(); } any_executor(const any_executor& other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast(other)), prop_fns_(other.prop_fns_) { } any_executor(std::nothrow_t, const any_executor& other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast(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(other)); } return *this; } any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT { prop_fns_ = prop_fns_table(); 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( static_cast(other))), prop_fns_(other.prop_fns_) { other.prop_fns_ = prop_fns_table(); } any_executor(std::nothrow_t, any_executor&& other) ASIO_NOEXCEPT : detail::any_executor_base( static_cast( static_cast(other))), prop_fns_(other.prop_fns_) { other.prop_fns_ = prop_fns_table(); } any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT { if (this != &other) { prop_fns_ = other.prop_fns_; detail::any_executor_base::operator=( static_cast( static_cast(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(other)); const prop_fns* 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 friend typename enable_if< is_base_of::value || is_base_of::value, bool >::type operator==(const AnyExecutor1& a, const AnyExecutor2& b) ASIO_NOEXCEPT { return static_cast(a).equality_helper(b); } template friend typename enable_if< is_same::value, bool >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT { return !a; } template friend typename enable_if< is_same::value, bool >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT { return !b; } template friend typename enable_if< is_base_of::value || is_base_of::value, bool >::type operator!=(const AnyExecutor1& a, const AnyExecutor2& b) ASIO_NOEXCEPT { return !static_cast(a).equality_helper(b); } template friend typename enable_if< is_same::value, bool >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT { return !!a; } template friend typename enable_if< is_same::value, bool >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT { return !!b; } template struct find_convertible_property : detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_property {}; template void query(const Property& p, typename enable_if< is_same< typename find_convertible_property::query_result_type, void >::value >::type* = 0) const { if (!target_) { bad_executor ex; asio::detail::throw_exception(ex); } typedef find_convertible_property found; prop_fns_[found::index].query(0, object_fns_->target(*this), &static_cast(p)); } template typename find_convertible_property::query_result_type query(const Property& p, typename enable_if< !is_same< typename find_convertible_property::query_result_type, void >::value && is_reference< typename find_convertible_property::query_result_type >::value >::type* = 0) const { if (!target_) { bad_executor ex; asio::detail::throw_exception(ex); } typedef find_convertible_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(p)); return *result; } template typename find_convertible_property::query_result_type query(const Property& p, typename enable_if< !is_same< typename find_convertible_property::query_result_type, void >::value && is_scalar< typename find_convertible_property::query_result_type >::value >::type* = 0) const { if (!target_) { bad_executor ex; asio::detail::throw_exception(ex); } typedef find_convertible_property found; typename found::query_result_type result; prop_fns_[found::index].query(&result, object_fns_->target(*this), &static_cast(p)); return result; } template typename find_convertible_property::query_result_type query(const Property& p, typename enable_if< !is_same< typename find_convertible_property::query_result_type, void >::value && !is_reference< typename find_convertible_property::query_result_type >::value && !is_scalar< typename find_convertible_property::query_result_type >::value >::type* = 0) const { if (!target_) { bad_executor ex; asio::detail::throw_exception(ex); } typedef find_convertible_property found; typename found::query_result_type* result; prop_fns_[found::index].query(&result, object_fns_->target(*this), &static_cast(p)); return *asio::detail::scoped_ptr< typename found::query_result_type>(result); } template struct find_convertible_requirable_property : detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_requirable_property {}; template any_executor require(const Property& p, typename enable_if< find_convertible_requirable_property::value >::type* = 0) const { if (!target_) { bad_executor ex; asio::detail::throw_exception(ex); } typedef find_convertible_requirable_property found; return prop_fns_[found::index].require(object_fns_->target(*this), &static_cast(p)); } template struct find_convertible_preferable_property : detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_preferable_property {}; template any_executor prefer(const Property& p, typename enable_if< find_convertible_preferable_property::value >::type* = 0) const { if (!target_) { bad_executor ex; asio::detail::throw_exception(ex); } typedef find_convertible_preferable_property found; return prop_fns_[found::index].prefer(object_fns_->target(*this), &static_cast(p)); } //private: template static const prop_fns* prop_fns_table() { static const prop_fns 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* prop_fns_; }; template inline void swap(any_executor& a, any_executor& 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, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7, \ { \ &detail::any_executor_base::query_fn, \ &detail::any_executor_base::require_fn, \ &detail::any_executor_base::prefer_fn \ } #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( \ static_cast(other))), \ prop_fns_(other.prop_fns_) \ { \ other.prop_fns_ = prop_fns_table(); \ } \ \ any_executor(std::nothrow_t, any_executor&& other) ASIO_NOEXCEPT \ : detail::any_executor_base( \ static_cast( \ static_cast(other))), \ prop_fns_(other.prop_fns_) \ { \ other.prop_fns_ = prop_fns_table(); \ } \ \ any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT \ { \ if (this != &other) \ { \ prop_fns_ = other.prop_fns_; \ detail::any_executor_base::operator=( \ static_cast( \ static_cast(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 \ class any_executor : \ public detail::any_executor_base, \ public detail::any_executor_context< \ any_executor, \ 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()) \ { \ } \ \ any_executor(nullptr_t) ASIO_NOEXCEPT \ : detail::any_executor_base(), \ prop_fns_(prop_fns_table()) \ { \ } \ \ template \ any_executor(Executor ex, \ typename enable_if< \ conditional< \ !is_same::value \ && !is_base_of::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()) \ { \ } \ \ template \ any_executor(std::nothrow_t, Executor ex, \ typename enable_if< \ conditional< \ !is_same::value \ && !is_base_of::value, \ detail::is_valid_target_executor< \ Executor, void(ASIO_VARIADIC_TARGS(n))>, \ false_type \ >::type::value \ >::type* = 0) ASIO_NOEXCEPT \ : detail::any_executor_base(std::nothrow, \ ASIO_MOVE_CAST(Executor)(ex), false_type()), \ prop_fns_(prop_fns_table()) \ { \ if (this->template target() == 0) \ prop_fns_ = prop_fns_table(); \ } \ \ any_executor(const any_executor& other) ASIO_NOEXCEPT \ : detail::any_executor_base( \ static_cast(other)), \ prop_fns_(other.prop_fns_) \ { \ } \ \ any_executor(std::nothrow_t, \ const any_executor& other) ASIO_NOEXCEPT \ : detail::any_executor_base( \ static_cast(other)), \ prop_fns_(other.prop_fns_) \ { \ if (this->template target() == 0) \ prop_fns_ = prop_fns_table(); \ } \ \ any_executor(any_executor<> other) \ : detail::any_executor_base(ASIO_MOVE_CAST( \ any_executor<>)(other), true_type()), \ prop_fns_(prop_fns_table >()) \ { \ } \ \ any_executor(std::nothrow_t, any_executor<> other) ASIO_NOEXCEPT \ : detail::any_executor_base(std::nothrow, \ ASIO_MOVE_CAST(any_executor<>)(other), true_type()), \ prop_fns_(prop_fns_table >()) \ { \ if (this->template target() == 0) \ prop_fns_ = prop_fns_table(); \ } \ \ template \ any_executor(OtherAnyExecutor other, \ typename enable_if< \ conditional< \ !is_same::value \ && is_base_of::value, \ typename detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ is_valid_target, \ false_type \ >::type::value \ >::type* = 0) \ : detail::any_executor_base(ASIO_MOVE_CAST( \ OtherAnyExecutor)(other), true_type()), \ prop_fns_(prop_fns_table()) \ { \ } \ \ template \ any_executor(std::nothrow_t, OtherAnyExecutor other, \ typename enable_if< \ conditional< \ !is_same::value \ && is_base_of::value, \ typename detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ is_valid_target, \ false_type \ >::type::value \ >::type* = 0) ASIO_NOEXCEPT \ : detail::any_executor_base(std::nothrow, \ ASIO_MOVE_CAST(OtherAnyExecutor)(other), true_type()), \ prop_fns_(prop_fns_table()) \ { \ if (this->template target() == 0) \ prop_fns_ = prop_fns_table(); \ } \ \ any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT \ { \ if (this != &other) \ { \ prop_fns_ = other.prop_fns_; \ detail::any_executor_base::operator=( \ static_cast(other)); \ } \ return *this; \ } \ \ any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT \ { \ prop_fns_ = prop_fns_table(); \ 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(other)); \ const prop_fns* 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 \ friend typename enable_if< \ is_base_of::value \ || is_base_of::value, \ bool \ >::type operator==(const AnyExecutor1& a, \ const AnyExecutor2& b) ASIO_NOEXCEPT \ { \ return static_cast(a).equality_helper(b); \ } \ \ template \ friend typename enable_if< \ is_same::value, \ bool \ >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT \ { \ return !a; \ } \ \ template \ friend typename enable_if< \ is_same::value, \ bool \ >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT \ { \ return !b; \ } \ \ template \ friend typename enable_if< \ is_base_of::value \ || is_base_of::value, \ bool \ >::type operator!=(const AnyExecutor1& a, \ const AnyExecutor2& b) ASIO_NOEXCEPT \ { \ return !static_cast(a).equality_helper(b); \ } \ \ template \ friend typename enable_if< \ is_same::value, \ bool \ >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT \ { \ return !!a; \ } \ \ template \ friend typename enable_if< \ is_same::value, \ bool \ >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT \ { \ return !!b; \ } \ \ template \ struct find_convertible_property : \ detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_property {}; \ \ template \ void query(const Property& p, \ typename enable_if< \ is_same< \ typename find_convertible_property::query_result_type, \ void \ >::value \ >::type* = 0) const \ { \ if (!target_) \ { \ bad_executor ex; \ asio::detail::throw_exception(ex); \ } \ typedef find_convertible_property found; \ prop_fns_[found::index].query(0, object_fns_->target(*this), \ &static_cast(p)); \ } \ \ template \ typename find_convertible_property::query_result_type \ query(const Property& p, \ typename enable_if< \ !is_same< \ typename find_convertible_property::query_result_type, \ void \ >::value \ && \ is_reference< \ typename find_convertible_property::query_result_type \ >::value \ >::type* = 0) const \ { \ if (!target_) \ { \ bad_executor ex; \ asio::detail::throw_exception(ex); \ } \ typedef find_convertible_property found; \ typename remove_reference< \ typename found::query_result_type>::type* result; \ prop_fns_[found::index].query(&result, object_fns_->target(*this), \ &static_cast(p)); \ return *result; \ } \ \ template \ typename find_convertible_property::query_result_type \ query(const Property& p, \ typename enable_if< \ !is_same< \ typename find_convertible_property::query_result_type, \ void \ >::value \ && \ is_scalar< \ typename find_convertible_property::query_result_type \ >::value \ >::type* = 0) const \ { \ if (!target_) \ { \ bad_executor ex; \ asio::detail::throw_exception(ex); \ } \ typedef find_convertible_property found; \ typename found::query_result_type result; \ prop_fns_[found::index].query(&result, object_fns_->target(*this), \ &static_cast(p)); \ return result; \ } \ \ template \ typename find_convertible_property::query_result_type \ query(const Property& p, \ typename enable_if< \ !is_same< \ typename find_convertible_property::query_result_type, \ void \ >::value \ && \ !is_reference< \ typename find_convertible_property::query_result_type \ >::value \ && \ !is_scalar< \ typename find_convertible_property::query_result_type \ >::value \ >::type* = 0) const \ { \ if (!target_) \ { \ bad_executor ex; \ asio::detail::throw_exception(ex); \ } \ typedef find_convertible_property found; \ typename found::query_result_type* result; \ prop_fns_[found::index].query(&result, object_fns_->target(*this), \ &static_cast(p)); \ return *asio::detail::scoped_ptr< \ typename found::query_result_type>(result); \ } \ \ template \ struct find_convertible_requirable_property : \ detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_requirable_property {}; \ \ template \ any_executor require(const Property& p, \ typename enable_if< \ find_convertible_requirable_property::value \ >::type* = 0) const \ { \ if (!target_) \ { \ bad_executor ex; \ asio::detail::throw_exception(ex); \ } \ typedef find_convertible_requirable_property found; \ return prop_fns_[found::index].require(object_fns_->target(*this), \ &static_cast(p)); \ } \ \ template \ struct find_convertible_preferable_property : \ detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_preferable_property {}; \ \ template \ any_executor prefer(const Property& p, \ typename enable_if< \ find_convertible_preferable_property::value \ >::type* = 0) const \ { \ if (!target_) \ { \ bad_executor ex; \ asio::detail::throw_exception(ex); \ } \ typedef find_convertible_preferable_property found; \ return prop_fns_[found::index].prefer(object_fns_->target(*this), \ &static_cast(p)); \ } \ \ template \ static const prop_fns* prop_fns_table() \ { \ static const prop_fns fns[] = \ { \ ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \ }; \ return fns; \ } \ \ const prop_fns* prop_fns_; \ typedef detail::supportable_properties<0, \ void(ASIO_VARIADIC_TARGS(n))> supportable_properties_type; \ }; \ \ template \ inline void swap(any_executor& a, \ any_executor& 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 struct equality_comparable > { static const bool is_valid = true; static const bool is_noexcept = true; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template <> struct equality_comparable > { static const bool is_valid = true; static const bool is_noexcept = true; }; #define ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF(n) \ template \ struct equality_comparable< \ execution::any_executor > \ { \ 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 struct execute_member, F> { static const bool is_valid = true; static const bool is_noexcept = false; typedef void result_type; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) template struct execute_member, 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 \ struct execute_member< \ execution::any_executor, 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 struct query_member< execution::any_executor, Prop, typename enable_if< execution::detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_property::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::query_result_type result_type; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) #define ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF(n) \ template \ struct query_member< \ execution::any_executor, Prop, \ typename enable_if< \ execution::detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_property::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::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 struct require_member< execution::any_executor, Prop, typename enable_if< execution::detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_requirable_property::value >::type> { static const bool is_valid = true; static const bool is_noexcept = false; typedef execution::any_executor result_type; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) #define ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF(n) \ template \ struct require_member< \ execution::any_executor, Prop, \ typename enable_if< \ execution::detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_requirable_property::value \ >::type> \ { \ static const bool is_valid = true; \ static const bool is_noexcept = false; \ typedef execution::any_executor 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 struct prefer_member< execution::any_executor, Prop, typename enable_if< execution::detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_preferable_property::value >::type> { static const bool is_valid = true; static const bool is_noexcept = false; typedef execution::any_executor result_type; }; #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) #define ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF(n) \ template \ struct prefer_member< \ execution::any_executor, Prop, \ typename enable_if< \ execution::detail::supportable_properties< \ 0, void(ASIO_VARIADIC_TARGS(n))>::template \ find_convertible_preferable_property::value \ >::type> \ { \ static const bool is_valid = true; \ static const bool is_noexcept = false; \ typedef execution::any_executor 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