/usr/include/boost/asio/execution
Edit: /usr/include/boost/asio/execution/any_executor.hpp (70761B)
//
// execution/any_executor.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2020 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 BOOST_ASIO_EXECUTION_ANY_EXECUTOR_HPP
#define BOOST_ASIO_EXECUTION_ANY_EXECUTOR_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace boost {
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 a polymorphic wrapper for the specified executor.
template
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
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
* boost::asio::require and boost::asio::prefer customisation points.
*
* For example:
* @code execution::any_executor ex = ...;
* auto ex2 = boost::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
* boost::asio::prefer customisation point.
*
* For example:
* @code execution::any_executor ex = ...;
* auto ex2 = boost::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
* boost::asio::query customisation point.
*
* For example:
* @code execution::any_executor ex = ...;
* size_t n = boost::asio::query(ex, execution::occupancy); @endcode
*/
template
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 boost::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(BOOST_ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL)
#define BOOST_ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL
#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template
class any_executor;
#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template
class any_executor;
#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
#endif // !defined(BOOST_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
{
BOOST_ASIO_STATIC_CONSTEXPR(bool, value = true);
typedef Prop type;
typedef typename Prop::polymorphic_query_result_type query_result_type;
BOOST_ASIO_STATIC_CONSTEXPR(std::size_t, index = I);
};
struct not_found
{
BOOST_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(BOOST_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(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
#define BOOST_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 {}; \
}; \
/**/
BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF)
#undef BOOST_ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF
#endif // defined(BOOST_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
{
};
class any_executor_base
{
public:
any_executor_base() BOOST_ASIO_NOEXCEPT
: object_fns_(object_fns_table()),
target_(0),
target_fns_(target_fns_table())
{
}
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(Executor other, true_type)
: object_fns_(object_fns_table >()),
target_fns_(other.target_fns_)
{
boost::asio::detail::shared_ptr p =
boost::asio::detail::make_shared(
BOOST_ASIO_MOVE_CAST(Executor)(other));
target_ = p->template target();
new (&object_) boost::asio::detail::shared_ptr(
BOOST_ASIO_MOVE_CAST(boost::asio::detail::shared_ptr)(p));
}
any_executor_base(const any_executor_base& other) BOOST_ASIO_NOEXCEPT
: object_fns_(other.object_fns_),
target_fns_(other.target_fns_)
{
object_fns_->copy(*this, other);
}
~any_executor_base() BOOST_ASIO_NOEXCEPT
{
object_fns_->destroy(*this);
}
any_executor_base& operator=(
const any_executor_base& other) BOOST_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) BOOST_ASIO_NOEXCEPT
{
object_fns_->destroy(*this);
target_ = 0;
object_fns_ = object_fns_table();
target_fns_ = target_fns_table();
return *this;
}
#if defined(BOOST_ASIO_HAS_MOVE)
any_executor_base(any_executor_base&& other) BOOST_ASIO_NOEXCEPT
: object_fns_(other.object_fns_),
target_fns_(other.target_fns_)
{
other.object_fns_ = object_fns_table();
other.target_fns_ = target_fns_table();
object_fns_->move(*this, other);
other.target_ = 0;
}
any_executor_base& operator=(
any_executor_base&& other) BOOST_ASIO_NOEXCEPT
{
if (this != &other)
{
object_fns_->destroy(*this);
object_fns_ = other.object_fns_;
other.object_fns_ = object_fns_table();
target_fns_ = other.target_fns_;
other.target_fns_ = target_fns_table();
object_fns_->move(*this, other);
other.target_ = 0;
}
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
void swap(any_executor_base& other) BOOST_ASIO_NOEXCEPT
{
if (this != &other)
{
any_executor_base tmp(BOOST_ASIO_MOVE_CAST(any_executor_base)(other));
other = BOOST_ASIO_MOVE_CAST(any_executor_base)(*this);
*this = BOOST_ASIO_MOVE_CAST(any_executor_base)(tmp);
}
}
template
void execute(BOOST_ASIO_MOVE_ARG(F) f) const
{
if (target_fns_->blocking_execute != 0)
{
boost::asio::detail::non_const_lvalue f2(f);
target_fns_->blocking_execute(*this, function_view(f2.value));
}
else
{
target_fns_->execute(*this,
function(BOOST_ASIO_MOVE_CAST(F)(f), std::allocator()));
}
}
template
Executor* target()
{
return static_cast(target_);
}
template
const Executor* target() const
{
return static_cast(target_);
}
#if !defined(BOOST_ASIO_NO_TYPEID)
const std::type_info& target_type() const
#else // !defined(BOOST_ASIO_NO_TYPEID)
const void* target_type() const
#endif // !defined(BOOST_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 BOOST_ASIO_NOEXCEPT
{
return target_ ? &any_executor_base::unspecified_bool_true : 0;
}
bool operator!() const BOOST_ASIO_NOEXCEPT
{
return target_ == 0;
}
protected:
bool equality_helper(const any_executor_base& other) const BOOST_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_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
static const object_fns* object_fns_table(
typename enable_if<
is_same::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 boost::asio::detail::shared_ptr type;
ex.object().~type();
}
static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2)
{
typedef boost::asio::detail::shared_ptr type;
new (&ex1.object_) type(ex2.object());
ex1.target_ = ex2.target_;
}
static void move_shared(any_executor_base& ex1, any_executor_base& ex2)
{
typedef boost::asio::detail::shared_ptr type;
new (&ex1.object_) type(BOOST_ASIO_MOVE_CAST(type)(ex2.object()));
ex1.target_ = ex2.target_;
ex2.object().~type();
}
static const void* target_shared(const any_executor_base& ex)
{
typedef boost::asio::detail::shared_ptr 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(BOOST_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 boost::asio::detail::executor_function function;
typedef boost::asio::detail::executor_function_view function_view;
struct target_fns
{
#if !defined(BOOST_ASIO_NO_TYPEID)
const std::type_info& (*target_type)();
#else // !defined(BOOST_ASIO_NO_TYPEID)
const void* (*target_type)();
#endif // !defined(BOOST_ASIO_NO_TYPEID)
bool (*equal)(const any_executor_base&, const any_executor_base&);
void (*execute)(const any_executor_base&, BOOST_ASIO_MOVE_ARG(function));
void (*blocking_execute)(const any_executor_base&, function_view);
};
#if !defined(BOOST_ASIO_NO_TYPEID)
static const std::type_info& target_type_void()
{
return typeid(void);
}
#else // !defined(BOOST_ASIO_NO_TYPEID)
static const void* target_type_void()
{
return 0;
}
#endif // !defined(BOOST_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&,
BOOST_ASIO_MOVE_ARG(function))
{
bad_executor ex;
boost::asio::detail::throw_exception(ex);
}
static void blocking_execute_void(const any_executor_base&, function_view)
{
bad_executor ex;
boost::asio::detail::throw_exception(ex);
}
template
static const target_fns* target_fns_table(
typename enable_if<
is_same::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(BOOST_ASIO_NO_TYPEID)
template
static const std::type_info& target_type_ex()
{
return typeid(Ex);
}
#else // !defined(BOOST_ASIO_NO_TYPEID)
template
static const void* target_type_ex()
{
static int unique_id;
return &unique_id;
}
#endif // !defined(BOOST_ASIO_NO_TYPEID)
template
static bool equal_ex(const any_executor_base& ex1,
const any_executor_base& ex2)
{
return *ex1.target() == *ex2.target();
}
template
static void execute_ex(const any_executor_base& ex,
BOOST_ASIO_MOVE_ARG(function) f)
{
execution::execute(*ex.target(), BOOST_ASIO_MOVE_CAST(function)(f));
}
template
static void blocking_execute_ex(const any_executor_base& ex, function_view f)
{
execution::execute(*ex.target(), f);
}
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(BOOST_ASIO_MSVC)
# pragma warning (push)
# pragma warning (disable:4702)
#endif // defined(BOOST_ASIO_MSVC)
static void query_fn_void(void*, const void*, const void*)
{
bad_executor ex;
boost::asio::detail::throw_exception(ex);
}
template
static void query_fn_non_void(void*, const void* ex, const void* prop,
typename enable_if<
boost::asio::can_query::value
&& is_same::value
>::type*)
{
boost::asio::query(*static_cast(ex),
*static_cast(prop));
}
template
static void query_fn_non_void(void*, const void*, const void*,
typename enable_if<
!boost::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<
boost::asio::can_query::value
&& !is_same::value
&& is_reference::value
>::type*)
{
*static_cast::type**>(result)
= &static_cast(
boost::asio::query(*static_cast(ex),
*static_cast(prop)));
}
template
static void query_fn_non_void(void*, const void*, const void*,
typename enable_if<
!boost::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<
boost::asio::can_query::value
&& !is_same::value
&& is_scalar::value
>::type*)
{
*static_cast(result)
= static_cast(
boost::asio::query(*static_cast(ex),
*static_cast(prop)));
}
template
static void query_fn_non_void(void* result, const void*, const void*,
typename enable_if<
!boost::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<
boost::asio::can_query::value
&& !is_same::value
&& !is_reference