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.hpp189
1 files changed, 189 insertions, 0 deletions
diff --git a/boost/beast/core/detail/bind_handler.hpp b/boost/beast/core/detail/bind_handler.hpp
new file mode 100644
index 0000000000..5a9059b8e3
--- /dev/null
+++ b/boost/beast/core/detail/bind_handler.hpp
@@ -0,0 +1,189 @@
+//
+// 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_DETAIL_BIND_HANDLER_HPP
+#define BOOST_BEAST_DETAIL_BIND_HANDLER_HPP
+
+#include <boost/beast/core/detail/integer_sequence.hpp>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/handler_continuation_hook.hpp>
+#include <boost/core/ignore_unused.hpp>
+#include <functional>
+#include <utility>
+
+namespace boost {
+namespace beast {
+namespace detail {
+
+/* Nullary handler that calls Handler with bound arguments.
+
+ The bound handler provides the same io_context execution
+ guarantees as the original handler.
+*/
+template<class Handler, class... Args>
+class bound_handler
+{
+ // 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...>;
+
+ Handler h_;
+ args_type args_;
+
+ template<class Arg, class Vals>
+ static
+ typename std::enable_if<
+ std::is_placeholder<typename
+ std::decay<Arg>::type>::value == 0,
+ Arg&&>::type
+ extract(Arg&& arg, Vals& vals)
+ {
+ boost::ignore_unused(vals);
+ return arg;
+ }
+
+ template<class Arg, class Vals>
+ static
+ 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
+ extract(Arg&&, Vals&& vals)
+ {
+ return std::get<std::is_placeholder<
+ typename std::decay<Arg>::type>::value - 1>(
+ std::forward<Vals>(vals));
+ }
+
+ template<
+ class ArgsTuple,
+ std::size_t... S>
+ static
+ void
+ invoke(
+ Handler& h,
+ ArgsTuple& args,
+ std::tuple<>&&,
+ index_sequence<S...>)
+ {
+ boost::ignore_unused(args);
+ h(std::get<S>(args)...);
+ }
+
+ template<
+ class ArgsTuple,
+ class ValsTuple,
+ std::size_t... S>
+ static
+ void
+ invoke(
+ Handler& h,
+ ArgsTuple& args,
+ ValsTuple&& vals,
+ index_sequence<S...>)
+ {
+ boost::ignore_unused(args);
+ boost::ignore_unused(vals);
+ h(extract(std::get<S>(args),
+ std::forward<ValsTuple>(vals))...);
+ }
+
+public:
+ using result_type = void;
+
+ using allocator_type =
+ boost::asio::associated_allocator_t<Handler>;
+
+ bound_handler(bound_handler&&) = default;
+ bound_handler(bound_handler const&) = default;
+
+ template<class DeducedHandler>
+ explicit
+ bound_handler(
+ DeducedHandler&& handler, Args&&... args)
+ : h_(std::forward<DeducedHandler>(handler))
+ , args_(std::forward<Args>(args)...)
+ {
+ }
+
+ allocator_type
+ get_allocator() const noexcept
+ {
+ return boost::asio::get_associated_allocator(h_);
+ }
+
+ friend
+ bool
+ asio_handler_is_continuation(bound_handler* h)
+ {
+ using boost::asio::asio_handler_is_continuation;
+ return asio_handler_is_continuation(std::addressof(h->h_));
+ }
+
+ template<class... Values>
+ void
+ operator()(Values&&... values)
+ {
+ invoke(h_, args_,
+ std::forward_as_tuple(
+ std::forward<Values>(values)...),
+ index_sequence_for<Args...>());
+ }
+
+ template<class... Values>
+ void
+ operator()(Values&&... values) const
+ {
+ invoke(h_, args_,
+ std::forward_as_tuple(
+ std::forward<Values>(values)...),
+ index_sequence_for<Args...>());
+ }
+};
+
+} // detail
+} // beast
+
+namespace asio {
+template<class Handler, class... Args, class Executor>
+struct associated_executor<
+ beast::detail::bound_handler<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
+ {
+ return associated_executor<
+ Handler, Executor>::get(h.h_, ex);
+ }
+};
+} // asio
+
+} // boost
+
+namespace std {
+template<class Handler, class... Args>
+void
+bind(boost::beast::detail::bound_handler<
+ Handler, Args...>, ...) = delete;
+} // std
+
+#endif