mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
Add tests for bind_back_handler
This commit is contained in:
@ -6,6 +6,7 @@ Version 202
|
|||||||
* Refactor async_op_base
|
* Refactor async_op_base
|
||||||
* Use async_op_base
|
* Use async_op_base
|
||||||
* async_op_base is a public interface
|
* async_op_base is a public interface
|
||||||
|
* Add tests for bind_back_handler
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ class bind_wrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using result_type = void;
|
using result_type = void; // asio needs this
|
||||||
|
|
||||||
bind_wrapper(bind_wrapper&&) = default;
|
bind_wrapper(bind_wrapper&&) = default;
|
||||||
bind_wrapper(bind_wrapper const&) = default;
|
bind_wrapper(bind_wrapper const&) = default;
|
||||||
@ -222,268 +222,11 @@ class bind_front_wrapper;
|
|||||||
//
|
//
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// 0-arg specialization
|
template<class Handler, class... Args>
|
||||||
template<class Handler>
|
class bind_front_wrapper
|
||||||
class bind_front_wrapper<Handler>
|
|
||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
|
detail::tuple<Args...> args_;
|
||||||
template<class T, class Executor>
|
|
||||||
friend struct net::associated_executor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using result_type = void;
|
|
||||||
|
|
||||||
bind_front_wrapper(bind_front_wrapper&&) = default;
|
|
||||||
bind_front_wrapper(bind_front_wrapper const&) = default;
|
|
||||||
|
|
||||||
template<class Handler_>
|
|
||||||
explicit
|
|
||||||
bind_front_wrapper(Handler_&& handler)
|
|
||||||
: h_(std::forward<Handler_>(handler))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class... Ts>
|
|
||||||
void operator()(Ts&&... ts)
|
|
||||||
{
|
|
||||||
h_(std::forward<Ts>(ts)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
using allocator_type =
|
|
||||||
net::associated_allocator_t<Handler>;
|
|
||||||
|
|
||||||
allocator_type
|
|
||||||
get_allocator() const noexcept
|
|
||||||
{
|
|
||||||
return net::get_associated_allocator(h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Function>
|
|
||||||
friend
|
|
||||||
void asio_handler_invoke(
|
|
||||||
Function&& f, bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_invoke;
|
|
||||||
asio_handler_invoke(f, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool asio_handler_is_continuation(
|
|
||||||
bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_is_continuation;
|
|
||||||
return asio_handler_is_continuation(
|
|
||||||
std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void* asio_handler_allocate(
|
|
||||||
std::size_t size, bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_allocate;
|
|
||||||
return asio_handler_allocate(
|
|
||||||
size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void asio_handler_deallocate(
|
|
||||||
void* p, std::size_t size, bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_deallocate;
|
|
||||||
asio_handler_deallocate(
|
|
||||||
p, size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// 1-arg specialization
|
|
||||||
template<class Handler, class Arg>
|
|
||||||
class bind_front_wrapper<Handler, Arg>
|
|
||||||
{
|
|
||||||
Handler h_;
|
|
||||||
Arg arg_;
|
|
||||||
|
|
||||||
template<class T, class Executor>
|
|
||||||
friend struct net::associated_executor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using result_type = void;
|
|
||||||
|
|
||||||
bind_front_wrapper(bind_front_wrapper&&) = default;
|
|
||||||
bind_front_wrapper(bind_front_wrapper const&) = default;
|
|
||||||
|
|
||||||
template<
|
|
||||||
class Handler_,
|
|
||||||
class Arg_>
|
|
||||||
bind_front_wrapper(
|
|
||||||
Handler_&& handler,
|
|
||||||
Arg_&& arg)
|
|
||||||
: h_(std::forward<Handler_>(handler))
|
|
||||||
, arg_(std::forward<Arg_>(arg))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class... Ts>
|
|
||||||
void operator()(Ts&&... ts)
|
|
||||||
{
|
|
||||||
h_( std::move(arg_),
|
|
||||||
std::forward<Ts>(ts)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
using allocator_type =
|
|
||||||
net::associated_allocator_t<Handler>;
|
|
||||||
|
|
||||||
allocator_type
|
|
||||||
get_allocator() const noexcept
|
|
||||||
{
|
|
||||||
return net::get_associated_allocator(h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Function>
|
|
||||||
friend
|
|
||||||
void asio_handler_invoke(
|
|
||||||
Function&& f, bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_invoke;
|
|
||||||
asio_handler_invoke(f, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool asio_handler_is_continuation(
|
|
||||||
bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_is_continuation;
|
|
||||||
return asio_handler_is_continuation(
|
|
||||||
std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void* asio_handler_allocate(
|
|
||||||
std::size_t size, bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_allocate;
|
|
||||||
return asio_handler_allocate(
|
|
||||||
size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void asio_handler_deallocate(
|
|
||||||
void* p, std::size_t size, bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_deallocate;
|
|
||||||
asio_handler_deallocate(
|
|
||||||
p, size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// 2-arg specialization
|
|
||||||
template<class Handler, class Arg1, class Arg2>
|
|
||||||
class bind_front_wrapper<Handler, Arg1, Arg2>
|
|
||||||
{
|
|
||||||
Handler h_;
|
|
||||||
Arg1 arg1_;
|
|
||||||
Arg2 arg2_;
|
|
||||||
|
|
||||||
template<class T, class Executor>
|
|
||||||
friend struct net::associated_executor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using result_type = void;
|
|
||||||
|
|
||||||
bind_front_wrapper(bind_front_wrapper&&) = default;
|
|
||||||
bind_front_wrapper(bind_front_wrapper const&) = default;
|
|
||||||
|
|
||||||
template<
|
|
||||||
class Handler_,
|
|
||||||
class Arg1_,
|
|
||||||
class Arg2_>
|
|
||||||
bind_front_wrapper(
|
|
||||||
Handler_&& handler,
|
|
||||||
Arg1_&& arg1,
|
|
||||||
Arg2_&& arg2)
|
|
||||||
: h_(std::forward<Handler_>(handler))
|
|
||||||
, arg1_(std::forward<Arg1_>(arg1))
|
|
||||||
, arg2_(std::forward<Arg2_>(arg2))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class... Ts>
|
|
||||||
void operator()(Ts&&... ts)
|
|
||||||
{
|
|
||||||
h_( std::move(arg1_),
|
|
||||||
std::move(arg2_),
|
|
||||||
std::forward<Ts>(ts)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
using allocator_type =
|
|
||||||
net::associated_allocator_t<Handler>;
|
|
||||||
|
|
||||||
allocator_type
|
|
||||||
get_allocator() const noexcept
|
|
||||||
{
|
|
||||||
return net::get_associated_allocator(h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Function>
|
|
||||||
friend
|
|
||||||
void asio_handler_invoke(
|
|
||||||
Function&& f, bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_invoke;
|
|
||||||
asio_handler_invoke(f, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool asio_handler_is_continuation(
|
|
||||||
bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_is_continuation;
|
|
||||||
return asio_handler_is_continuation(
|
|
||||||
std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void* asio_handler_allocate(
|
|
||||||
std::size_t size, bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_allocate;
|
|
||||||
return asio_handler_allocate(
|
|
||||||
size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void asio_handler_deallocate(
|
|
||||||
void* p, std::size_t size, bind_front_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_deallocate;
|
|
||||||
asio_handler_deallocate(
|
|
||||||
p, size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// 3+ arg specialization
|
|
||||||
template<
|
|
||||||
class Handler,
|
|
||||||
class Arg1, class Arg2, class Arg3,
|
|
||||||
class... Args>
|
|
||||||
class bind_front_wrapper<
|
|
||||||
Handler, Arg1, Arg2, Arg3, Args...>
|
|
||||||
{
|
|
||||||
Handler h_;
|
|
||||||
detail::tuple<
|
|
||||||
Arg1, Arg2, Arg3, Args...> args_;
|
|
||||||
|
|
||||||
template<class T, class Executor>
|
template<class T, class Executor>
|
||||||
friend struct net::associated_executor;
|
friend struct net::associated_executor;
|
||||||
@ -499,27 +242,17 @@ class bind_front_wrapper<
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using result_type = void;
|
using result_type = void; // asio needs this
|
||||||
|
|
||||||
bind_front_wrapper(bind_front_wrapper&&) = default;
|
bind_front_wrapper(bind_front_wrapper&&) = default;
|
||||||
bind_front_wrapper(bind_front_wrapper const&) = default;
|
bind_front_wrapper(bind_front_wrapper const&) = default;
|
||||||
|
|
||||||
template<
|
template<class Handler_, class... Args_>
|
||||||
class Handler_,
|
|
||||||
class Arg1_, class Arg2_, class Arg3_,
|
|
||||||
class... Args_>
|
|
||||||
bind_front_wrapper(
|
bind_front_wrapper(
|
||||||
Handler_&& handler,
|
Handler_&& handler,
|
||||||
Arg1_&& arg1,
|
|
||||||
Arg2_&& arg2,
|
|
||||||
Arg3_&& arg3,
|
|
||||||
Args_&&... args)
|
Args_&&... args)
|
||||||
: h_(std::forward<Handler_>(handler))
|
: h_(std::forward<Handler_>(handler))
|
||||||
, args_(
|
, args_(std::forward<Args_>(args)...)
|
||||||
std::forward<Arg1_>(arg1),
|
|
||||||
std::forward<Arg2_>(arg2),
|
|
||||||
std::forward<Arg3_>(arg3),
|
|
||||||
std::forward<Args_>(args)...)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,8 +260,7 @@ public:
|
|||||||
void operator()(Ts&&... ts)
|
void operator()(Ts&&... ts)
|
||||||
{
|
{
|
||||||
invoke(
|
invoke(
|
||||||
mp11::index_sequence_for<
|
mp11::index_sequence_for<Args...>{},
|
||||||
Arg1, Arg2, Arg3, Args...>{},
|
|
||||||
std::forward<Ts>(ts)...);
|
std::forward<Ts>(ts)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -596,7 +328,7 @@ class bind_front_wrapper<
|
|||||||
std::size_t n_;
|
std::size_t n_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using result_type = void;
|
using result_type = void; // asio needs this
|
||||||
|
|
||||||
bind_front_wrapper(bind_front_wrapper&&) = default;
|
bind_front_wrapper(bind_front_wrapper&&) = default;
|
||||||
bind_front_wrapper(bind_front_wrapper const&) = default;
|
bind_front_wrapper(bind_front_wrapper const&) = default;
|
||||||
@ -670,268 +402,11 @@ public:
|
|||||||
//
|
//
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// 0-arg specialization
|
template<class Handler, class... Args>
|
||||||
template<class Handler>
|
class bind_back_wrapper
|
||||||
class bind_back_wrapper<Handler>
|
|
||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
|
detail::tuple<Args...> args_;
|
||||||
template<class T, class Executor>
|
|
||||||
friend struct net::associated_executor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using result_type = void;
|
|
||||||
|
|
||||||
bind_back_wrapper(bind_back_wrapper&&) = default;
|
|
||||||
bind_back_wrapper(bind_back_wrapper const&) = default;
|
|
||||||
|
|
||||||
template<class Handler_>
|
|
||||||
explicit
|
|
||||||
bind_back_wrapper(Handler_&& handler)
|
|
||||||
: h_(std::forward<Handler_>(handler))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class... Ts>
|
|
||||||
void operator()(Ts&&... ts)
|
|
||||||
{
|
|
||||||
h_(std::forward<Ts>(ts)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
using allocator_type =
|
|
||||||
net::associated_allocator_t<Handler>;
|
|
||||||
|
|
||||||
allocator_type
|
|
||||||
get_allocator() const noexcept
|
|
||||||
{
|
|
||||||
return net::get_associated_allocator(h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Function>
|
|
||||||
friend
|
|
||||||
void asio_handler_invoke(
|
|
||||||
Function&& f, bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_invoke;
|
|
||||||
asio_handler_invoke(f, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool asio_handler_is_continuation(
|
|
||||||
bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_is_continuation;
|
|
||||||
return asio_handler_is_continuation(
|
|
||||||
std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void* asio_handler_allocate(
|
|
||||||
std::size_t size, bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_allocate;
|
|
||||||
return asio_handler_allocate(
|
|
||||||
size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void asio_handler_deallocate(
|
|
||||||
void* p, std::size_t size, bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_deallocate;
|
|
||||||
asio_handler_deallocate(
|
|
||||||
p, size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// 1-arg specialization
|
|
||||||
template<class Handler, class Arg>
|
|
||||||
class bind_back_wrapper<Handler, Arg>
|
|
||||||
{
|
|
||||||
Handler h_;
|
|
||||||
Arg arg_;
|
|
||||||
|
|
||||||
template<class T, class Executor>
|
|
||||||
friend struct net::associated_executor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using result_type = void;
|
|
||||||
|
|
||||||
bind_back_wrapper(bind_back_wrapper&&) = default;
|
|
||||||
bind_back_wrapper(bind_back_wrapper const&) = default;
|
|
||||||
|
|
||||||
template<
|
|
||||||
class Handler_,
|
|
||||||
class Arg_>
|
|
||||||
bind_back_wrapper(
|
|
||||||
Handler_&& handler,
|
|
||||||
Arg_&& arg)
|
|
||||||
: h_(std::forward<Handler_>(handler))
|
|
||||||
, arg_(std::forward<Arg_>(arg))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class... Ts>
|
|
||||||
void operator()(Ts&&... ts)
|
|
||||||
{
|
|
||||||
h_( std::forward<Ts>(ts)...,
|
|
||||||
std::move(arg_));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
using allocator_type =
|
|
||||||
net::associated_allocator_t<Handler>;
|
|
||||||
|
|
||||||
allocator_type
|
|
||||||
get_allocator() const noexcept
|
|
||||||
{
|
|
||||||
return net::get_associated_allocator(h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Function>
|
|
||||||
friend
|
|
||||||
void asio_handler_invoke(
|
|
||||||
Function&& f, bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_invoke;
|
|
||||||
asio_handler_invoke(f, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool asio_handler_is_continuation(
|
|
||||||
bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_is_continuation;
|
|
||||||
return asio_handler_is_continuation(
|
|
||||||
std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void* asio_handler_allocate(
|
|
||||||
std::size_t size, bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_allocate;
|
|
||||||
return asio_handler_allocate(
|
|
||||||
size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void asio_handler_deallocate(
|
|
||||||
void* p, std::size_t size, bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_deallocate;
|
|
||||||
asio_handler_deallocate(
|
|
||||||
p, size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// 2-arg specialization
|
|
||||||
template<class Handler, class Arg1, class Arg2>
|
|
||||||
class bind_back_wrapper<Handler, Arg1, Arg2>
|
|
||||||
{
|
|
||||||
Handler h_;
|
|
||||||
Arg1 arg1_;
|
|
||||||
Arg2 arg2_;
|
|
||||||
|
|
||||||
template<class T, class Executor>
|
|
||||||
friend struct net::associated_executor;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using result_type = void;
|
|
||||||
|
|
||||||
bind_back_wrapper(bind_back_wrapper&&) = default;
|
|
||||||
bind_back_wrapper(bind_back_wrapper const&) = default;
|
|
||||||
|
|
||||||
template<
|
|
||||||
class Handler_,
|
|
||||||
class Arg1_,
|
|
||||||
class Arg2_>
|
|
||||||
bind_back_wrapper(
|
|
||||||
Handler_&& handler,
|
|
||||||
Arg1_&& arg1,
|
|
||||||
Arg2_&& arg2)
|
|
||||||
: h_(std::forward<Handler_>(handler))
|
|
||||||
, arg1_(std::forward<Arg1_>(arg1))
|
|
||||||
, arg2_(std::forward<Arg2_>(arg2))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class... Ts>
|
|
||||||
void operator()(Ts&&... ts)
|
|
||||||
{
|
|
||||||
h_( std::forward<Ts>(ts)...,
|
|
||||||
std::move(arg1_),
|
|
||||||
std::move(arg2_));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
using allocator_type =
|
|
||||||
net::associated_allocator_t<Handler>;
|
|
||||||
|
|
||||||
allocator_type
|
|
||||||
get_allocator() const noexcept
|
|
||||||
{
|
|
||||||
return net::get_associated_allocator(h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Function>
|
|
||||||
friend
|
|
||||||
void asio_handler_invoke(
|
|
||||||
Function&& f, bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_invoke;
|
|
||||||
asio_handler_invoke(f, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool asio_handler_is_continuation(
|
|
||||||
bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_is_continuation;
|
|
||||||
return asio_handler_is_continuation(
|
|
||||||
std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void* asio_handler_allocate(
|
|
||||||
std::size_t size, bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_allocate;
|
|
||||||
return asio_handler_allocate(
|
|
||||||
size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void asio_handler_deallocate(
|
|
||||||
void* p, std::size_t size, bind_back_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_deallocate;
|
|
||||||
asio_handler_deallocate(
|
|
||||||
p, size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// 3+ arg specialization
|
|
||||||
template<
|
|
||||||
class Handler,
|
|
||||||
class Arg1, class Arg2, class Arg3,
|
|
||||||
class... Args>
|
|
||||||
class bind_back_wrapper<
|
|
||||||
Handler, Arg1, Arg2, Arg3, Args...>
|
|
||||||
{
|
|
||||||
Handler h_;
|
|
||||||
detail::tuple<
|
|
||||||
Arg1, Arg2, Arg3, Args...> args_;
|
|
||||||
|
|
||||||
template<class T, class Executor>
|
template<class T, class Executor>
|
||||||
friend struct net::associated_executor;
|
friend struct net::associated_executor;
|
||||||
@ -947,27 +422,15 @@ class bind_back_wrapper<
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using result_type = void;
|
using result_type = void; // asio needs this
|
||||||
|
|
||||||
bind_back_wrapper(bind_back_wrapper&&) = default;
|
bind_back_wrapper(bind_back_wrapper&&) = default;
|
||||||
bind_back_wrapper(bind_back_wrapper const&) = default;
|
bind_back_wrapper(bind_back_wrapper const&) = default;
|
||||||
|
|
||||||
template<
|
template<class Handler_, class... Args_>
|
||||||
class Handler_,
|
bind_back_wrapper(Handler_&& handler, Args_&&... args)
|
||||||
class Arg1_, class Arg2_, class Arg3_,
|
|
||||||
class... Args_>
|
|
||||||
bind_back_wrapper(
|
|
||||||
Handler_&& handler,
|
|
||||||
Arg1_&& arg1,
|
|
||||||
Arg2_&& arg2,
|
|
||||||
Arg3_&& arg3,
|
|
||||||
Args_&&... args)
|
|
||||||
: h_(std::forward<Handler_>(handler))
|
: h_(std::forward<Handler_>(handler))
|
||||||
, args_(
|
, args_(std::forward<Args_>(args)...)
|
||||||
std::forward<Arg1_>(arg1),
|
|
||||||
std::forward<Arg2_>(arg2),
|
|
||||||
std::forward<Arg3_>(arg3),
|
|
||||||
std::forward<Args_>(args)...)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -975,8 +438,7 @@ public:
|
|||||||
void operator()(Ts&&... ts)
|
void operator()(Ts&&... ts)
|
||||||
{
|
{
|
||||||
invoke(
|
invoke(
|
||||||
mp11::index_sequence_for<
|
mp11::index_sequence_for<Args...>{},
|
||||||
Arg1, Arg2, Arg3, Args...>{},
|
|
||||||
std::forward<Ts>(ts)...);
|
std::forward<Ts>(ts)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1044,7 +506,7 @@ class bind_back_wrapper<
|
|||||||
std::size_t n_;
|
std::size_t n_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using result_type = void;
|
using result_type = void; // asio needs this
|
||||||
|
|
||||||
bind_back_wrapper(bind_back_wrapper&&) = default;
|
bind_back_wrapper(bind_back_wrapper&&) = default;
|
||||||
bind_back_wrapper(bind_back_wrapper const&) = default;
|
bind_back_wrapper(bind_back_wrapper const&) = default;
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <boost/beast/core/bind_handler.hpp>
|
#include <boost/beast/core/bind_handler.hpp>
|
||||||
|
|
||||||
|
#include "test_handler.hpp"
|
||||||
|
|
||||||
#include <boost/beast/core/detail/type_traits.hpp>
|
#include <boost/beast/core/detail/type_traits.hpp>
|
||||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
#include <boost/beast/_experimental/test/stream.hpp>
|
#include <boost/beast/_experimental/test/stream.hpp>
|
||||||
@ -28,8 +30,6 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class bind_handler_test : public unit_test::suite
|
class bind_handler_test : public unit_test::suite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -42,54 +42,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class AsyncReadStream, class ReadHandler>
|
|
||||||
void
|
|
||||||
signal_aborted (AsyncReadStream& stream, ReadHandler&& handler)
|
|
||||||
{
|
|
||||||
net::post(
|
|
||||||
stream.get_executor(),
|
|
||||||
bind_handler (std::forward <ReadHandler> (handler),
|
|
||||||
net::error::operation_aborted, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class AsyncReadStream, class ReadHandler>
|
|
||||||
void
|
|
||||||
signal_eof (AsyncReadStream& stream, ReadHandler&& handler)
|
|
||||||
{
|
|
||||||
net::post(
|
|
||||||
stream.get_executor(),
|
|
||||||
bind_front_handler (std::forward<ReadHandler> (handler),
|
|
||||||
net::error::eof, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class AsyncReadStream, class ReadHandler>
|
|
||||||
void
|
|
||||||
signal_unreachable (AsyncReadStream& stream, ReadHandler&& handler)
|
|
||||||
{
|
|
||||||
net::post(
|
|
||||||
stream.get_executor(),
|
|
||||||
bind_back_handler (std::forward<ReadHandler> (handler),
|
|
||||||
net::error::network_unreachable, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
testJavadocs()
|
|
||||||
{
|
|
||||||
BEAST_EXPECT((
|
|
||||||
&bind_handler_test::signal_aborted<
|
|
||||||
test::stream, handler<error_code, std::size_t>>));
|
|
||||||
|
|
||||||
BEAST_EXPECT((
|
|
||||||
&bind_handler_test::signal_eof<
|
|
||||||
test::stream, handler<error_code, std::size_t>>));
|
|
||||||
|
|
||||||
BEAST_EXPECT((
|
|
||||||
&bind_handler_test::signal_unreachable<
|
|
||||||
test::stream, handler<error_code, std::size_t>>));
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
struct copyable
|
struct copyable
|
||||||
{
|
{
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
@ -307,6 +259,12 @@ public:
|
|||||||
{
|
{
|
||||||
std::bind(bind_front_handler(test_cb{*this}));
|
std::bind(bind_front_handler(test_cb{*this}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
failStdBindBack()
|
||||||
|
{
|
||||||
|
std::bind(bind_back_handler(test_cb{*this}));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
@ -440,6 +398,13 @@ public:
|
|||||||
bind_handler(test_cb{*this}, 42));
|
bind_handler(test_cb{*this}, 42));
|
||||||
ioc.run();
|
ioc.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// legacy hooks
|
||||||
|
legacy_handler::test(*this,
|
||||||
|
[](legacy_handler h)
|
||||||
|
{
|
||||||
|
return bind_handler(h);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -513,14 +478,165 @@ public:
|
|||||||
test_executor(*this, ioc), test_cb{*this}),
|
test_executor(*this, ioc), test_cb{*this}),
|
||||||
ec, n));
|
ec, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// legacy hooks
|
||||||
|
legacy_handler::test(*this,
|
||||||
|
[](legacy_handler h)
|
||||||
|
{
|
||||||
|
return bind_front_handler(h);
|
||||||
|
});
|
||||||
|
legacy_handler::test(*this,
|
||||||
|
[](legacy_handler h)
|
||||||
|
{
|
||||||
|
return bind_front_handler(
|
||||||
|
h, error_code{}, std::size_t{});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
testBindBackHandler()
|
||||||
|
{
|
||||||
|
using m1 = move_arg<1>;
|
||||||
|
using m2 = move_arg<2>;
|
||||||
|
|
||||||
|
// 0-ary
|
||||||
|
bind_back_handler(test_cb{*this})();
|
||||||
|
|
||||||
|
// 1-ary
|
||||||
|
bind_back_handler(test_cb{*this}, 42)();
|
||||||
|
bind_back_handler(test_cb{*this})(42);
|
||||||
|
|
||||||
|
// 2-ary
|
||||||
|
bind_back_handler(test_cb{*this}, 42, "s")();
|
||||||
|
bind_back_handler(test_cb{*this}, "s")(42);
|
||||||
|
bind_back_handler(test_cb{*this})(42, "s");
|
||||||
|
|
||||||
|
// 3-ary
|
||||||
|
bind_back_handler(test_cb{*this}, 42, "s", m1{})();
|
||||||
|
bind_back_handler(test_cb{*this}, m1{})(42, "s");
|
||||||
|
bind_back_handler(test_cb{*this}, "s", m1{})(42);
|
||||||
|
bind_back_handler(test_cb{*this})(42, "s", m1{});
|
||||||
|
|
||||||
|
// 4-ary
|
||||||
|
bind_back_handler(test_cb{*this}, 42, "s", m1{}, m2{})();
|
||||||
|
bind_back_handler(test_cb{*this}, "s", m1{}, m2{})(42);
|
||||||
|
bind_back_handler(test_cb{*this}, m1{}, m2{})(42, "s");
|
||||||
|
bind_back_handler(test_cb{*this}, "s", m1{}, m2{})(42);
|
||||||
|
bind_back_handler(test_cb{*this})(42, "s", m1{}, m2{});
|
||||||
|
|
||||||
|
error_code ec;
|
||||||
|
std::size_t n = 256;
|
||||||
|
|
||||||
|
// void(error_code, size_t)
|
||||||
|
bind_back_handler(test_cb{*this}, ec, n)();
|
||||||
|
|
||||||
|
// void(error_code, size_t)(string_view)
|
||||||
|
bind_back_handler(test_cb{*this}, "s")(ec, n);
|
||||||
|
|
||||||
|
// perfect forwarding
|
||||||
|
{
|
||||||
|
std::shared_ptr<int> const sp =
|
||||||
|
std::make_shared<int>(42);
|
||||||
|
bind_back_handler(test_cb{*this}, sp)();
|
||||||
|
BEAST_EXPECT(sp.get() != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// associated executor
|
||||||
|
{
|
||||||
|
net::io_context ioc;
|
||||||
|
|
||||||
|
testHooks(ioc, bind_back_handler(net::bind_executor(
|
||||||
|
test_executor(*this, ioc), test_cb{*this})
|
||||||
|
));
|
||||||
|
testHooks(ioc, bind_back_handler(net::bind_executor(
|
||||||
|
test_executor(*this, ioc), test_cb{*this}),
|
||||||
|
42));
|
||||||
|
testHooks(ioc, bind_back_handler(net::bind_executor(
|
||||||
|
test_executor(*this, ioc), test_cb{*this}),
|
||||||
|
42, "s"));
|
||||||
|
testHooks(ioc, bind_back_handler(net::bind_executor(
|
||||||
|
test_executor(*this, ioc), test_cb{*this}),
|
||||||
|
42, "s", m1{}));
|
||||||
|
testHooks(ioc, bind_back_handler(net::bind_executor(
|
||||||
|
test_executor(*this, ioc), test_cb{*this}),
|
||||||
|
42, "s", m1{}, m2{}));
|
||||||
|
testHooks(ioc, bind_back_handler(net::bind_executor(
|
||||||
|
test_executor(*this, ioc), test_cb{*this}),
|
||||||
|
ec, n));
|
||||||
|
}
|
||||||
|
|
||||||
|
// legacy hooks
|
||||||
|
legacy_handler::test(*this,
|
||||||
|
[](legacy_handler h)
|
||||||
|
{
|
||||||
|
return bind_back_handler(h);
|
||||||
|
});
|
||||||
|
legacy_handler::test(*this,
|
||||||
|
[](legacy_handler h)
|
||||||
|
{
|
||||||
|
return bind_back_handler(
|
||||||
|
h, error_code{}, std::size_t{});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template <class AsyncReadStream, class ReadHandler>
|
||||||
|
void
|
||||||
|
signal_aborted (AsyncReadStream& stream, ReadHandler&& handler)
|
||||||
|
{
|
||||||
|
net::post(
|
||||||
|
stream.get_executor(),
|
||||||
|
bind_handler (std::forward <ReadHandler> (handler),
|
||||||
|
net::error::operation_aborted, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class AsyncReadStream, class ReadHandler>
|
||||||
|
void
|
||||||
|
signal_eof (AsyncReadStream& stream, ReadHandler&& handler)
|
||||||
|
{
|
||||||
|
net::post(
|
||||||
|
stream.get_executor(),
|
||||||
|
bind_front_handler (std::forward<ReadHandler> (handler),
|
||||||
|
net::error::eof, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class AsyncReadStream, class ReadHandler>
|
||||||
|
void
|
||||||
|
signal_unreachable (AsyncReadStream& stream, ReadHandler&& handler)
|
||||||
|
{
|
||||||
|
net::post(
|
||||||
|
stream.get_executor(),
|
||||||
|
bind_back_handler (std::forward<ReadHandler> (handler),
|
||||||
|
net::error::network_unreachable, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testJavadocs()
|
||||||
|
{
|
||||||
|
BEAST_EXPECT((
|
||||||
|
&bind_handler_test::signal_aborted<
|
||||||
|
test::stream, handler<error_code, std::size_t>>));
|
||||||
|
|
||||||
|
BEAST_EXPECT((
|
||||||
|
&bind_handler_test::signal_eof<
|
||||||
|
test::stream, handler<error_code, std::size_t>>));
|
||||||
|
|
||||||
|
BEAST_EXPECT((
|
||||||
|
&bind_handler_test::signal_unreachable<
|
||||||
|
test::stream, handler<error_code, std::size_t>>));
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
testJavadocs();
|
|
||||||
testBindHandler();
|
testBindHandler();
|
||||||
testBindFrontHandler();
|
testBindFrontHandler();
|
||||||
|
testBindBackHandler();
|
||||||
|
testJavadocs();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
129
test/beast/core/test_handler.hpp
Normal file
129
test/beast/core/test_handler.hpp
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail 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)
|
||||||
|
//
|
||||||
|
// Official repository: https://github.com/boostorg/beast
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef BOOST_BEAST_TEST_HANDLER_HPP
|
||||||
|
#define BOOST_BEAST_TEST_HANDLER_HPP
|
||||||
|
|
||||||
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
|
#include <boost/asio/associated_executor.hpp>
|
||||||
|
#include <boost/asio/handler_alloc_hook.hpp>
|
||||||
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
// Used to test the legacy handler hooks
|
||||||
|
struct legacy_handler
|
||||||
|
{
|
||||||
|
bool& hook_invoked;
|
||||||
|
|
||||||
|
struct executor
|
||||||
|
{
|
||||||
|
void* context() { return nullptr; }
|
||||||
|
void on_work_started() {}
|
||||||
|
void on_work_finished() {}
|
||||||
|
template<class F> void dispatch(F&&) {}
|
||||||
|
template<class F> void post(F&&) {}
|
||||||
|
template<class F> void defer(F&&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
executor
|
||||||
|
get_executor() const noexcept
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Signature of `f` is H<legacy_handler> where H is the wrapper to test
|
||||||
|
template<class F>
|
||||||
|
static
|
||||||
|
void
|
||||||
|
test(unit_test::suite& suite, F const& f)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
bool hook_invoked = false;
|
||||||
|
bool lambda_invoked = false;
|
||||||
|
auto h = f(legacy_handler{hook_invoked});
|
||||||
|
using net::asio_handler_invoke;
|
||||||
|
asio_handler_invoke(
|
||||||
|
[&lambda_invoked]
|
||||||
|
{
|
||||||
|
lambda_invoked =true;
|
||||||
|
}, &h);
|
||||||
|
suite.BEAST_EXPECT(hook_invoked);
|
||||||
|
suite.BEAST_EXPECT(lambda_invoked);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bool hook_invoked = false;
|
||||||
|
auto h = f(legacy_handler{hook_invoked});
|
||||||
|
using net::asio_handler_allocate;
|
||||||
|
asio_handler_allocate(0, &h);
|
||||||
|
suite.BEAST_EXPECT(hook_invoked);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bool hook_invoked = false;
|
||||||
|
auto h = f(legacy_handler{hook_invoked});
|
||||||
|
using net::asio_handler_deallocate;
|
||||||
|
asio_handler_deallocate(nullptr, 0, &h);
|
||||||
|
suite.BEAST_EXPECT(hook_invoked);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bool hook_invoked = false;
|
||||||
|
auto h = f(legacy_handler{hook_invoked});
|
||||||
|
using net::asio_handler_is_continuation;
|
||||||
|
asio_handler_is_continuation(&h);
|
||||||
|
suite.BEAST_EXPECT(hook_invoked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Function>
|
||||||
|
void
|
||||||
|
asio_handler_invoke(
|
||||||
|
Function&& f,
|
||||||
|
legacy_handler* p)
|
||||||
|
{
|
||||||
|
p->hook_invoked = true;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
void*
|
||||||
|
asio_handler_allocate(
|
||||||
|
std::size_t,
|
||||||
|
legacy_handler* p)
|
||||||
|
{
|
||||||
|
p->hook_invoked = true;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
asio_handler_deallocate(
|
||||||
|
void*, std::size_t,
|
||||||
|
legacy_handler* p)
|
||||||
|
{
|
||||||
|
p->hook_invoked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool
|
||||||
|
asio_handler_is_continuation(
|
||||||
|
legacy_handler* p)
|
||||||
|
{
|
||||||
|
p->hook_invoked = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
#endif
|
Reference in New Issue
Block a user