mirror of
https://github.com/boostorg/beast.git
synced 2025-08-01 22:04:34 +02:00
Fix bind_handler, bind_front_handler:
This tidies up small corner cases and bugs with the bind_handler and bind_front_handler wrappers: * Legacy allocation hooks are deleted * Fixes for bind_front_handler specializations * Decay bound arguments first, to reduce template instantiations * Proper moving and forwarding of bound arguments and call parameters
This commit is contained in:
@@ -8,6 +8,7 @@ Version 198:
|
|||||||
* Add buffer_traits.hpp, buffers_type
|
* Add buffer_traits.hpp, buffers_type
|
||||||
* Tidy up experimental files
|
* Tidy up experimental files
|
||||||
* Tidy up core files
|
* Tidy up core files
|
||||||
|
* Fix bind_handler, bind_front_handler
|
||||||
|
|
||||||
API Changes:
|
API Changes:
|
||||||
|
|
||||||
|
@@ -108,12 +108,16 @@ __implementation_defined__
|
|||||||
#else
|
#else
|
||||||
auto
|
auto
|
||||||
#endif
|
#endif
|
||||||
bind_front_handler(Handler&& handler, Args&&... args) ->
|
bind_front_handler(
|
||||||
detail::bind_front_wrapper<typename
|
Handler&& handler,
|
||||||
std::decay<Handler>::type, Args...>
|
Args&&... args) ->
|
||||||
|
detail::bind_front_wrapper<
|
||||||
|
typename std::decay<Handler>::type,
|
||||||
|
typename std::decay<Args>::type...>
|
||||||
{
|
{
|
||||||
return detail::bind_front_wrapper<typename
|
return detail::bind_front_wrapper<
|
||||||
std::decay<Handler>::type, Args...>(
|
typename std::decay<Handler>::type,
|
||||||
|
typename std::decay<Args>::type...>(
|
||||||
std::forward<Handler>(handler),
|
std::forward<Handler>(handler),
|
||||||
std::forward<Args>(args)...);
|
std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
@@ -37,8 +37,6 @@ class bind_wrapper
|
|||||||
Handler h_;
|
Handler h_;
|
||||||
args_type args_;
|
args_type args_;
|
||||||
|
|
||||||
// Can't friend partial specializations,
|
|
||||||
// so we just friend the whole thing.
|
|
||||||
template<class T, class Executor>
|
template<class T, class Executor>
|
||||||
friend struct net::associated_executor;
|
friend struct net::associated_executor;
|
||||||
|
|
||||||
@@ -178,24 +176,6 @@ public:
|
|||||||
asio_handler_invoke(f, std::addressof(w->h_));
|
asio_handler_invoke(f, std::addressof(w->h_));
|
||||||
}
|
}
|
||||||
|
|
||||||
friend
|
|
||||||
void* asio_handler_allocate(
|
|
||||||
std::size_t size, bind_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_wrapper* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_deallocate;
|
|
||||||
asio_handler_deallocate(
|
|
||||||
p, size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
friend
|
||||||
bool asio_handler_is_continuation(
|
bool asio_handler_is_continuation(
|
||||||
bind_wrapper* op)
|
bind_wrapper* op)
|
||||||
@@ -206,19 +186,17 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<class Handler, class... Args>
|
template<class Handler, class... Args>
|
||||||
class bind_front_wrapper;
|
class bind_front_wrapper;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// 0-arg specialization
|
// 0-arg specialization
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
class bind_front_wrapper<Handler>
|
class bind_front_wrapper<Handler>
|
||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
|
|
||||||
// Can't friend partial specializations,
|
|
||||||
// so we just friend the whole thing.
|
|
||||||
template<class T, class Executor>
|
template<class T, class Executor>
|
||||||
friend struct net::associated_executor;
|
friend struct net::associated_executor;
|
||||||
|
|
||||||
@@ -228,10 +206,10 @@ public:
|
|||||||
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<class DeducedHandler>
|
template<class Handler_>
|
||||||
explicit
|
explicit
|
||||||
bind_front_wrapper(DeducedHandler&& handler)
|
bind_front_wrapper(Handler_&& handler)
|
||||||
: h_(std::forward<DeducedHandler>(handler))
|
: h_(std::forward<Handler_>(handler))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,43 +239,25 @@ public:
|
|||||||
asio_handler_invoke(f, std::addressof(w->h_));
|
asio_handler_invoke(f, std::addressof(w->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_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
friend
|
||||||
bool asio_handler_is_continuation(
|
bool asio_handler_is_continuation(
|
||||||
bind_front_wrapper* op)
|
bind_front_wrapper* op)
|
||||||
{
|
{
|
||||||
using net::asio_handler_is_continuation;
|
using net::asio_handler_is_continuation;
|
||||||
return asio_handler_is_continuation(
|
return asio_handler_is_continuation(
|
||||||
std::addressof(op->h_));
|
std::addressof(op->h_));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// 1-arg specialization
|
// 1-arg specialization
|
||||||
template<class Handler, class Arg>
|
template<class Handler, class Arg>
|
||||||
class bind_front_wrapper<Handler, Arg>
|
class bind_front_wrapper<Handler, Arg>
|
||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
typename std::decay<Arg>::type arg_;
|
Arg arg_;
|
||||||
|
|
||||||
// Can't friend partial specializations,
|
|
||||||
// so we just friend the whole thing.
|
|
||||||
template<class T, class Executor>
|
template<class T, class Executor>
|
||||||
friend struct net::associated_executor;
|
friend struct net::associated_executor;
|
||||||
|
|
||||||
@@ -307,18 +267,21 @@ public:
|
|||||||
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<class DeducedHandler>
|
template<
|
||||||
|
class Handler_,
|
||||||
|
class Arg_>
|
||||||
bind_front_wrapper(
|
bind_front_wrapper(
|
||||||
DeducedHandler&& handler, Arg&& arg)
|
Handler_&& handler,
|
||||||
: h_(std::forward<DeducedHandler>(handler))
|
Arg_&& arg)
|
||||||
, arg_(std::forward<Arg>(arg))
|
: h_(std::forward<Handler_>(handler))
|
||||||
|
, arg_(std::forward<Arg_>(arg))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class... Ts>
|
template<class... Ts>
|
||||||
void operator()(Ts&&... ts)
|
void operator()(Ts&&... ts)
|
||||||
{
|
{
|
||||||
h_( std::forward<Arg>(arg_),
|
h_( std::move(arg_),
|
||||||
std::forward<Ts>(ts)...);
|
std::forward<Ts>(ts)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,44 +305,26 @@ public:
|
|||||||
asio_handler_invoke(f, std::addressof(w->h_));
|
asio_handler_invoke(f, std::addressof(w->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_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
friend
|
||||||
bool asio_handler_is_continuation(
|
bool asio_handler_is_continuation(
|
||||||
bind_front_wrapper* op)
|
bind_front_wrapper* op)
|
||||||
{
|
{
|
||||||
using net::asio_handler_is_continuation;
|
using net::asio_handler_is_continuation;
|
||||||
return asio_handler_is_continuation(
|
return asio_handler_is_continuation(
|
||||||
std::addressof(op->h_));
|
std::addressof(op->h_));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// 2-arg specialization
|
// 2-arg specialization
|
||||||
template<class Handler, class Arg1, class Arg2>
|
template<class Handler, class Arg1, class Arg2>
|
||||||
class bind_front_wrapper<Handler, Arg1, Arg2>
|
class bind_front_wrapper<Handler, Arg1, Arg2>
|
||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
typename std::decay<Arg1>::type arg1_;
|
Arg1 arg1_;
|
||||||
typename std::decay<Arg2>::type arg2_;
|
Arg2 arg2_;
|
||||||
|
|
||||||
// Can't friend partial specializations,
|
|
||||||
// so we just friend the whole thing.
|
|
||||||
template<class T, class Executor>
|
template<class T, class Executor>
|
||||||
friend struct net::associated_executor;
|
friend struct net::associated_executor;
|
||||||
|
|
||||||
@@ -389,20 +334,25 @@ public:
|
|||||||
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<class DeducedHandler>
|
template<
|
||||||
bind_front_wrapper(DeducedHandler&& handler,
|
class Handler_,
|
||||||
Arg1&& arg1, Arg2&& arg2)
|
class Arg1_,
|
||||||
: h_(std::forward<DeducedHandler>(handler))
|
class Arg2_>
|
||||||
, arg1_(std::forward<Arg1>(arg1))
|
bind_front_wrapper(
|
||||||
, arg2_(std::forward<Arg2>(arg2))
|
Handler_&& handler,
|
||||||
|
Arg1_&& arg1,
|
||||||
|
Arg2_&& arg2)
|
||||||
|
: h_(std::forward<Handler_>(handler))
|
||||||
|
, arg1_(std::forward<Arg1_>(arg1))
|
||||||
|
, arg2_(std::forward<Arg2_>(arg2))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class... Ts>
|
template<class... Ts>
|
||||||
void operator()(Ts&&... ts)
|
void operator()(Ts&&... ts)
|
||||||
{
|
{
|
||||||
h_( std::forward<Arg1>(arg1_),
|
h_( std::move(arg1_),
|
||||||
std::forward<Arg2>(arg2_),
|
std::move(arg2_),
|
||||||
std::forward<Ts>(ts)...);
|
std::forward<Ts>(ts)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,50 +376,31 @@ public:
|
|||||||
asio_handler_invoke(f, std::addressof(w->h_));
|
asio_handler_invoke(f, std::addressof(w->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_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
friend
|
||||||
bool asio_handler_is_continuation(
|
bool asio_handler_is_continuation(
|
||||||
bind_front_wrapper* op)
|
bind_front_wrapper* op)
|
||||||
{
|
{
|
||||||
using net::asio_handler_is_continuation;
|
using net::asio_handler_is_continuation;
|
||||||
return asio_handler_is_continuation(
|
return asio_handler_is_continuation(
|
||||||
std::addressof(op->h_));
|
std::addressof(op->h_));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// 3+ arg specialization
|
// 3+ arg specialization
|
||||||
template<class Handler,
|
template<
|
||||||
class Arg1, class Arg2, class Arg3, class... Args>
|
class Handler,
|
||||||
class bind_front_wrapper<Handler, Arg1, Arg2, Arg3, Args...>
|
class Arg1, class Arg2, class Arg3,
|
||||||
|
class... Args>
|
||||||
|
class bind_front_wrapper<
|
||||||
|
Handler, Arg1, Arg2, Arg3, Args...>
|
||||||
{
|
{
|
||||||
using args_type = tuple<
|
|
||||||
typename std::decay<Arg1>::type,
|
|
||||||
typename std::decay<Arg2>::type,
|
|
||||||
typename std::decay<Arg3>::type,
|
|
||||||
typename std::decay<Args>::type...>;
|
|
||||||
|
|
||||||
Handler h_;
|
Handler h_;
|
||||||
args_type args_;
|
detail::tuple<
|
||||||
|
Arg1, Arg2, Arg3, Args...> args_;
|
||||||
|
|
||||||
// Can't friend partial specializations,
|
|
||||||
// so we just friend the whole thing.
|
|
||||||
template<class T, class Executor>
|
template<class T, class Executor>
|
||||||
friend struct net::associated_executor;
|
friend struct net::associated_executor;
|
||||||
|
|
||||||
@@ -489,16 +420,22 @@ public:
|
|||||||
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<class DeducedHandler>
|
template<
|
||||||
bind_front_wrapper(DeducedHandler&& handler,
|
class Handler_,
|
||||||
Arg1&& arg1, Arg2&& arg2, Arg3&& arg3,
|
class Arg1_, class Arg2_, class Arg3_,
|
||||||
Args&&... args)
|
class... Args_>
|
||||||
: h_(std::forward<DeducedHandler>(handler))
|
bind_front_wrapper(
|
||||||
|
Handler_&& handler,
|
||||||
|
Arg1_&& arg1,
|
||||||
|
Arg2_&& arg2,
|
||||||
|
Arg3_&& arg3,
|
||||||
|
Args_&&... args)
|
||||||
|
: h_(std::forward<Handler_>(handler))
|
||||||
, args_(
|
, args_(
|
||||||
std::forward<Arg1>(arg1),
|
std::forward<Arg1_>(arg1),
|
||||||
std::forward<Arg2>(arg2),
|
std::forward<Arg2_>(arg2),
|
||||||
std::forward<Arg3>(arg3),
|
std::forward<Arg3_>(arg3),
|
||||||
std::forward<Args>(args)...)
|
std::forward<Args_>(args)...)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,31 +468,13 @@ public:
|
|||||||
asio_handler_invoke(f, std::addressof(w->h_));
|
asio_handler_invoke(f, std::addressof(w->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_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
friend
|
||||||
bool asio_handler_is_continuation(
|
bool asio_handler_is_continuation(
|
||||||
bind_front_wrapper* op)
|
bind_front_wrapper* op)
|
||||||
{
|
{
|
||||||
using net::asio_handler_is_continuation;
|
using net::asio_handler_is_continuation;
|
||||||
return asio_handler_is_continuation(
|
return asio_handler_is_continuation(
|
||||||
std::addressof(op->h_));
|
std::addressof(op->h_));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -567,6 +486,9 @@ template<class Handler>
|
|||||||
class bind_front_wrapper<
|
class bind_front_wrapper<
|
||||||
Handler, error_code, std::size_t>
|
Handler, error_code, std::size_t>
|
||||||
{
|
{
|
||||||
|
template<class T, class Executor>
|
||||||
|
friend struct net::associated_executor;
|
||||||
|
|
||||||
Handler h_;
|
Handler h_;
|
||||||
error_code ec_;
|
error_code ec_;
|
||||||
std::size_t n_;
|
std::size_t n_;
|
||||||
@@ -586,9 +508,10 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator()()
|
template<class... Ts>
|
||||||
|
void operator()(Ts&&... ts)
|
||||||
{
|
{
|
||||||
h_(ec_, n_);
|
h_(ec_, n_, std::forward<Ts>(ts)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -611,34 +534,39 @@ public:
|
|||||||
asio_handler_invoke(f, std::addressof(w->h_));
|
asio_handler_invoke(f, std::addressof(w->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_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
friend
|
||||||
bool asio_handler_is_continuation(
|
bool asio_handler_is_continuation(
|
||||||
bind_front_wrapper* op)
|
bind_front_wrapper* op)
|
||||||
{
|
{
|
||||||
using net::asio_handler_is_continuation;
|
using net::asio_handler_is_continuation;
|
||||||
return asio_handler_is_continuation(
|
return asio_handler_is_continuation(
|
||||||
std::addressof(op->h_));
|
std::addressof(op->h_));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// VFALCO These are only called when using deprecated
|
||||||
|
// network interfaces in conjunction with extensions,
|
||||||
|
// and should not be needed. If this creates a problem
|
||||||
|
// please contact me.
|
||||||
|
|
||||||
|
template<class Handler, class... Args>
|
||||||
|
void* asio_handler_allocate(std::size_t,
|
||||||
|
bind_wrapper<Handler, Args...>* op) = delete;
|
||||||
|
|
||||||
|
template<class Handler, class... Args>
|
||||||
|
void asio_handler_deallocate(void*, std::size_t,
|
||||||
|
bind_wrapper<Handler, Args...>* op) = delete;
|
||||||
|
|
||||||
|
template<class Handler, class... Args>
|
||||||
|
void* asio_handler_allocate(std::size_t,
|
||||||
|
bind_front_wrapper<Handler, Args...>* op) = delete;
|
||||||
|
|
||||||
|
template<class Handler, class... Args>
|
||||||
|
void asio_handler_deallocate(void*, std::size_t,
|
||||||
|
bind_front_wrapper<Handler, Args...>* op) = delete;
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
@@ -689,6 +617,13 @@ struct associated_executor<
|
|||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
|
// VFALCO Using std::bind on a completion handler will
|
||||||
|
// cause undefined behavior later, because the executor
|
||||||
|
// associated with the handler is not propagated to the
|
||||||
|
// wrapper returned by std::bind; these overloads are
|
||||||
|
// deleted to prevent mistakes. If this creates a problem
|
||||||
|
// please contact me.
|
||||||
|
|
||||||
template<class Handler, class... Args>
|
template<class Handler, class... Args>
|
||||||
void
|
void
|
||||||
bind(boost::beast::detail::bind_wrapper<
|
bind(boost::beast::detail::bind_wrapper<
|
||||||
|
Reference in New Issue
Block a user