Test for native I/O executors in detail::handler_work<>.
The detail::io_object_executor wrapper has been removed, and the job of detecting, and optimising for, native I/O executors is now performed directly in the detail::handler_work implementation.
This commit is contained in:
parent
a5401f7eee
commit
6080760b80
@ -135,7 +135,6 @@ nobase_include_HEADERS = \
|
||||
asio/detail/impl/win_thread.ipp \
|
||||
asio/detail/impl/win_tss_ptr.ipp \
|
||||
asio/detail/io_control.hpp \
|
||||
asio/detail/io_object_executor.hpp \
|
||||
asio/detail/io_object_impl.hpp \
|
||||
asio/detail/is_buffer_sequence.hpp \
|
||||
asio/detail/is_executor.hpp \
|
||||
|
@ -1093,7 +1093,7 @@ private:
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_send(
|
||||
self_->impl_.get_implementation(), buffers, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1126,8 +1126,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_send_to(
|
||||
self_->impl_.get_implementation(), buffers, destination, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers, destination,
|
||||
flags, handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1161,7 +1161,7 @@ private:
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_receive(
|
||||
self_->impl_.get_implementation(), buffers, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1194,8 +1194,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_receive_from(
|
||||
self_->impl_.get_implementation(), buffers, *sender_endpoint, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers, *sender_endpoint,
|
||||
flags, handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -671,8 +671,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WaitHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_wait(
|
||||
self_->impl_.get_implementation(), handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(),
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1085,7 +1085,7 @@ private:
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_send(
|
||||
self_->impl_.get_implementation(), buffers, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1118,8 +1118,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_send_to(
|
||||
self_->impl_.get_implementation(), buffers, destination, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers, destination,
|
||||
flags, handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1153,7 +1153,7 @@ private:
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_receive(
|
||||
self_->impl_.get_implementation(), buffers, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1186,8 +1186,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_receive_from(
|
||||
self_->impl_.get_implementation(), buffers, *sender_endpoint, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers, *sender_endpoint,
|
||||
flags, handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -706,7 +706,7 @@ private:
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_send(
|
||||
self_->impl_.get_implementation(), buffers, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -740,8 +740,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_receive_with_flags(
|
||||
self_->impl_.get_implementation(), buffers, in_flags, *out_flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers, in_flags,
|
||||
*out_flags, handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -849,8 +849,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_write_some(
|
||||
self_->impl_.get_implementation(), buffers, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -882,8 +882,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_read_some(
|
||||
self_->impl_.get_implementation(), buffers, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -552,8 +552,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<SignalHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_wait(
|
||||
self_->impl_.get_implementation(), handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(),
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1846,7 +1846,7 @@ private:
|
||||
detail::non_const_lvalue<ConnectHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_connect(
|
||||
self_->impl_.get_implementation(), peer_endpoint,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1878,8 +1878,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WaitHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_wait(
|
||||
self_->impl_.get_implementation(), w, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), w,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -2400,8 +2400,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WaitHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_wait(
|
||||
self_->impl_.get_implementation(), w, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), w,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -2435,7 +2435,7 @@ private:
|
||||
detail::non_const_lvalue<AcceptHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_accept(
|
||||
self_->impl_.get_implementation(), *peer, peer_endpoint,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -2469,7 +2469,7 @@ private:
|
||||
detail::non_const_lvalue<MoveAcceptHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_move_accept(
|
||||
self_->impl_.get_implementation(), peer_ex, peer_endpoint,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1000,7 +1000,7 @@ private:
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_send(
|
||||
self_->impl_.get_implementation(), buffers, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1034,7 +1034,7 @@ private:
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_receive(
|
||||
self_->impl_.get_implementation(), buffers, flags,
|
||||
handler2.value, self_->impl_.get_implementation_executor());
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -790,8 +790,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WaitHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_wait(
|
||||
self_->impl_.get_implementation(), handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(),
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -18,84 +18,220 @@
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/associated_executor.hpp"
|
||||
#include "asio/detail/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/type_traits.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
class executor;
|
||||
class io_context;
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename Executor, typename CandidateExecutor = void,
|
||||
typename IoContext = io_context,
|
||||
typename PolymorphicExecutor = executor, typename = void>
|
||||
class handler_work_base
|
||||
{
|
||||
public:
|
||||
explicit handler_work_base(const Executor& ex) ASIO_NOEXCEPT
|
||||
: executor_(ex),
|
||||
owns_work_(true)
|
||||
{
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
handler_work_base(const Executor& ex,
|
||||
const Executor& candidate) ASIO_NOEXCEPT
|
||||
: executor_(ex),
|
||||
owns_work_(ex != candidate)
|
||||
{
|
||||
if (owns_work_)
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
template <typename OtherExecutor>
|
||||
handler_work_base(const Executor& ex,
|
||||
const OtherExecutor&) ASIO_NOEXCEPT
|
||||
: executor_(ex),
|
||||
owns_work_(true)
|
||||
{
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT
|
||||
: executor_(other.executor_),
|
||||
owns_work_(other.owns_work_)
|
||||
{
|
||||
if (owns_work_)
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT
|
||||
: executor_(ASIO_MOVE_CAST(Executor)(other.executor_)),
|
||||
owns_work_(other.owns_work_)
|
||||
{
|
||||
other.owns_work_ = false;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
~handler_work_base()
|
||||
{
|
||||
if (owns_work_)
|
||||
executor_.on_work_finished();
|
||||
}
|
||||
|
||||
bool owns_work() const ASIO_NOEXCEPT
|
||||
{
|
||||
return owns_work_;
|
||||
}
|
||||
|
||||
const Executor& get_executor() const ASIO_NOEXCEPT
|
||||
{
|
||||
return executor_;
|
||||
}
|
||||
|
||||
private:
|
||||
Executor executor_;
|
||||
bool owns_work_;
|
||||
};
|
||||
|
||||
template <typename Executor, typename IoContext, typename PolymorphicExecutor>
|
||||
class handler_work_base<Executor, void, IoContext, PolymorphicExecutor,
|
||||
typename enable_if<
|
||||
is_same<
|
||||
Executor,
|
||||
typename IoContext::executor_type
|
||||
>::value
|
||||
>::type>
|
||||
{
|
||||
public:
|
||||
explicit handler_work_base(const Executor&)
|
||||
{
|
||||
}
|
||||
|
||||
bool owns_work() const ASIO_NOEXCEPT
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Executor, typename IoContext>
|
||||
class handler_work_base<Executor, void, IoContext, Executor>
|
||||
{
|
||||
public:
|
||||
explicit handler_work_base(const Executor& ex) ASIO_NOEXCEPT
|
||||
#if !defined(ASIO_NO_TYPEID)
|
||||
: executor_(
|
||||
ex.target_type() == typeid(typename IoContext::executor_type)
|
||||
? Executor() : ex)
|
||||
#else // !defined(ASIO_NO_TYPEID)
|
||||
: executor_(ex)
|
||||
#endif // !defined(ASIO_NO_TYPEID)
|
||||
{
|
||||
if (executor_)
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
handler_work_base(const Executor& ex,
|
||||
const Executor& candidate) ASIO_NOEXCEPT
|
||||
: executor_(ex != candidate ? ex : Executor())
|
||||
{
|
||||
if (executor_)
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
template <typename OtherExecutor>
|
||||
handler_work_base(const Executor& ex,
|
||||
const OtherExecutor&) ASIO_NOEXCEPT
|
||||
: executor_(ex)
|
||||
{
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT
|
||||
: executor_(other.executor_)
|
||||
{
|
||||
if (executor_)
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT
|
||||
: executor_(ASIO_MOVE_CAST(Executor)(other.executor_))
|
||||
{
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
~handler_work_base()
|
||||
{
|
||||
if (executor_)
|
||||
executor_.on_work_finished();
|
||||
}
|
||||
|
||||
bool owns_work() const ASIO_NOEXCEPT
|
||||
{
|
||||
return !!executor_;
|
||||
}
|
||||
|
||||
const Executor& get_executor() const ASIO_NOEXCEPT
|
||||
{
|
||||
return executor_;
|
||||
}
|
||||
|
||||
private:
|
||||
Executor executor_;
|
||||
};
|
||||
|
||||
// A helper class template to allow completion handlers to be dispatched
|
||||
// through either the new executors framework or the old invocaton hook. The
|
||||
// primary template uses the new executors framework.
|
||||
template <typename Handler,
|
||||
typename IoExecutor = system_executor, typename HandlerExecutor
|
||||
= typename associated_executor<Handler, IoExecutor>::type>
|
||||
class handler_work
|
||||
class handler_work :
|
||||
handler_work_base<IoExecutor>,
|
||||
handler_work_base<HandlerExecutor, IoExecutor>
|
||||
{
|
||||
public:
|
||||
explicit handler_work(Handler& handler) ASIO_NOEXCEPT
|
||||
: io_executor_(),
|
||||
executor_(asio::get_associated_executor(handler, io_executor_)),
|
||||
owns_work_(true)
|
||||
: handler_work_base<IoExecutor>(IoExecutor()),
|
||||
handler_work_base<HandlerExecutor, IoExecutor>(
|
||||
asio::get_associated_executor(handler), IoExecutor())
|
||||
{
|
||||
io_executor_.on_work_started();
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
handler_work(Handler& handler, const IoExecutor& io_ex) ASIO_NOEXCEPT
|
||||
: io_executor_(io_ex),
|
||||
executor_(asio::get_associated_executor(handler, io_executor_)),
|
||||
owns_work_(true)
|
||||
: handler_work_base<IoExecutor>(io_ex),
|
||||
handler_work_base<HandlerExecutor, IoExecutor>(
|
||||
asio::get_associated_executor(handler, io_ex), io_ex)
|
||||
{
|
||||
io_executor_.on_work_started();
|
||||
executor_.on_work_started();
|
||||
}
|
||||
|
||||
handler_work(const handler_work& other)
|
||||
: io_executor_(other.io_executor_),
|
||||
executor_(other.executor_),
|
||||
owns_work_(other.owns_work_)
|
||||
{
|
||||
if (owns_work_)
|
||||
{
|
||||
io_executor_.on_work_started();
|
||||
executor_.on_work_started();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
handler_work(handler_work&& other)
|
||||
: io_executor_(ASIO_MOVE_CAST(IoExecutor)(other.io_executor_)),
|
||||
executor_(ASIO_MOVE_CAST(HandlerExecutor)(other.executor_)),
|
||||
owns_work_(other.owns_work_)
|
||||
{
|
||||
other.owns_work_ = false;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
~handler_work()
|
||||
{
|
||||
if (owns_work_)
|
||||
{
|
||||
io_executor_.on_work_finished();
|
||||
executor_.on_work_finished();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
void complete(Function& function, Handler& handler)
|
||||
{
|
||||
executor_.dispatch(ASIO_MOVE_CAST(Function)(function),
|
||||
asio::get_associated_allocator(handler));
|
||||
if (!handler_work_base<IoExecutor>::owns_work()
|
||||
&& !handler_work_base<HandlerExecutor, IoExecutor>::owns_work())
|
||||
{
|
||||
// When using a native implementation, I/O completion handlers are
|
||||
// already dispatched according to the execution context's executor's
|
||||
// rules. We can call the function directly.
|
||||
asio_handler_invoke_helpers::invoke(function, handler);
|
||||
}
|
||||
else
|
||||
{
|
||||
handler_work_base<HandlerExecutor, IoExecutor>::get_executor().dispatch(
|
||||
ASIO_MOVE_CAST(Function)(function),
|
||||
asio::get_associated_allocator(handler));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Disallow assignment.
|
||||
handler_work& operator=(const handler_work&);
|
||||
|
||||
IoExecutor io_executor_;
|
||||
HandlerExecutor executor_;
|
||||
bool owns_work_;
|
||||
};
|
||||
|
||||
// This specialisation dispatches a handler through the old invocation hook.
|
||||
|
@ -1,167 +0,0 @@
|
||||
//
|
||||
// io_object_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 ASIO_DETAIL_IO_OBJECT_EXECUTOR_HPP
|
||||
#define ASIO_DETAIL_IO_OBJECT_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/handler_invoke_helpers.hpp"
|
||||
#include "asio/detail/type_traits.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
namespace detail {
|
||||
|
||||
// Wrap the (potentially polymorphic) executor so that we can bypass it when
|
||||
// dispatching on a target executor that has a native I/O implementation.
|
||||
template <typename Executor>
|
||||
class io_object_executor
|
||||
{
|
||||
public:
|
||||
io_object_executor(const Executor& ex,
|
||||
bool native_implementation) ASIO_NOEXCEPT
|
||||
: executor_(ex),
|
||||
has_native_impl_(native_implementation)
|
||||
{
|
||||
}
|
||||
|
||||
io_object_executor(const io_object_executor& other) ASIO_NOEXCEPT
|
||||
: executor_(other.executor_),
|
||||
has_native_impl_(other.has_native_impl_)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Executor1>
|
||||
io_object_executor(
|
||||
const io_object_executor<Executor1>& other) ASIO_NOEXCEPT
|
||||
: executor_(other.inner_executor()),
|
||||
has_native_impl_(other.has_native_implementation())
|
||||
{
|
||||
}
|
||||
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
io_object_executor(io_object_executor&& other) ASIO_NOEXCEPT
|
||||
: executor_(ASIO_MOVE_CAST(Executor)(other.executor_)),
|
||||
has_native_impl_(other.has_native_impl_)
|
||||
{
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
const Executor& inner_executor() const ASIO_NOEXCEPT
|
||||
{
|
||||
return executor_;
|
||||
}
|
||||
|
||||
bool has_native_implementation() const ASIO_NOEXCEPT
|
||||
{
|
||||
return has_native_impl_;
|
||||
}
|
||||
|
||||
execution_context& context() const ASIO_NOEXCEPT
|
||||
{
|
||||
return executor_.context();
|
||||
}
|
||||
|
||||
void on_work_started() const ASIO_NOEXCEPT
|
||||
{
|
||||
if (is_same<Executor, io_context::executor_type>::value
|
||||
|| has_native_impl_)
|
||||
{
|
||||
// When using a native implementation, work is already counted by the
|
||||
// execution context.
|
||||
}
|
||||
else
|
||||
{
|
||||
executor_.on_work_started();
|
||||
}
|
||||
}
|
||||
|
||||
void on_work_finished() const ASIO_NOEXCEPT
|
||||
{
|
||||
if (is_same<Executor, io_context::executor_type>::value
|
||||
|| has_native_impl_)
|
||||
{
|
||||
// When using a native implementation, work is already counted by the
|
||||
// execution context.
|
||||
}
|
||||
else
|
||||
{
|
||||
executor_.on_work_finished();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F, typename A>
|
||||
void dispatch(ASIO_MOVE_ARG(F) f, const A& a) const
|
||||
{
|
||||
if (is_same<Executor, io_context::executor_type>::value
|
||||
|| has_native_impl_)
|
||||
{
|
||||
// When using a native implementation, I/O completion handlers are
|
||||
// already dispatched according to the execution context's executor's
|
||||
// rules. We can call the function directly.
|
||||
#if defined(ASIO_HAS_MOVE)
|
||||
if (is_same<F, typename decay<F>::type>::value)
|
||||
{
|
||||
asio_handler_invoke_helpers::invoke(f, f);
|
||||
return;
|
||||
}
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
typename decay<F>::type function(ASIO_MOVE_CAST(F)(f));
|
||||
asio_handler_invoke_helpers::invoke(function, function);
|
||||
}
|
||||
else
|
||||
{
|
||||
executor_.dispatch(ASIO_MOVE_CAST(F)(f), a);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F, typename A>
|
||||
void post(ASIO_MOVE_ARG(F) f, const A& a) const
|
||||
{
|
||||
executor_.post(ASIO_MOVE_CAST(F)(f), a);
|
||||
}
|
||||
|
||||
template <typename F, typename A>
|
||||
void defer(ASIO_MOVE_ARG(F) f, const A& a) const
|
||||
{
|
||||
executor_.defer(ASIO_MOVE_CAST(F)(f), a);
|
||||
}
|
||||
|
||||
friend bool operator==(const io_object_executor& a,
|
||||
const io_object_executor& b) ASIO_NOEXCEPT
|
||||
{
|
||||
return a.executor_ == b.executor_
|
||||
&& a.has_native_impl_ == b.has_native_impl_;
|
||||
}
|
||||
|
||||
friend bool operator!=(const io_object_executor& a,
|
||||
const io_object_executor& b) ASIO_NOEXCEPT
|
||||
{
|
||||
return a.executor_ != b.executor_
|
||||
|| a.has_native_impl_ != b.has_native_impl_;
|
||||
}
|
||||
|
||||
private:
|
||||
Executor executor_;
|
||||
const bool has_native_impl_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace asio
|
||||
|
||||
#include "asio/detail/pop_options.hpp"
|
||||
|
||||
#endif // ASIO_DETAIL_IO_OBJECT_EXECUTOR_HPP
|
@ -17,41 +17,14 @@
|
||||
|
||||
#include <new>
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/detail/io_object_executor.hpp"
|
||||
#include "asio/detail/type_traits.hpp"
|
||||
#include "asio/io_context.hpp"
|
||||
|
||||
#include "asio/detail/push_options.hpp"
|
||||
|
||||
namespace asio {
|
||||
|
||||
class executor;
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline bool is_native_io_executor(const io_context::executor_type&)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Executor>
|
||||
inline bool is_native_io_executor(const Executor&,
|
||||
typename enable_if<!is_same<Executor, executor>::value>::type* = 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Executor>
|
||||
inline bool is_native_io_executor(const Executor& ex,
|
||||
typename enable_if<is_same<Executor, executor>::value>::type* = 0)
|
||||
{
|
||||
#if !defined (ASIO_NO_TYPEID)
|
||||
return ex.target_type() == typeid(io_context::executor_type);
|
||||
#else // !defined (ASIO_NO_TYPEID)
|
||||
return false;
|
||||
#endif // !defined (ASIO_NO_TYPEID)
|
||||
}
|
||||
|
||||
template <typename IoObjectService,
|
||||
typename Executor = io_context::executor_type>
|
||||
class io_object_impl
|
||||
@ -66,13 +39,10 @@ public:
|
||||
// The type of the executor associated with the object.
|
||||
typedef Executor executor_type;
|
||||
|
||||
// The type of executor to be used when implementing asynchronous operations.
|
||||
typedef io_object_executor<Executor> implementation_executor_type;
|
||||
|
||||
// Construct an I/O object using an executor.
|
||||
explicit io_object_impl(const executor_type& ex)
|
||||
: service_(&asio::use_service<IoObjectService>(ex.context())),
|
||||
implementation_executor_(ex, (is_native_io_executor)(ex))
|
||||
executor_(ex)
|
||||
{
|
||||
service_->construct(implementation_);
|
||||
}
|
||||
@ -83,8 +53,7 @@ public:
|
||||
typename enable_if<is_convertible<
|
||||
ExecutionContext&, execution_context&>::value>::type* = 0)
|
||||
: service_(&asio::use_service<IoObjectService>(context)),
|
||||
implementation_executor_(context.get_executor(),
|
||||
is_same<ExecutionContext, io_context>::value)
|
||||
executor_(context.get_executor())
|
||||
{
|
||||
service_->construct(implementation_);
|
||||
}
|
||||
@ -93,7 +62,7 @@ public:
|
||||
// Move-construct an I/O object.
|
||||
io_object_impl(io_object_impl&& other)
|
||||
: service_(&other.get_service()),
|
||||
implementation_executor_(other.get_implementation_executor())
|
||||
executor_(other.get_executor())
|
||||
{
|
||||
service_->move_construct(implementation_, other.implementation_);
|
||||
}
|
||||
@ -102,8 +71,8 @@ public:
|
||||
template <typename IoObjectService1, typename Executor1>
|
||||
io_object_impl(io_object_impl<IoObjectService1, Executor1>&& other)
|
||||
: service_(&asio::use_service<IoObjectService>(
|
||||
other.get_implementation_executor().context())),
|
||||
implementation_executor_(other.get_implementation_executor())
|
||||
other.get_executor().context())),
|
||||
executor_(other.get_executor())
|
||||
{
|
||||
service_->converting_move_construct(implementation_,
|
||||
other.get_service(), other.get_implementation());
|
||||
@ -124,9 +93,9 @@ public:
|
||||
{
|
||||
service_->move_assign(implementation_,
|
||||
*other.service_, other.implementation_);
|
||||
implementation_executor_.~implementation_executor_type();
|
||||
new (&implementation_executor_) implementation_executor_type(
|
||||
std::move(other.implementation_executor_));
|
||||
executor_.~executor_type();
|
||||
new (&executor_) executor_type(
|
||||
std::move(other.executor_));
|
||||
service_ = other.service_;
|
||||
}
|
||||
return *this;
|
||||
@ -134,16 +103,9 @@ public:
|
||||
#endif // defined(ASIO_HAS_MOVE)
|
||||
|
||||
// Get the executor associated with the object.
|
||||
executor_type get_executor() ASIO_NOEXCEPT
|
||||
const executor_type& get_executor() ASIO_NOEXCEPT
|
||||
{
|
||||
return implementation_executor_.inner_executor();
|
||||
}
|
||||
|
||||
// Get the executor to be used when implementing asynchronous operations.
|
||||
const implementation_executor_type& get_implementation_executor()
|
||||
ASIO_NOEXCEPT
|
||||
{
|
||||
return implementation_executor_;
|
||||
return executor_;
|
||||
}
|
||||
|
||||
// Get the service associated with the I/O object.
|
||||
@ -182,7 +144,7 @@ private:
|
||||
implementation_type implementation_;
|
||||
|
||||
// The associated executor.
|
||||
implementation_executor_type implementation_executor_;
|
||||
executor_type executor_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
@ -21,7 +21,6 @@
|
||||
|
||||
#include "asio/io_context.hpp"
|
||||
#include "asio/detail/handler_alloc_helpers.hpp"
|
||||
#include "asio/detail/io_object_executor.hpp"
|
||||
#include "asio/detail/memory.hpp"
|
||||
#include "asio/detail/noncopyable.hpp"
|
||||
#include "asio/detail/win_iocp_overlapped_op.hpp"
|
||||
@ -80,10 +79,10 @@ public:
|
||||
const bool native = is_same<Executor, io_context::executor_type>::value;
|
||||
win_iocp_io_context* iocp_service = this->get_iocp_service(ex);
|
||||
|
||||
typedef win_iocp_overlapped_op<Handler, io_object_executor<Executor> > op;
|
||||
typedef win_iocp_overlapped_op<Handler, Executor> op;
|
||||
typename op::ptr p = { asio::detail::addressof(handler),
|
||||
op::ptr::allocate(handler), 0 };
|
||||
p.p = new (p.v) op(handler, io_object_executor<Executor>(ex, native));
|
||||
p.p = new (p.v) op(handler, ex);
|
||||
|
||||
ASIO_HANDLER_CREATION((ex.context(), *p.p,
|
||||
"iocp_service", iocp_service, 0, "overlapped"));
|
||||
|
@ -1003,8 +1003,8 @@ private:
|
||||
|
||||
asio::detail::non_const_lvalue<ResolveHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_resolve(
|
||||
self_->impl_.get_implementation(), q, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), q,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -677,8 +677,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WaitHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_wait(
|
||||
self_->impl_.get_implementation(), w, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), w,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -419,8 +419,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_write_some(
|
||||
self_->impl_.get_implementation(), buffers, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -452,8 +452,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_read_some(
|
||||
self_->impl_.get_implementation(), buffers, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -412,8 +412,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WaitHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_wait(
|
||||
self_->impl_.get_implementation(), handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(),
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -437,8 +437,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_write_some_at(
|
||||
self_->impl_.get_implementation(), offset, buffers, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), offset, buffers,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -470,8 +470,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_read_some_at(
|
||||
self_->impl_.get_implementation(), offset, buffers, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), offset, buffers,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -421,8 +421,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<WriteHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_write_some(
|
||||
self_->impl_.get_implementation(), buffers, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -454,8 +454,8 @@ private:
|
||||
|
||||
detail::non_const_lvalue<ReadHandler> handler2(handler);
|
||||
self_->impl_.get_service().async_read_some(
|
||||
self_->impl_.get_implementation(), buffers, handler2.value,
|
||||
self_->impl_.get_implementation_executor());
|
||||
self_->impl_.get_implementation(), buffers,
|
||||
handler2.value, self_->impl_.get_executor());
|
||||
}
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user