// bind_executor.hpp
// ~~~~~~~~~~~~~~~~~
//
-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+// Copyright (c) 2003-2022 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)
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/variadic_templates.hpp>
#include <boost/asio/associated_executor.hpp>
-#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associator.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/execution/executor.hpp>
#include <boost/asio/execution_context.hpp>
/// Associate an object of type @c T with an executor of type @c Executor.
template <typename Executor, typename T>
-inline executor_binder<typename decay<T>::type, Executor>
+BOOST_ASIO_NODISCARD inline executor_binder<typename decay<T>::type, Executor>
bind_executor(const Executor& ex, BOOST_ASIO_MOVE_ARG(T) t,
- typename enable_if<
+ typename constraint<
is_executor<Executor>::value || execution::is_executor<Executor>::value
- >::type* = 0)
+ >::type = 0)
{
return executor_binder<typename decay<T>::type, Executor>(
executor_arg_t(), ex, BOOST_ASIO_MOVE_CAST(T)(t));
/// Associate an object of type @c T with an execution context's executor.
template <typename ExecutionContext, typename T>
-inline executor_binder<typename decay<T>::type,
+BOOST_ASIO_NODISCARD inline executor_binder<typename decay<T>::type,
typename ExecutionContext::executor_type>
bind_executor(ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(T) t,
- typename enable_if<is_convertible<
- ExecutionContext&, execution_context&>::value>::type* = 0)
+ typename constraint<is_convertible<
+ ExecutionContext&, execution_context&>::value>::type = 0)
{
return executor_binder<typename decay<T>::type,
typename ExecutionContext::executor_type>(
struct uses_executor<executor_binder<T, Executor>, Executor>
: true_type {};
-template <typename T, typename Executor, typename Signature>
-class async_result<executor_binder<T, Executor>, Signature>
+namespace detail {
+
+template <typename TargetAsyncResult, typename Executor, typename = void>
+class executor_binder_completion_handler_async_result
+{
+public:
+ template <typename T>
+ explicit executor_binder_completion_handler_async_result(T&)
+ {
+ }
+};
+
+template <typename TargetAsyncResult, typename Executor>
+class executor_binder_completion_handler_async_result<
+ TargetAsyncResult, Executor,
+ typename void_type<
+ typename TargetAsyncResult::completion_handler_type
+ >::type>
{
public:
typedef executor_binder<
- typename async_result<T, Signature>::completion_handler_type, Executor>
+ typename TargetAsyncResult::completion_handler_type, Executor>
completion_handler_type;
- typedef typename async_result<T, Signature>::return_type return_type;
+ explicit executor_binder_completion_handler_async_result(
+ typename TargetAsyncResult::completion_handler_type& handler)
+ : target_(handler)
+ {
+ }
+
+ typename TargetAsyncResult::return_type get()
+ {
+ return target_.get();
+ }
+private:
+ TargetAsyncResult target_;
+};
+
+template <typename TargetAsyncResult, typename = void>
+struct executor_binder_async_result_return_type
+{
+};
+
+template <typename TargetAsyncResult>
+struct executor_binder_async_result_return_type<
+ TargetAsyncResult,
+ typename void_type<
+ typename TargetAsyncResult::return_type
+ >::type>
+{
+ typedef typename TargetAsyncResult::return_type return_type;
+};
+
+} // namespace detail
+
+template <typename T, typename Executor, typename Signature>
+class async_result<executor_binder<T, Executor>, Signature> :
+ public detail::executor_binder_completion_handler_async_result<
+ async_result<T, Signature>, Executor>,
+ public detail::executor_binder_async_result_return_type<
+ async_result<T, Signature> >
+{
+public:
explicit async_result(executor_binder<T, Executor>& b)
- : target_(b.get())
+ : detail::executor_binder_completion_handler_async_result<
+ async_result<T, Signature>, Executor>(b.get())
{
}
- return_type get()
+ template <typename Initiation>
+ struct init_wrapper
{
- return target_.get();
+ template <typename Init>
+ init_wrapper(const Executor& ex, BOOST_ASIO_MOVE_ARG(Init) init)
+ : ex_(ex),
+ initiation_(BOOST_ASIO_MOVE_CAST(Init)(init))
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Handler, typename... Args>
+ void operator()(
+ BOOST_ASIO_MOVE_ARG(Handler) handler,
+ BOOST_ASIO_MOVE_ARG(Args)... args)
+ {
+ BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
+ executor_binder<typename decay<Handler>::type, Executor>(
+ executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ }
+
+ template <typename Handler, typename... Args>
+ void operator()(
+ BOOST_ASIO_MOVE_ARG(Handler) handler,
+ BOOST_ASIO_MOVE_ARG(Args)... args) const
+ {
+ initiation_(
+ executor_binder<typename decay<Handler>::type, Executor>(
+ executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ }
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Handler>
+ void operator()(
+ BOOST_ASIO_MOVE_ARG(Handler) handler)
+ {
+ BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
+ executor_binder<typename decay<Handler>::type, Executor>(
+ executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
+ }
+
+ template <typename Handler>
+ void operator()(
+ BOOST_ASIO_MOVE_ARG(Handler) handler) const
+ {
+ initiation_(
+ executor_binder<typename decay<Handler>::type, Executor>(
+ executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
+ }
+
+#define BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
+ template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ void operator()( \
+ BOOST_ASIO_MOVE_ARG(Handler) handler, \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( \
+ executor_binder<typename decay<Handler>::type, Executor>( \
+ executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
+ BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ \
+ template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ void operator()( \
+ BOOST_ASIO_MOVE_ARG(Handler) handler, \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
+ { \
+ initiation_( \
+ executor_binder<typename decay<Handler>::type, Executor>( \
+ executor_arg_t(), ex_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
+ BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF)
+#undef BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ Executor ex_;
+ Initiation initiation_;
+ };
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Initiation, typename RawCompletionToken, typename... Args>
+ static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
+ (async_initiate<T, Signature>(
+ declval<init_wrapper<typename decay<Initiation>::type> >(),
+ declval<RawCompletionToken>().get(),
+ declval<BOOST_ASIO_MOVE_ARG(Args)>()...)))
+ initiate(
+ BOOST_ASIO_MOVE_ARG(Initiation) initiation,
+ BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
+ BOOST_ASIO_MOVE_ARG(Args)... args)
+ {
+ return async_initiate<T, Signature>(
+ init_wrapper<typename decay<Initiation>::type>(
+ token.get_executor(), BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
+ token.get(), BOOST_ASIO_MOVE_CAST(Args)(args)...);
}
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Initiation, typename RawCompletionToken>
+ static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
+ (async_initiate<T, Signature>(
+ declval<init_wrapper<typename decay<Initiation>::type> >(),
+ declval<RawCompletionToken>().get())))
+ initiate(
+ BOOST_ASIO_MOVE_ARG(Initiation) initiation,
+ BOOST_ASIO_MOVE_ARG(RawCompletionToken) token)
+ {
+ return async_initiate<T, Signature>(
+ init_wrapper<typename decay<Initiation>::type>(
+ token.get_executor(), BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
+ token.get());
+ }
+
+#define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \
+ template <typename Initiation, typename RawCompletionToken, \
+ BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \
+ (async_initiate<T, Signature>( \
+ declval<init_wrapper<typename decay<Initiation>::type> >(), \
+ declval<RawCompletionToken>().get(), \
+ BOOST_ASIO_VARIADIC_MOVE_DECLVAL(n)))) \
+ initiate( \
+ BOOST_ASIO_MOVE_ARG(Initiation) initiation, \
+ BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ return async_initiate<T, Signature>( \
+ init_wrapper<typename decay<Initiation>::type>( \
+ token.get_executor(), BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), \
+ token.get(), BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF)
+#undef BOOST_ASIO_PRIVATE_INITIATE_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
private:
async_result(const async_result&) BOOST_ASIO_DELETED;
async_result& operator=(const async_result&) BOOST_ASIO_DELETED;
-
- async_result<T, Signature> target_;
};
-template <typename T, typename Executor, typename Allocator>
-struct associated_allocator<executor_binder<T, Executor>, Allocator>
+template <template <typename, typename> class Associator,
+ typename T, typename Executor, typename DefaultCandidate>
+struct associator<Associator, executor_binder<T, Executor>, DefaultCandidate>
{
- typedef typename associated_allocator<T, Allocator>::type type;
+ typedef typename Associator<T, DefaultCandidate>::type type;
static type get(const executor_binder<T, Executor>& b,
- const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ const DefaultCandidate& c = DefaultCandidate()) BOOST_ASIO_NOEXCEPT
{
- return associated_allocator<T, Allocator>::get(b.get(), a);
+ return Associator<T, DefaultCandidate>::get(b.get(), c);
}
};