123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- //
- // 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/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 {
- //------------------------------------------------------------------------------
- //
- // bind_handler
- //
- //------------------------------------------------------------------------------
- template<class Handler, class... Args>
- class bind_wrapper
- {
- 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<
- 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,
- 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...>());
- }
- //
- template<class Function>
- friend
- void asio_handler_invoke(
- Function&& f, bind_wrapper* op)
- {
- using net::asio_handler_invoke;
- asio_handler_invoke(f, std::addressof(op->h_));
- }
- friend
- bool asio_handler_is_continuation(
- bind_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_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_));
- }
- };
- 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
- 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)...);
- }
- //
- 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::bind_wrapper<Handler, Args...>, Executor>
- {
- using type = typename
- associated_executor<Handler, Executor>::type;
- static
- type
- get(beast::detail::bind_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 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::bind_wrapper<
- Handler, Args...>, ...) = delete;
- template<class Handler, class... Args>
- void
- bind(boost::beast::detail::bind_front_wrapper<
- Handler, Args...>, ...) = delete;
- } // std
- //------------------------------------------------------------------------------
- #endif
|