818 lines
25 KiB
C++
818 lines
25 KiB
C++
//
|
|
// inline_or_executor.hpp
|
|
// ~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
// Copyright (c) 2003-2025 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_INLINE_OR_EXECUTOR_HPP
|
|
#define ASIO_INLINE_OR_EXECUTOR_HPP
|
|
|
|
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
|
# pragma once
|
|
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
|
|
|
#include "asio/detail/config.hpp"
|
|
#include "asio/detail/non_const_lvalue.hpp"
|
|
#include "asio/detail/type_traits.hpp"
|
|
#include "asio/execution/blocking.hpp"
|
|
#include "asio/execution/executor.hpp"
|
|
#include "asio/execution/inline_exception_handling.hpp"
|
|
#include "asio/execution_context.hpp"
|
|
#include "asio/is_executor.hpp"
|
|
|
|
#include "asio/detail/push_options.hpp"
|
|
|
|
namespace asio {
|
|
|
|
/// Adapts an executor to add inline invocation of the submitted function.
|
|
/**
|
|
* The @inline_or_executor class template adapts an existing executor such that:
|
|
*
|
|
* @li posted function objects (or when the @c blocking property is set to
|
|
* @c blocking.never) are submitted to the wrapped executor; and
|
|
*
|
|
* @li dispatched function objects (or when @c blocking is @c blocking.always or
|
|
* @c blocking.possibly) are executed inline.
|
|
*/
|
|
template <typename Executor,
|
|
typename Blocking = execution::blocking_t::always_t,
|
|
typename InlineExceptionHandling
|
|
= execution::inline_exception_handling_t::propagate_t>
|
|
class inline_or_executor
|
|
{
|
|
public:
|
|
/// The type of the underlying executor.
|
|
typedef Executor inner_executor_type;
|
|
|
|
/// Default constructor.
|
|
/**
|
|
* This constructor is only valid if the underlying executor type is default
|
|
* constructible.
|
|
*/
|
|
inline_or_executor()
|
|
: executor_()
|
|
{
|
|
}
|
|
|
|
/// Construct an inline_or_executor for the specified executor.
|
|
template <typename Executor1>
|
|
explicit inline_or_executor(const Executor1& e,
|
|
constraint_t<
|
|
conditional_t<
|
|
!is_same<Executor1, inline_or_executor>::value,
|
|
is_convertible<Executor1, Executor>,
|
|
false_type
|
|
>::value
|
|
> = 0)
|
|
: executor_(e)
|
|
{
|
|
}
|
|
|
|
/// Copy constructor.
|
|
inline_or_executor(const inline_or_executor& other) noexcept
|
|
: executor_(other.executor_)
|
|
{
|
|
}
|
|
|
|
/// Converting constructor.
|
|
/**
|
|
* This constructor is only valid if the @c OtherExecutor type is convertible
|
|
* to @c Executor.
|
|
*/
|
|
template <class OtherExecutor>
|
|
inline_or_executor(
|
|
const inline_or_executor<OtherExecutor>& other) noexcept
|
|
: executor_(other.executor_)
|
|
{
|
|
}
|
|
|
|
/// Assignment operator.
|
|
inline_or_executor& operator=(const inline_or_executor& other) noexcept
|
|
{
|
|
executor_ = other.executor_;
|
|
return *this;
|
|
}
|
|
|
|
/// Converting assignment operator.
|
|
/**
|
|
* This assignment operator is only valid if the @c OtherExecutor type is
|
|
* convertible to @c Executor.
|
|
*/
|
|
template <class OtherExecutor>
|
|
inline_or_executor& operator=(
|
|
const inline_or_executor<OtherExecutor>& other) noexcept
|
|
{
|
|
executor_ = other.executor_;
|
|
return *this;
|
|
}
|
|
|
|
/// Move constructor.
|
|
inline_or_executor(inline_or_executor&& other) noexcept
|
|
: executor_(static_cast<Executor&&>(other.executor_))
|
|
{
|
|
}
|
|
|
|
/// Converting move constructor.
|
|
/**
|
|
* This constructor is only valid if the @c OtherExecutor type is convertible
|
|
* to @c Executor.
|
|
*/
|
|
template <class OtherExecutor>
|
|
inline_or_executor(inline_or_executor<OtherExecutor>&& other) noexcept
|
|
: executor_(static_cast<OtherExecutor&&>(other.executor_))
|
|
{
|
|
}
|
|
|
|
/// Move assignment operator.
|
|
inline_or_executor& operator=(inline_or_executor&& other) noexcept
|
|
{
|
|
executor_ = static_cast<Executor&&>(other.executor_);
|
|
return *this;
|
|
}
|
|
|
|
/// Converting move assignment operator.
|
|
/**
|
|
* This assignment operator is only valid if the @c OtherExecutor type is
|
|
* convertible to @c Executor.
|
|
*/
|
|
template <class OtherExecutor>
|
|
inline_or_executor& operator=(
|
|
inline_or_executor<OtherExecutor>&& other) noexcept
|
|
{
|
|
executor_ = static_cast<OtherExecutor&&>(other.executor_);
|
|
return *this;
|
|
}
|
|
|
|
/// Destructor.
|
|
~inline_or_executor() noexcept
|
|
{
|
|
}
|
|
|
|
/// Obtain the underlying executor.
|
|
inner_executor_type get_inner_executor() const noexcept
|
|
{
|
|
return executor_;
|
|
}
|
|
|
|
/// Query the current value of the @c blocking property.
|
|
/**
|
|
* Do not call this function directly. It is intended for use with the
|
|
* asio::query customisation point.
|
|
*
|
|
* For example:
|
|
* @code asio::inline_or_executor<my_executor_type> ex = ...;
|
|
* if (asio::query(ex, asio::execution::blocking)
|
|
* == asio::execution::blocking.possibly)
|
|
* ... @endcode
|
|
*/
|
|
static constexpr execution::blocking_t query(execution::blocking_t) noexcept
|
|
{
|
|
return Blocking();
|
|
}
|
|
|
|
/// Query the current value of the @c inline_exception_handling property.
|
|
/**
|
|
* Do not call this function directly. It is intended for use with the
|
|
* asio::query customisation point.
|
|
*
|
|
* For example:
|
|
* @code asio::inline_or_executor<my_executor_type> ex = ...;
|
|
* if (asio::query(ex,
|
|
* asio::execution::inline_exception_handling)
|
|
* == asio::execution::inline_exception_handling.propagate)
|
|
* ... @endcode
|
|
*/
|
|
static constexpr execution::inline_exception_handling_t query(
|
|
execution::inline_exception_handling_t) noexcept
|
|
{
|
|
return InlineExceptionHandling();
|
|
}
|
|
|
|
/// Forward a query to the underlying executor.
|
|
/**
|
|
* Do not call this function directly. It is intended for use with the
|
|
* asio::query customisation point.
|
|
*
|
|
* For example:
|
|
* @code asio::inline_or_executor<my_executor_type> ex = ...;
|
|
* if (asio::query(ex, asio::execution::blocking)
|
|
* == asio::execution::blocking.never)
|
|
* ... @endcode
|
|
*/
|
|
template <typename Property>
|
|
query_result_t<const Executor&, Property> query(const Property& p,
|
|
constraint_t<
|
|
can_query<const Executor&, Property>::value
|
|
> = 0,
|
|
constraint_t<
|
|
!is_convertible<Property, execution::blocking_t>::value
|
|
> = 0,
|
|
constraint_t<
|
|
!is_convertible<Property, execution::inline_exception_handling_t>::value
|
|
> = 0) const
|
|
noexcept(is_nothrow_query<const Executor&, Property>::value)
|
|
{
|
|
return asio::query(executor_, p);
|
|
}
|
|
|
|
/// Obtain an executor with the @c blocking.possibly property.
|
|
/**
|
|
* Do not call this function directly. It is intended for use with the
|
|
* asio::require customisation point.
|
|
*
|
|
* For example:
|
|
* @code asio::inline_or_executor<my_executor_type> ex = ...;
|
|
* auto ex2 = asio::require(ex1,
|
|
* asio::execution::blocking.possibly); @endcode
|
|
*/
|
|
inline_or_executor<Executor, execution::blocking_t::possibly_t,
|
|
InlineExceptionHandling>
|
|
require(const execution::blocking_t::possibly_t&) const noexcept
|
|
{
|
|
return inline_or_executor<Executor, execution::blocking_t::possibly_t,
|
|
InlineExceptionHandling>(executor_);
|
|
}
|
|
|
|
/// Obtain an executor with the @c blocking.always property.
|
|
/**
|
|
* Do not call this function directly. It is intended for use with the
|
|
* asio::require customisation point.
|
|
*
|
|
* For example:
|
|
* @code asio::inline_or_executor<my_executor_type> ex = ...;
|
|
* auto ex2 = asio::require(ex1,
|
|
* asio::execution::blocking.always); @endcode
|
|
*/
|
|
inline_or_executor<Executor, execution::blocking_t::always_t,
|
|
InlineExceptionHandling>
|
|
require(const execution::blocking_t::always_t&) const noexcept
|
|
{
|
|
return inline_or_executor<Executor, execution::blocking_t::always_t,
|
|
InlineExceptionHandling>(executor_);
|
|
}
|
|
|
|
/// Obtain an executor with the @c blocking.never property.
|
|
/**
|
|
* Do not call this function directly. It is intended for use with the
|
|
* asio::require customisation point.
|
|
*
|
|
* For example:
|
|
* @code asio::inline_or_executor<my_executor_type> ex = ...;
|
|
* auto ex2 = asio::require(ex1,
|
|
* asio::execution::blocking.never); @endcode
|
|
*/
|
|
inline_or_executor<Executor, execution::blocking_t::never_t,
|
|
InlineExceptionHandling>
|
|
require(const execution::blocking_t::never_t&) const noexcept
|
|
{
|
|
return inline_or_executor<Executor, execution::blocking_t::never_t,
|
|
InlineExceptionHandling>(executor_);
|
|
}
|
|
|
|
/// Obtain an executor with the @c inline_exception_handling.propagate
|
|
/// property.
|
|
/**
|
|
* Do not call this function directly. It is intended for use with the
|
|
* asio::require customisation point.
|
|
*
|
|
* For example:
|
|
* @code asio::inline_or_executor<my_executor_type> ex = ...;
|
|
* auto ex2 = asio::require(ex1,
|
|
* asio::execution::inline_exception_handling.propagate); @endcode
|
|
*/
|
|
inline_or_executor<Executor, Blocking,
|
|
execution::inline_exception_handling_t::propagate_t>
|
|
require(const execution::inline_exception_handling_t::propagate_t&)
|
|
const noexcept
|
|
{
|
|
return inline_or_executor<Executor, Blocking,
|
|
execution::inline_exception_handling_t::propagate_t>(executor_);
|
|
}
|
|
|
|
/// Obtain an executor with the @c inline_exception_handling.terminate
|
|
/// property.
|
|
/**
|
|
* Do not call this function directly. It is intended for use with the
|
|
* asio::require customisation point.
|
|
*
|
|
* For example:
|
|
* @code asio::inline_or_executor<my_executor_type> ex = ...;
|
|
* auto ex2 = asio::require(ex1,
|
|
* asio::execution::inline_exception_handling.terminate); @endcode
|
|
*/
|
|
inline_or_executor<Executor, Blocking,
|
|
execution::inline_exception_handling_t::terminate_t>
|
|
require(const execution::inline_exception_handling_t::terminate_t&)
|
|
const noexcept
|
|
{
|
|
return inline_or_executor<Executor, Blocking,
|
|
execution::inline_exception_handling_t::terminate_t>(executor_);
|
|
}
|
|
|
|
/// Forward a requirement to the underlying executor.
|
|
/**
|
|
* Do not call this function directly. It is intended for use with the
|
|
* asio::require customisation point.
|
|
*
|
|
* For example:
|
|
* @code asio::inline_or_executor<my_executor_type> ex1 = ...;
|
|
* auto ex2 = asio::require(ex1,
|
|
* asio::execution::relationship.continuation); @endcode
|
|
*/
|
|
template <typename Property>
|
|
inline_or_executor<decay_t<require_result_t<const Executor&, Property>>,
|
|
Blocking, InlineExceptionHandling>
|
|
require(const Property& p,
|
|
constraint_t<
|
|
can_require<const Executor&, Property>::value
|
|
> = 0,
|
|
constraint_t<
|
|
!is_convertible<Property, execution::blocking_t>::value
|
|
> = 0,
|
|
constraint_t<
|
|
!is_convertible<Property, execution::inline_exception_handling_t>::value
|
|
> = 0) const
|
|
noexcept(is_nothrow_require<const Executor&, Property>::value)
|
|
{
|
|
return inline_or_executor<
|
|
decay_t<require_result_t<const Executor&, Property>>,
|
|
Blocking, InlineExceptionHandling>(asio::require(executor_, p));
|
|
}
|
|
|
|
/// Forward a preference to the underlying executor.
|
|
/**
|
|
* Do not call this function directly. It is intended for use with the
|
|
* asio::prefer customisation point.
|
|
*
|
|
* For example:
|
|
* @code asio::inline_or_executor<my_executor_type> ex1 = ...;
|
|
* auto ex2 = asio::prefer(ex1,
|
|
* asio::execution::relationship.continuation); @endcode
|
|
*/
|
|
template <typename Property>
|
|
inline_or_executor<decay_t<prefer_result_t<const Executor&, Property>>,
|
|
Blocking, InlineExceptionHandling>
|
|
prefer(const Property& p,
|
|
constraint_t<
|
|
can_prefer<const Executor&, Property>::value
|
|
> = 0,
|
|
constraint_t<
|
|
!is_convertible<Property, execution::blocking_t>::value
|
|
> = 0,
|
|
constraint_t<
|
|
!is_convertible<Property, execution::inline_exception_handling_t>::value
|
|
> = 0) const
|
|
noexcept(is_nothrow_prefer<const Executor&, Property>::value)
|
|
{
|
|
return inline_or_executor<
|
|
decay_t<prefer_result_t<const Executor&, Property>>,
|
|
Blocking, InlineExceptionHandling>(asio::prefer(executor_, p));
|
|
}
|
|
|
|
#if !defined(ASIO_NO_TS_EXECUTORS)
|
|
/// Obtain the underlying execution context.
|
|
execution_context& context() const noexcept
|
|
{
|
|
return executor_.context();
|
|
}
|
|
|
|
/// Inform the inline_or_executor that it has some outstanding work to do.
|
|
/**
|
|
* The inline_or_executor delegates this call to its underlying executor.
|
|
*/
|
|
void on_work_started() const noexcept
|
|
{
|
|
executor_.on_work_started();
|
|
}
|
|
|
|
/// Inform the inline_or_executor that some work is no longer outstanding.
|
|
/**
|
|
* The inline_or_executor delegates this call to its underlying executor.
|
|
*/
|
|
void on_work_finished() const noexcept
|
|
{
|
|
executor_.on_work_finished();
|
|
}
|
|
#endif // !defined(ASIO_NO_TS_EXECUTORS)
|
|
|
|
/// Request the inline_or_executor to invoke the given function object.
|
|
/**
|
|
* This function is used to ask the inline_or_executor to execute the given
|
|
* function object. The function object will be executed inline or according
|
|
* to the properties of the underlying executor.
|
|
*
|
|
* @param f The function object to be called. The executor will make
|
|
* a copy of the handler object as required. The function signature of the
|
|
* function object must be: @code void function(); @endcode
|
|
*/
|
|
template <typename Function>
|
|
constraint_t<
|
|
traits::execute_member<const Executor&, Function>::is_valid,
|
|
void
|
|
> execute(Function&& f) const
|
|
{
|
|
this->execute_helper(static_cast<Function&&>(f), Blocking{});
|
|
}
|
|
|
|
#if !defined(ASIO_NO_TS_EXECUTORS)
|
|
/// Request the inline_or_executor to invoke the given function object.
|
|
/**
|
|
* This function is used to ask the inline_or_executor to execute the given
|
|
* function object. The function object will be executed inside this function.
|
|
*
|
|
* @param f The function object to be called. The executor will make
|
|
* a copy of the handler object as required. The function signature of the
|
|
* function object must be: @code void function(); @endcode
|
|
*
|
|
* @param a An allocator that may be used by the executor to allocate the
|
|
* internal storage needed for function invocation.
|
|
*/
|
|
template <typename Function, typename Allocator>
|
|
void dispatch(Function&& f, const Allocator& a) const
|
|
{
|
|
(void)a;
|
|
detail::non_const_lvalue<Function> f2(f);
|
|
static_cast<decay_t<Function>&&>(f2.value)();
|
|
}
|
|
|
|
/// Request the inline_or_executor to invoke the given function object.
|
|
/**
|
|
* This function is used to ask the executor to execute the given function
|
|
* object. The function object will never be executed inside this function.
|
|
* Instead, it will be scheduled by the underlying executor's post function.
|
|
*
|
|
* @param f The function object to be called. The executor will make
|
|
* a copy of the handler object as required. The function signature of the
|
|
* function object must be: @code void function(); @endcode
|
|
*
|
|
* @param a An allocator that may be used by the executor to allocate the
|
|
* internal storage needed for function invocation.
|
|
*/
|
|
template <typename Function, typename Allocator>
|
|
void post(Function&& f, const Allocator& a) const
|
|
{
|
|
executor_.post(static_cast<Function&&>(f), a);
|
|
}
|
|
|
|
/// Request the inline_or_executor to invoke the given function object.
|
|
/**
|
|
* This function is used to ask the executor to execute the given function
|
|
* object. The function object will never be executed inside this function.
|
|
* Instead, it will be scheduled by the underlying executor's defer function.
|
|
*
|
|
* @param f The function object to be called. The executor will make
|
|
* a copy of the handler object as required. The function signature of the
|
|
* function object must be: @code void function(); @endcode
|
|
*
|
|
* @param a An allocator that may be used by the executor to allocate the
|
|
* internal storage needed for function invocation.
|
|
*/
|
|
template <typename Function, typename Allocator>
|
|
void defer(Function&& f, const Allocator& a) const
|
|
{
|
|
executor_.defer(static_cast<Function&&>(f), a);
|
|
}
|
|
#endif // !defined(ASIO_NO_TS_EXECUTORS)
|
|
|
|
/// Compare two inline_or_executors for equality.
|
|
/**
|
|
* Two inline_or_executors are equal if their underlying executors are equal.
|
|
*/
|
|
friend bool operator==(const inline_or_executor& a,
|
|
const inline_or_executor& b) noexcept
|
|
{
|
|
return a.executor_ == b.executor_;
|
|
}
|
|
|
|
/// Compare two inline_or_executors for inequality.
|
|
/**
|
|
* Two inline_or_executors are equal if their underlying executors are equal.
|
|
*/
|
|
friend bool operator!=(const inline_or_executor& a,
|
|
const inline_or_executor& b) noexcept
|
|
{
|
|
return a.executor_ != b.executor_;
|
|
}
|
|
|
|
#if defined(GENERATING_DOCUMENTATION)
|
|
private:
|
|
#endif // defined(GENERATING_DOCUMENTATION)
|
|
template <typename Function>
|
|
void execute_helper(Function&& f, execution::blocking_t::possibly_t) const
|
|
{
|
|
#if !defined(ASIO_NO_EXCEPTIONS)
|
|
try
|
|
#endif // !defined(ASIO_NO_EXCEPTIONS)
|
|
{
|
|
detail::non_const_lvalue<Function> f2(f);
|
|
static_cast<decay_t<Function>&&>(f2.value)();
|
|
}
|
|
#if !defined(ASIO_NO_EXCEPTIONS)
|
|
catch (...)
|
|
{
|
|
if (is_same<InlineExceptionHandling,
|
|
execution::inline_exception_handling_t::terminate_t>::value)
|
|
{
|
|
std::terminate();
|
|
}
|
|
else
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
#endif // !defined(ASIO_NO_EXCEPTIONS)
|
|
}
|
|
|
|
template <typename Function>
|
|
void execute_helper(Function&& f, execution::blocking_t::always_t) const
|
|
{
|
|
this->execute_helper(static_cast<Function&&>(f),
|
|
execution::blocking.possibly);
|
|
}
|
|
|
|
template <typename Function>
|
|
void execute_helper(Function&& f, execution::blocking_t::never_t) const
|
|
{
|
|
asio::require(executor_, execution::blocking.never).execute(
|
|
static_cast<Function&&>(f));
|
|
}
|
|
|
|
Executor executor_;
|
|
};
|
|
|
|
/** @defgroup inline_or asio::inline_or
|
|
*
|
|
* @brief The asio::inline_or function creates an @ref inline_or_executor
|
|
* object for an executor or execution context.
|
|
*/
|
|
/*@{*/
|
|
|
|
/// Create an @ref inline_or_executor object for an executor.
|
|
/**
|
|
* @param ex An executor.
|
|
*
|
|
* @returns An inline_or_executor constructed with the specified executor.
|
|
*/
|
|
template <typename Executor>
|
|
inline inline_or_executor<Executor> inline_or(const Executor& ex,
|
|
constraint_t<
|
|
is_executor<Executor>::value || execution::is_executor<Executor>::value
|
|
> = 0)
|
|
{
|
|
return inline_or_executor<Executor>(ex);
|
|
}
|
|
|
|
/// Create an @ref inline_or_executor object for an execution context.
|
|
/**
|
|
* @param ctx An execution context, from which an executor will be obtained.
|
|
*
|
|
* @returns An inline_or_executor constructed with the execution context's
|
|
* executor, obtained by performing <tt>ctx.get_executor()</tt>.
|
|
*/
|
|
template <typename ExecutionContext>
|
|
inline inline_or_executor<typename ExecutionContext::executor_type>
|
|
inline_or(ExecutionContext& ctx,
|
|
constraint_t<
|
|
is_convertible<ExecutionContext&, execution_context&>::value
|
|
> = 0)
|
|
{
|
|
return inline_or_executor<typename ExecutionContext::executor_type>(
|
|
ctx.get_executor());
|
|
}
|
|
|
|
/*@}*/
|
|
|
|
#if !defined(GENERATING_DOCUMENTATION)
|
|
|
|
namespace traits {
|
|
|
|
#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling>
|
|
struct equality_comparable<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept = true;
|
|
};
|
|
|
|
#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
|
|
|
|
#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling, typename Function>
|
|
struct execute_member<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Function,
|
|
enable_if_t<
|
|
traits::execute_member<const Executor&, Function>::is_valid
|
|
>
|
|
>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept = false;
|
|
typedef void result_type;
|
|
};
|
|
|
|
#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
|
|
|
|
#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling, typename Property>
|
|
struct query_static_constexpr_member<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
|
|
Property,
|
|
enable_if_t<
|
|
is_convertible<
|
|
Property,
|
|
execution::blocking_t
|
|
>::value
|
|
>
|
|
>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept = true;
|
|
typedef Blocking result_type;
|
|
|
|
static constexpr result_type value() noexcept
|
|
{
|
|
return result_type();
|
|
}
|
|
};
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling, typename Property>
|
|
struct query_static_constexpr_member<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
|
|
Property,
|
|
enable_if_t<
|
|
is_convertible<
|
|
Property,
|
|
execution::inline_exception_handling_t
|
|
>::value
|
|
>
|
|
>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept = true;
|
|
typedef InlineExceptionHandling result_type;
|
|
|
|
static constexpr result_type value() noexcept
|
|
{
|
|
return result_type();
|
|
}
|
|
};
|
|
|
|
#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
|
|
|
|
#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling, typename Property>
|
|
struct query_member<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Property,
|
|
enable_if_t<
|
|
can_query<const Executor&, Property>::value
|
|
&& !is_convertible<Property,
|
|
execution::blocking_t>::value
|
|
&& !is_convertible<Property,
|
|
execution::inline_exception_handling_t>::value
|
|
>
|
|
>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept =
|
|
is_nothrow_query<Executor, Property>::value;
|
|
typedef query_result_t<Executor, Property> result_type;
|
|
};
|
|
|
|
#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
|
|
|
|
#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling>
|
|
struct require_member<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
|
|
execution::blocking_t::possibly_t
|
|
>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept = true;
|
|
typedef inline_or_executor<Executor, execution::blocking_t::possibly_t,
|
|
InlineExceptionHandling> result_type;
|
|
};
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling>
|
|
struct require_member<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
|
|
execution::blocking_t::always_t
|
|
>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept = true;
|
|
typedef inline_or_executor<Executor, execution::blocking_t::always_t,
|
|
InlineExceptionHandling> result_type;
|
|
};
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling>
|
|
struct require_member<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
|
|
execution::blocking_t::never_t
|
|
>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept = true;
|
|
typedef inline_or_executor<Executor, execution::blocking_t::never_t,
|
|
InlineExceptionHandling> result_type;
|
|
};
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling>
|
|
struct require_member<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
|
|
execution::inline_exception_handling_t::propagate_t
|
|
>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept = true;
|
|
typedef inline_or_executor<Executor, Blocking,
|
|
execution::inline_exception_handling_t::propagate_t> result_type;
|
|
};
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling>
|
|
struct require_member<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
|
|
execution::inline_exception_handling_t::terminate_t
|
|
>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept = true;
|
|
typedef inline_or_executor<Executor, Blocking,
|
|
execution::inline_exception_handling_t::terminate_t> result_type;
|
|
};
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling, typename Property>
|
|
struct require_member<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Property,
|
|
enable_if_t<
|
|
can_require<const Executor&, Property>::value
|
|
&& !is_convertible<Property,
|
|
execution::blocking_t>::value
|
|
&& !is_convertible<Property,
|
|
execution::inline_exception_handling_t>::value
|
|
>
|
|
>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept =
|
|
is_nothrow_require<const Executor&, Property>::value;
|
|
typedef inline_or_executor<
|
|
decay_t<require_result_t<const Executor&, Property>>,
|
|
Blocking, InlineExceptionHandling> result_type;
|
|
};
|
|
|
|
#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
|
|
|
|
#if !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
|
|
|
|
template <typename Executor, typename Blocking,
|
|
typename InlineExceptionHandling, typename Property>
|
|
struct prefer_member<
|
|
inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Property,
|
|
enable_if_t<
|
|
can_prefer<const Executor&, Property>::value
|
|
&& !is_convertible<Property, execution::blocking_t::always_t>::value
|
|
>
|
|
>
|
|
{
|
|
static constexpr bool is_valid = true;
|
|
static constexpr bool is_noexcept =
|
|
is_nothrow_prefer<const Executor&, Property>::value;
|
|
typedef inline_or_executor<
|
|
decay_t<prefer_result_t<const Executor&, Property>>,
|
|
Blocking, InlineExceptionHandling> result_type;
|
|
};
|
|
|
|
#endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
|
|
|
|
} // namespace traits
|
|
|
|
#endif // !defined(GENERATING_DOCUMENTATION)
|
|
|
|
} // namespace asio
|
|
|
|
#include "asio/detail/pop_options.hpp"
|
|
|
|
#endif // ASIO_INLINE_OR_EXECUTOR_HPP
|