Simplify and improve performance of executor operations.
This commit is contained in:
parent
e5acea17d7
commit
bbe092b3d7
@ -31,11 +31,12 @@ template <typename Handler, typename Alloc,
|
||||
class executor_op : public Operation
|
||||
{
|
||||
public:
|
||||
ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(executor_op, Alloc);
|
||||
ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(executor_op);
|
||||
|
||||
executor_op(Handler& h, const Alloc& allocator)
|
||||
template <typename H>
|
||||
executor_op(ASIO_MOVE_ARG(H) h, const Alloc& allocator)
|
||||
: Operation(&executor_op::do_complete),
|
||||
handler_(ASIO_MOVE_CAST(Handler)(h)),
|
||||
handler_(ASIO_MOVE_CAST(H)(h)),
|
||||
allocator_(allocator)
|
||||
{
|
||||
}
|
||||
@ -46,7 +47,8 @@ public:
|
||||
{
|
||||
// Take ownership of the handler object.
|
||||
executor_op* o(static_cast<executor_op*>(base));
|
||||
ptr p = { o->allocator_, o, o };
|
||||
Alloc allocator(o->allocator_);
|
||||
ptr p = { detail::addressof(allocator), o, o };
|
||||
|
||||
ASIO_HANDLER_COMPLETION((*o));
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "asio/detail/config.hpp"
|
||||
#include "asio/detail/memory.hpp"
|
||||
#include "asio/detail/noncopyable.hpp"
|
||||
#include "asio/detail/recycling_allocator.hpp"
|
||||
#include "asio/associated_allocator.hpp"
|
||||
#include "asio/handler_alloc_hook.hpp"
|
||||
|
||||
@ -164,18 +165,30 @@ public:
|
||||
} \
|
||||
/**/
|
||||
|
||||
#define ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op, alloc) \
|
||||
#define ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op) \
|
||||
struct ptr \
|
||||
{ \
|
||||
ASIO_REBIND_ALLOC(alloc, op) a; \
|
||||
const Alloc* a; \
|
||||
void* v; \
|
||||
op* p; \
|
||||
~ptr() \
|
||||
{ \
|
||||
reset(); \
|
||||
} \
|
||||
static op* allocate(const Alloc& a) \
|
||||
{ \
|
||||
typedef typename ::asio::detail::get_recycling_allocator< \
|
||||
Alloc>::type recycling_allocator_type; \
|
||||
ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
|
||||
::asio::detail::get_recycling_allocator<Alloc>::get(a)); \
|
||||
return a1.allocate(1); \
|
||||
} \
|
||||
void reset() \
|
||||
{ \
|
||||
typedef typename ::asio::detail::get_recycling_allocator< \
|
||||
Alloc>::type recycling_allocator_type; \
|
||||
ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
|
||||
::asio::detail::get_recycling_allocator<Alloc>::get(*a)); \
|
||||
if (p) \
|
||||
{ \
|
||||
p->~op(); \
|
||||
@ -183,7 +196,7 @@ public:
|
||||
} \
|
||||
if (v) \
|
||||
{ \
|
||||
a.deallocate(static_cast<op*>(v), 1); \
|
||||
a1.deallocate(static_cast<op*>(v), 1); \
|
||||
v = 0; \
|
||||
} \
|
||||
} \
|
||||
|
@ -99,27 +99,23 @@ template <typename Executor, typename Function, typename Allocator>
|
||||
void strand_executor_service::dispatch(const implementation_type& impl,
|
||||
Executor& ex, ASIO_MOVE_ARG(Function) function, const Allocator& a)
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
typedef typename decay<Function>::type function_type;
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(function));
|
||||
|
||||
// If we are already in the strand then the function can run immediately.
|
||||
if (call_stack<strand_impl>::contains(impl.get()))
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(function));
|
||||
|
||||
fenced_block b(fenced_block::full);
|
||||
asio_handler_invoke_helpers::invoke(tmp, tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Allocator>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Allocator>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef executor_op<function_type, alloc_type> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
p.p = new (p.v) op(tmp, allocator);
|
||||
typedef executor_op<function_type, Allocator> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(function), a);
|
||||
|
||||
ASIO_HANDLER_CREATION((impl->service_->context(), *p.p,
|
||||
"strand_executor", impl.get(), 0, "dispatch"));
|
||||
@ -128,7 +124,7 @@ void strand_executor_service::dispatch(const implementation_type& impl,
|
||||
bool first = enqueue(impl, p.p);
|
||||
p.v = p.p = 0;
|
||||
if (first)
|
||||
ex.dispatch(invoker<Executor>(impl, ex), allocator);
|
||||
ex.dispatch(invoker<Executor>(impl, ex), a);
|
||||
}
|
||||
|
||||
// Request invocation of the given function and return immediately.
|
||||
@ -136,19 +132,12 @@ template <typename Executor, typename Function, typename Allocator>
|
||||
void strand_executor_service::post(const implementation_type& impl,
|
||||
Executor& ex, ASIO_MOVE_ARG(Function) function, const Allocator& a)
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
typedef typename decay<Function>::type function_type;
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(function));
|
||||
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Allocator>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Allocator>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef executor_op<function_type, alloc_type> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
p.p = new (p.v) op(tmp, allocator);
|
||||
typedef executor_op<function_type, Allocator> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(function), a);
|
||||
|
||||
ASIO_HANDLER_CREATION((impl->service_->context(), *p.p,
|
||||
"strand_executor", impl.get(), 0, "post"));
|
||||
@ -157,7 +146,7 @@ void strand_executor_service::post(const implementation_type& impl,
|
||||
bool first = enqueue(impl, p.p);
|
||||
p.v = p.p = 0;
|
||||
if (first)
|
||||
ex.post(invoker<Executor>(impl, ex), allocator);
|
||||
ex.post(invoker<Executor>(impl, ex), a);
|
||||
}
|
||||
|
||||
// Request invocation of the given function and return immediately.
|
||||
@ -165,19 +154,12 @@ template <typename Executor, typename Function, typename Allocator>
|
||||
void strand_executor_service::defer(const implementation_type& impl,
|
||||
Executor& ex, ASIO_MOVE_ARG(Function) function, const Allocator& a)
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
typedef typename decay<Function>::type function_type;
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(function));
|
||||
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Allocator>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Allocator>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef executor_op<function_type, alloc_type> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
p.p = new (p.v) op(tmp, allocator);
|
||||
typedef executor_op<function_type, Allocator> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(function), a);
|
||||
|
||||
ASIO_HANDLER_CREATION((impl->service_->context(), *p.p,
|
||||
"strand_executor", impl.get(), 0, "defer"));
|
||||
@ -186,7 +168,7 @@ void strand_executor_service::defer(const implementation_type& impl,
|
||||
bool first = enqueue(impl, p.p);
|
||||
p.v = p.p = 0;
|
||||
if (first)
|
||||
ex.defer(invoker<Executor>(impl, ex), allocator);
|
||||
ex.defer(invoker<Executor>(impl, ex), a);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
@ -39,15 +39,10 @@ public:
|
||||
template <typename F, typename Alloc>
|
||||
explicit function(F f, const Alloc& a)
|
||||
{
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Alloc>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Alloc>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef detail::executor_op<F, alloc_type> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
op_ = new (p.v) op(f, allocator);
|
||||
typedef detail::executor_op<F, Alloc> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
op_ = new (p.v) op(ASIO_MOVE_CAST(F)(f), a);
|
||||
p.v = 0;
|
||||
}
|
||||
|
||||
|
@ -226,27 +226,23 @@ template <typename Function, typename Allocator>
|
||||
void io_context::executor_type::dispatch(
|
||||
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
typedef typename decay<Function>::type function_type;
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(f));
|
||||
|
||||
// Invoke immediately if we are already inside the thread pool.
|
||||
if (io_context_.impl_.can_dispatch())
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(f));
|
||||
|
||||
detail::fenced_block b(detail::fenced_block::full);
|
||||
asio_handler_invoke_helpers::invoke(tmp, tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Allocator>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Allocator>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef detail::executor_op<function_type, alloc_type, detail::operation> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
p.p = new (p.v) op(tmp, allocator);
|
||||
typedef detail::executor_op<function_type, Allocator, detail::operation> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
|
||||
|
||||
ASIO_HANDLER_CREATION((this->context(), *p.p,
|
||||
"io_context", &this->context(), 0, "post"));
|
||||
@ -259,19 +255,12 @@ template <typename Function, typename Allocator>
|
||||
void io_context::executor_type::post(
|
||||
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
typedef typename decay<Function>::type function_type;
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(f));
|
||||
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Allocator>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Allocator>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef detail::executor_op<function_type, alloc_type, detail::operation> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
p.p = new (p.v) op(tmp, allocator);
|
||||
typedef detail::executor_op<function_type, Allocator, detail::operation> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
|
||||
|
||||
ASIO_HANDLER_CREATION((this->context(), *p.p,
|
||||
"io_context", &this->context(), 0, "post"));
|
||||
@ -284,19 +273,12 @@ template <typename Function, typename Allocator>
|
||||
void io_context::executor_type::defer(
|
||||
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
typedef typename decay<Function>::type function_type;
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(f));
|
||||
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Allocator>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Allocator>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef detail::executor_op<function_type, alloc_type, detail::operation> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
p.p = new (p.v) op(tmp, allocator);
|
||||
typedef detail::executor_op<function_type, Allocator, detail::operation> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
|
||||
|
||||
ASIO_HANDLER_CREATION((this->context(), *p.p,
|
||||
"io_context", &this->context(), 0, "defer"));
|
||||
|
@ -42,21 +42,14 @@ template <typename Function, typename Allocator>
|
||||
void system_executor::post(
|
||||
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
|
||||
{
|
||||
typedef typename decay<Function>::type function_type;
|
||||
|
||||
context_impl& ctx = detail::global<context_impl>();
|
||||
|
||||
// Make a local, non-const copy of the function.
|
||||
typedef typename decay<Function>::type function_type;
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(f));
|
||||
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Allocator>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Allocator>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef detail::executor_op<function_type, alloc_type> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
p.p = new (p.v) op(tmp, allocator);
|
||||
typedef detail::executor_op<function_type, Allocator> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
|
||||
|
||||
ASIO_HANDLER_CREATION((ctx, *p.p,
|
||||
"system_executor", &this->context(), 0, "post"));
|
||||
@ -69,21 +62,14 @@ template <typename Function, typename Allocator>
|
||||
void system_executor::defer(
|
||||
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
|
||||
{
|
||||
typedef typename decay<Function>::type function_type;
|
||||
|
||||
context_impl& ctx = detail::global<context_impl>();
|
||||
|
||||
// Make a local, non-const copy of the function.
|
||||
typedef typename decay<Function>::type function_type;
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(f));
|
||||
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Allocator>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Allocator>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef detail::executor_op<function_type, alloc_type> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
p.p = new (p.v) op(tmp, allocator);
|
||||
typedef detail::executor_op<function_type, Allocator> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
|
||||
|
||||
ASIO_HANDLER_CREATION((ctx, *p.p,
|
||||
"system_executor", &this->context(), 0, "defer"));
|
||||
|
@ -53,27 +53,23 @@ template <typename Function, typename Allocator>
|
||||
void thread_pool::executor_type::dispatch(
|
||||
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
typedef typename decay<Function>::type function_type;
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(f));
|
||||
|
||||
// Invoke immediately if we are already inside the thread pool.
|
||||
if (pool_.scheduler_.can_dispatch())
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(f));
|
||||
|
||||
detail::fenced_block b(detail::fenced_block::full);
|
||||
asio_handler_invoke_helpers::invoke(tmp, tmp);
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Allocator>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Allocator>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef detail::executor_op<function_type, alloc_type> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
p.p = new (p.v) op(tmp, allocator);
|
||||
typedef detail::executor_op<function_type, Allocator> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
|
||||
|
||||
ASIO_HANDLER_CREATION((pool_, *p.p,
|
||||
"thread_pool", &this->context(), 0, "dispatch"));
|
||||
@ -86,19 +82,12 @@ template <typename Function, typename Allocator>
|
||||
void thread_pool::executor_type::post(
|
||||
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
typedef typename decay<Function>::type function_type;
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(f));
|
||||
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Allocator>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Allocator>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef detail::executor_op<function_type, alloc_type> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
p.p = new (p.v) op(tmp, allocator);
|
||||
typedef detail::executor_op<function_type, Allocator> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
|
||||
|
||||
ASIO_HANDLER_CREATION((pool_, *p.p,
|
||||
"thread_pool", &this->context(), 0, "post"));
|
||||
@ -111,19 +100,12 @@ template <typename Function, typename Allocator>
|
||||
void thread_pool::executor_type::defer(
|
||||
ASIO_MOVE_ARG(Function) f, const Allocator& a) const
|
||||
{
|
||||
// Make a local, non-const copy of the function.
|
||||
typedef typename decay<Function>::type function_type;
|
||||
function_type tmp(ASIO_MOVE_CAST(Function)(f));
|
||||
|
||||
// Construct an allocator to be used for the operation.
|
||||
typedef typename detail::get_recycling_allocator<Allocator>::type alloc_type;
|
||||
alloc_type allocator(detail::get_recycling_allocator<Allocator>::get(a));
|
||||
|
||||
// Allocate and construct an operation to wrap the function.
|
||||
typedef detail::executor_op<function_type, alloc_type> op;
|
||||
typename op::ptr p = { allocator, 0, 0 };
|
||||
p.v = p.a.allocate(1);
|
||||
p.p = new (p.v) op(tmp, allocator);
|
||||
typedef detail::executor_op<function_type, Allocator> op;
|
||||
typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
|
||||
p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);
|
||||
|
||||
ASIO_HANDLER_CREATION((pool_, *p.p,
|
||||
"thread_pool", &this->context(), 0, "defer"));
|
||||
|
Loading…
Reference in New Issue
Block a user