2347 lines
69 KiB
C++
2347 lines
69 KiB
C++
//
|
|
// 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_same<AnyExecutor1, any_executor>::value
|
|
|| is_same<AnyExecutor2, any_executor>::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_same<AnyExecutor1, any_executor>::value
|
|
|| is_same<AnyExecutor2, any_executor>::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_same<AnyExecutor1, any_executor>::value
|
|
|| is_same<AnyExecutor2, any_executor>::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_same<AnyExecutor1, any_executor>::value
|
|
|| is_same<AnyExecutor2, any_executor>::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_same<AnyExecutor1, any_executor>::value \
|
|
|| is_same<AnyExecutor2, any_executor>::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_same<AnyExecutor1, any_executor>::value \
|
|
|| is_same<AnyExecutor2, any_executor>::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
|