]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/boost/boost/beast/core/detail/bind_handler.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / beast / core / detail / bind_handler.hpp
index 48046df923e23d45b252f357e6cc79d7b99bc5fb..db481757f90b4bdc42fe17f4971fcbf695c36dfd 100644 (file)
@@ -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)
 #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<
@@ -51,10 +56,10 @@ class bound_handler
         boost::is_placeholder<typename
             std::decay<Arg>::type>::value == 0,
         Arg&&>::type
-    extract(Arg&& arg, Vals& vals)
+    extract(Arg&& arg, Vals&& vals)
     {
         boost::ignore_unused(vals);
-        return arg;
+        return std::forward<Arg>(arg);
     }
 
     template<class Arg, class Vals>
@@ -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>(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>(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