summaryrefslogtreecommitdiff
path: root/boost/beast/core/detail/bind_handler.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/core/detail/bind_handler.hpp')
-rw-r--r--boost/beast/core/detail/bind_handler.hpp335
1 files changed, 264 insertions, 71 deletions
diff --git a/boost/beast/core/detail/bind_handler.hpp b/boost/beast/core/detail/bind_handler.hpp
index 8bacc921f7..db481757f9 100644
--- a/boost/beast/core/detail/bind_handler.hpp
+++ b/boost/beast/core/detail/bind_handler.hpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2016-2019 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)
@@ -10,39 +10,44 @@
#ifndef BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
#define BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
-#include <boost/beast/core/detail/integer_sequence.hpp>
+#include <boost/beast/core/error.hpp>
+#include <boost/beast/core/detail/tuple.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>
#include <boost/core/ignore_unused.hpp>
+#include <boost/mp11/integer_sequence.hpp>
#include <boost/is_placeholder.hpp>
#include <functional>
+#include <type_traits>
#include <utility>
namespace boost {
namespace beast {
namespace detail {
-/* Nullary handler that calls Handler with bound arguments.
+//------------------------------------------------------------------------------
+//
+// bind_handler
+//
+//------------------------------------------------------------------------------
- The bound handler provides the same io_context execution
- guarantees as the original handler.
-*/
template<class Handler, class... Args>
-class bound_handler
+class bind_wrapper
{
- // Can't friend partial specializations,
- // so we just friend the whole thing.
- template<class T, class Executor>
- friend struct boost::asio::associated_executor;
-
- using args_type = std::tuple<
- typename std::decay<Args>::type...>;
+ using args_type = detail::tuple<Args...>;
Handler h_;
args_type args_;
+ template<class T, class Executor>
+ friend struct net::associated_executor;
+
+ template<class T, class Allocator>
+ friend struct net::associated_allocator;
+
template<class Arg, class Vals>
static
typename std::enable_if<
@@ -62,13 +67,12 @@ class bound_handler
typename std::enable_if<
std::is_placeholder<typename
std::decay<Arg>::type>::value != 0,
- typename std::tuple_element<
- std::is_placeholder<
- typename std::decay<Arg>::type>::value - 1,
- Vals>>::type::type&&
+ tuple_element<std::is_placeholder<
+ typename std::decay<Arg>::type>::value - 1,
+ Vals>>::type&&
extract(Arg&&, Vals&& vals)
{
- return std::get<std::is_placeholder<
+ return detail::get<std::is_placeholder<
typename std::decay<Arg>::type>::value - 1>(
std::forward<Vals>(vals));
}
@@ -78,30 +82,27 @@ class bound_handler
typename std::enable_if<
boost::is_placeholder<typename
std::decay<Arg>::type>::value != 0,
- typename std::tuple_element<
- boost::is_placeholder<
- typename std::decay<Arg>::type>::value - 1,
- Vals>>::type::type&&
+ tuple_element<boost::is_placeholder<
+ typename std::decay<Arg>::type>::value - 1,
+ Vals>>::type&&
extract(Arg&&, Vals&& vals)
{
- return std::get<boost::is_placeholder<
+ return detail::get<boost::is_placeholder<
typename std::decay<Arg>::type>::value - 1>(
std::forward<Vals>(vals));
}
- template<
- class ArgsTuple,
- std::size_t... S>
+ template<class ArgsTuple, std::size_t... S>
static
void
invoke(
Handler& h,
ArgsTuple& args,
- std::tuple<>&&,
- index_sequence<S...>)
+ tuple<>&&,
+ mp11::index_sequence<S...>)
{
boost::ignore_unused(args);
- h(std::get<S>(std::move(args))...);
+ h(detail::get<S>(std::move(args))...);
}
template<
@@ -114,104 +115,296 @@ class bound_handler
Handler& h,
ArgsTuple& args,
ValsTuple&& vals,
- index_sequence<S...>)
+ mp11::index_sequence<S...>)
{
boost::ignore_unused(args);
boost::ignore_unused(vals);
- h(extract(std::get<S>(std::move(args)),
+ h(extract(detail::get<S>(std::move(args)),
std::forward<ValsTuple>(vals))...);
}
public:
- using result_type = void;
+ using result_type = void; // asio needs this
- using allocator_type =
- boost::asio::associated_allocator_t<Handler>;
+ bind_wrapper(bind_wrapper&&) = default;
+ bind_wrapper(bind_wrapper const&) = default;
- bound_handler(bound_handler&&) = default;
- bound_handler(bound_handler const&) = delete;
-
- template<class DeducedHandler>
+ template<
+ class DeducedHandler,
+ class... Args_>
explicit
- bound_handler(
- DeducedHandler&& handler, Args&&... args)
+ bind_wrapper(
+ DeducedHandler&& handler,
+ Args_&&... args)
: h_(std::forward<DeducedHandler>(handler))
- , args_(std::forward<Args>(args)...)
+ , args_(std::forward<Args_>(args)...)
+ {
+ }
+
+ template<class... Values>
+ void
+ operator()(Values&&... values)
{
+ invoke(h_, args_,
+ tuple<Values&&...>(
+ std::forward<Values>(values)...),
+ mp11::index_sequence_for<Args...>());
}
- allocator_type
- get_allocator() const noexcept
+ //
+
+ template<class Function>
+ friend
+ void asio_handler_invoke(
+ Function&& f, bind_wrapper* op)
{
- return (boost::asio::get_associated_allocator)(h_);
+ using net::asio_handler_invoke;
+ asio_handler_invoke(f, std::addressof(op->h_));
}
friend
- bool
- asio_handler_is_continuation(bound_handler* h)
+ bool asio_handler_is_continuation(
+ bind_wrapper* op)
{
- using boost::asio::asio_handler_is_continuation;
- return asio_handler_is_continuation(std::addressof(h->h_));
+ using net::asio_handler_is_continuation;
+ return asio_handler_is_continuation(
+ std::addressof(op->h_));
}
- template<class Function>
friend
- void asio_handler_invoke(Function&& f, bound_handler* h)
+ void* asio_handler_allocate(
+ std::size_t size, bind_wrapper* op)
{
- using boost::asio::asio_handler_invoke;
- asio_handler_invoke(f, std::addressof(h->h_));
+ using net::asio_handler_allocate;
+ return asio_handler_allocate(
+ size, std::addressof(op->h_));
}
- template<class... Values>
+ 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_));
+ }
+};
+
+template<class Handler, class... Args>
+class bind_back_wrapper;
+
+template<class Handler, class... Args>
+class bind_front_wrapper;
+
+//------------------------------------------------------------------------------
+//
+// bind_front
+//
+//------------------------------------------------------------------------------
+
+template<class Handler, class... Args>
+class bind_front_wrapper
+{
+ Handler h_;
+ detail::tuple<Args...> args_;
+
+ template<class T, class Executor>
+ friend struct net::associated_executor;
+
+ template<class T, class Allocator>
+ friend struct net::associated_allocator;
+
+ template<std::size_t... I, class... Ts>
void
- operator()(Values&&... values)
+ invoke(
+ std::false_type,
+ mp11::index_sequence<I...>,
+ Ts&&... ts)
{
- invoke(h_, args_,
- std::forward_as_tuple(
- std::forward<Values>(values)...),
- index_sequence_for<Args...>());
+ h_( detail::get<I>(std::move(args_))...,
+ std::forward<Ts>(ts)...);
}
- template<class... Values>
+ template<std::size_t... I, class... Ts>
void
- operator()(Values&&... values) const
+ invoke(
+ std::true_type,
+ mp11::index_sequence<I...>,
+ Ts&&... ts)
{
- invoke(h_, args_,
- std::forward_as_tuple(
- std::forward<Values>(values)...),
- index_sequence_for<Args...>());
+ std::mem_fn(h_)(
+ detail::get<I>(std::move(args_))...,
+ std::forward<Ts>(ts)...);
+ }
+
+public:
+ using result_type = void; // asio needs this
+
+ bind_front_wrapper(bind_front_wrapper&&) = default;
+ bind_front_wrapper(bind_front_wrapper const&) = default;
+
+ template<class Handler_, class... Args_>
+ bind_front_wrapper(
+ Handler_&& handler,
+ Args_&&... args)
+ : h_(std::forward<Handler_>(handler))
+ , args_(std::forward<Args_>(args)...)
+ {
+ }
+
+ template<class... Ts>
+ void operator()(Ts&&... ts)
+ {
+ invoke(
+ std::is_member_function_pointer<Handler>{},
+ mp11::index_sequence_for<Args...>{},
+ std::forward<Ts>(ts)...);
+ }
+
+ //
+
+ 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_));
}
};
} // detail
} // beast
+} // boost
+//------------------------------------------------------------------------------
+
+namespace boost {
namespace asio {
+
template<class Handler, class... Args, class Executor>
struct associated_executor<
- beast::detail::bound_handler<Handler, Args...>, Executor>
+ beast::detail::bind_wrapper<Handler, Args...>, Executor>
{
using type = typename
associated_executor<Handler, Executor>::type;
static
type
- get(beast::detail::bound_handler<Handler, Args...> const& h,
- Executor const& ex = Executor()) noexcept
+ get(beast::detail::bind_wrapper<Handler, Args...> const& op,
+ Executor const& ex = Executor{}) noexcept
{
return associated_executor<
- Handler, Executor>::get(h.h_, ex);
+ Handler, Executor>::get(op.h_, ex);
}
};
-} // asio
+template<class Handler, class... Args, class Executor>
+struct associated_executor<
+ beast::detail::bind_front_wrapper<Handler, Args...>, Executor>
+{
+ using type = typename
+ associated_executor<Handler, Executor>::type;
+
+ static
+ type
+ get(beast::detail::bind_front_wrapper<Handler, Args...> const& op,
+ Executor const& ex = Executor{}) noexcept
+ {
+ return associated_executor<
+ Handler, Executor>::get(op.h_, ex);
+ }
+};
+
+//
+
+template<class Handler, class... Args, class Allocator>
+struct associated_allocator<
+ beast::detail::bind_wrapper<Handler, Args...>, Allocator>
+{
+ using type = typename
+ associated_allocator<Handler, Allocator>::type;
+
+ static
+ type
+ get(beast::detail::bind_wrapper<Handler, Args...> const& op,
+ Allocator const& alloc = Allocator{}) noexcept
+ {
+ return associated_allocator<
+ Handler, Allocator>::get(op.h_, alloc);
+ }
+};
+
+template<class Handler, class... Args, class Allocator>
+struct associated_allocator<
+ beast::detail::bind_front_wrapper<Handler, Args...>, Allocator>
+{
+ using type = typename
+ associated_allocator<Handler, Allocator>::type;
+
+ static
+ type
+ get(beast::detail::bind_front_wrapper<Handler, Args...> const& op,
+ Allocator const& alloc = Allocator{}) noexcept
+ {
+ return associated_allocator<
+ Handler, Allocator>::get(op.h_, alloc);
+ }
+};
+
+} // asio
} // boost
+//------------------------------------------------------------------------------
+
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>
void
-bind(boost::beast::detail::bound_handler<
+bind(boost::beast::detail::bind_wrapper<
Handler, Args...>, ...) = delete;
+
+template<class Handler, class... Args>
+void
+bind(boost::beast::detail::bind_front_wrapper<
+ Handler, Args...>, ...) = delete;
+
} // std
+//------------------------------------------------------------------------------
+
#endif