123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- //
- // 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)
- //
- // 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/error.hpp>
- #include <boost/beast/core/detail/tuple.hpp>
- #include <boost/asio/associator.hpp>
- #include <boost/asio/handler_continuation_hook.hpp>
- #include <boost/core/ignore_unused.hpp>
- #include <boost/mp11/integer_sequence.hpp>
- #include <boost/bind/std_placeholders.hpp>
- #include <boost/is_placeholder.hpp>
- #include <functional>
- #include <type_traits>
- #include <utility>
- namespace boost {
- namespace beast {
- namespace detail {
- //------------------------------------------------------------------------------
- //
- // bind_handler
- //
- //------------------------------------------------------------------------------
- template<class Handler, class... Args>
- class bind_wrapper
- {
- using args_type = detail::tuple<Args...>;
- Handler h_;
- args_type args_;
- template <template <typename, typename> class,
- typename, typename, typename>
- friend struct net::associator;
- template<class Arg, class Vals>
- static
- typename std::enable_if<
- std::is_placeholder<typename
- std::decay<Arg>::type>::value == 0 &&
- boost::is_placeholder<typename
- std::decay<Arg>::type>::value == 0,
- Arg&&>::type
- extract(Arg&& arg, Vals&& vals)
- {
- boost::ignore_unused(vals);
- return std::forward<Arg>(arg);
- }
- template<class Arg, class Vals>
- static
- typename std::enable_if<
- std::is_placeholder<typename
- std::decay<Arg>::type>::value != 0,
- tuple_element<std::is_placeholder<
- typename std::decay<Arg>::type>::value - 1,
- Vals>>::type&&
- extract(Arg&&, Vals&& vals)
- {
- return detail::get<std::is_placeholder<
- typename std::decay<Arg>::type>::value - 1>(
- std::forward<Vals>(vals));
- }
- template<class Arg, class Vals>
- static
- typename std::enable_if<
- boost::is_placeholder<typename
- std::decay<Arg>::type>::value != 0 &&
- std::is_placeholder<typename
- std::decay<Arg>::type>::value == 0,
- tuple_element<boost::is_placeholder<
- typename std::decay<Arg>::type>::value - 1,
- Vals>>::type&&
- extract(Arg&&, Vals&& vals)
- {
- return detail::get<boost::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,
- tuple<>&&,
- mp11::index_sequence<S...>)
- {
- boost::ignore_unused(args);
- h(detail::get<S>(std::move(args))...);
- }
- template<
- class ArgsTuple,
- class ValsTuple,
- std::size_t... S>
- static
- void
- invoke(
- Handler& h,
- ArgsTuple& args,
- ValsTuple&& vals,
- mp11::index_sequence<S...>)
- {
- boost::ignore_unused(args);
- boost::ignore_unused(vals);
- h(extract(detail::get<S>(std::move(args)),
- std::forward<ValsTuple>(vals))...);
- }
- public:
- using result_type = void; // asio needs this
- bind_wrapper(bind_wrapper&&) = default;
- bind_wrapper(bind_wrapper const&) = default;
- template<
- class DeducedHandler,
- class... Args_>
- explicit
- bind_wrapper(
- DeducedHandler&& handler,
- Args_&&... args)
- : h_(std::forward<DeducedHandler>(handler))
- , 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...>());
- }
- //
- friend
- bool asio_handler_is_continuation(
- bind_wrapper* op)
- {
- using boost::asio::asio_handler_is_continuation;
- return asio_handler_is_continuation(
- 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 <template <typename, typename> class,
- typename, typename, typename>
- friend struct net::associator;
- template<std::size_t... I, class... Ts>
- void
- invoke(
- std::false_type,
- mp11::index_sequence<I...>,
- Ts&&... ts)
- {
- h_( detail::get<I>(std::move(args_))...,
- std::forward<Ts>(ts)...);
- }
- template<std::size_t... I, class... Ts>
- void
- invoke(
- std::true_type,
- mp11::index_sequence<I...>,
- Ts&&... ts)
- {
- 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)...);
- }
- //
- friend
- bool asio_handler_is_continuation(
- bind_front_wrapper* op)
- {
- using boost::asio::asio_handler_is_continuation;
- return asio_handler_is_continuation(
- std::addressof(op->h_));
- }
- };
- } // detail
- } // beast
- } // boost
- //------------------------------------------------------------------------------
- namespace boost {
- namespace asio {
- template <template <typename, typename> class Associator,
- typename Handler, typename... Args, typename DefaultCandidate>
- struct associator<Associator,
- beast::detail::bind_wrapper<Handler, Args...>, DefaultCandidate>
- : Associator<Handler, DefaultCandidate>
- {
- static typename Associator<Handler, DefaultCandidate>::type get(
- const beast::detail::bind_wrapper<Handler, Args...>& h) noexcept
- {
- return Associator<Handler, DefaultCandidate>::get(h.h_);
- }
- static auto get(const beast::detail::bind_wrapper<Handler, Args...>& h,
- const DefaultCandidate& c) noexcept
- -> decltype(Associator<Handler, DefaultCandidate>::get(h.h_, c))
- {
- return Associator<Handler, DefaultCandidate>::get(h.h_, c);
- }
- };
- template <template <typename, typename> class Associator,
- typename Handler, typename... Args, typename DefaultCandidate>
- struct associator<Associator,
- beast::detail::bind_front_wrapper<Handler, Args...>, DefaultCandidate>
- : Associator<Handler, DefaultCandidate>
- {
- static typename Associator<Handler, DefaultCandidate>::type get(
- const beast::detail::bind_front_wrapper<Handler, Args...>& h) noexcept
- {
- return Associator<Handler, DefaultCandidate>::get(h.h_);
- }
- static auto get(const beast::detail::bind_front_wrapper<Handler, Args...>& h,
- const DefaultCandidate& c) noexcept
- -> decltype(Associator<Handler, DefaultCandidate>::get(h.h_, c))
- {
- return Associator<Handler, DefaultCandidate>::get(h.h_, c);
- }
- };
- } // 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::bind_wrapper<
- Handler, Args...>, ...) = delete;
- template<class Handler, class... Args>
- void
- bind(boost::beast::detail::bind_front_wrapper<
- Handler, Args...>, ...) = delete;
- } // std
- //------------------------------------------------------------------------------
- #endif
|