diff options
Diffstat (limited to 'boost/beast/core/detail/bind_handler.hpp')
-rw-r--r-- | boost/beast/core/detail/bind_handler.hpp | 189 |
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 |