Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:32

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_WEBSOCKET_DETAIL_DECORATOR_HPP
0011 #define BOOST_BEAST_WEBSOCKET_DETAIL_DECORATOR_HPP
0012 
0013 #include <boost/beast/websocket/rfc6455.hpp>
0014 #include <boost/core/exchange.hpp>
0015 #include <boost/type_traits/aligned_storage.hpp>
0016 #include <boost/type_traits/make_void.hpp>
0017 #include <algorithm>
0018 #include <memory>
0019 #include <new>
0020 #include <type_traits>
0021 #include <utility>
0022 
0023 namespace boost {
0024 namespace beast {
0025 namespace websocket {
0026 namespace detail {
0027 
0028 // VFALCO NOTE: When this is two traits, one for
0029 //              request and one for response,
0030 //              Visual Studio 2015 fails.
0031 
0032 template<class T, class U, class = void>
0033 struct can_invoke_with : std::false_type
0034 {
0035 };
0036 
0037 template<class T, class U>
0038 struct can_invoke_with<T, U, boost::void_t<decltype(
0039     std::declval<T&>()(std::declval<U&>()))>>
0040     : std::true_type
0041 {
0042 };
0043 
0044 template<class T>
0045 using is_decorator = std::integral_constant<bool,
0046     can_invoke_with<T, request_type>::value ||
0047     can_invoke_with<T, response_type>::value>;
0048 
0049 class decorator
0050 {
0051     friend class decorator_test;
0052 
0053     struct incomplete;
0054 
0055     struct exemplar
0056     {
0057         void (incomplete::*mf)();
0058         std::shared_ptr<incomplete> sp;
0059         void* param;
0060     };
0061 
0062     union storage
0063     {
0064         void* p_;
0065         void (*fn_)();
0066         typename boost::aligned_storage<
0067             sizeof(exemplar),
0068             alignof(exemplar)>::type buf_;
0069     };
0070 
0071     struct vtable
0072     {
0073         void (*move)(
0074             storage& dst, storage& src) noexcept;
0075         void (*destroy)(storage& dst) noexcept;
0076         void (*invoke_req)(
0077             storage& dst, request_type& req);
0078         void (*invoke_res)(
0079             storage& dst, response_type& req);
0080 
0081         static void move_fn(
0082             storage&, storage&) noexcept
0083         {
0084         }
0085 
0086         static void destroy_fn(
0087             storage&) noexcept
0088         {
0089         }
0090 
0091         static void invoke_req_fn(
0092             storage&, request_type&)
0093         {
0094         }
0095 
0096         static void invoke_res_fn(
0097             storage&, response_type&)
0098         {
0099         }
0100 
0101         static vtable const* get_default()
0102         {
0103             static const vtable impl{
0104                 &move_fn,
0105                 &destroy_fn,
0106                 &invoke_req_fn,
0107                 &invoke_res_fn
0108             };
0109             return &impl;
0110         }
0111     };
0112 
0113     template<class F, bool Inline =
0114         (sizeof(F) <= sizeof(storage) &&
0115         alignof(F) <= alignof(storage) &&
0116         std::is_nothrow_move_constructible<F>::value)>
0117     struct vtable_impl;
0118 
0119     storage storage_;
0120     vtable const* vtable_ = vtable::get_default();
0121 
0122     // VFALCO NOTE: When this is two traits, one for
0123     //              request and one for response,
0124     //              Visual Studio 2015 fails.
0125 
0126     template<class T, class U, class = void>
0127     struct maybe_invoke
0128     {
0129         void
0130         operator()(T&, U&)
0131         {
0132         }
0133     };
0134 
0135     template<class T, class U>
0136     struct maybe_invoke<T, U, boost::void_t<decltype(
0137         std::declval<T&>()(std::declval<U&>()))>>
0138     {
0139         void
0140         operator()(T& t, U& u)
0141         {
0142             t(u);
0143         }
0144     };
0145 
0146 public:
0147     decorator() = default;
0148     decorator(decorator const&) = delete;
0149     decorator& operator=(decorator const&) = delete;
0150 
0151     ~decorator()
0152     {
0153         vtable_->destroy(storage_);
0154     }
0155 
0156     decorator(decorator&& other) noexcept
0157         : vtable_(boost::exchange(
0158             other.vtable_, vtable::get_default()))
0159     {
0160         vtable_->move(
0161             storage_, other.storage_);
0162     }
0163 
0164     template<class F,
0165         class = typename std::enable_if<
0166         ! std::is_convertible<
0167             F, decorator>::value>::type>
0168     explicit
0169     decorator(F&& f)
0170       : vtable_(vtable_impl<
0171           typename std::decay<F>::type>::
0172         construct(storage_, std::forward<F>(f)))
0173     {
0174     }
0175 
0176     decorator&
0177     operator=(decorator&& other) noexcept
0178     {
0179         vtable_->destroy(storage_);
0180         vtable_ = boost::exchange(
0181             other.vtable_, vtable::get_default());
0182         vtable_->move(storage_, other.storage_);
0183         return *this;
0184     }
0185 
0186     void
0187     operator()(request_type& req)
0188     {
0189         vtable_->invoke_req(storage_, req);
0190     }
0191 
0192     void
0193     operator()(response_type& res)
0194     {
0195         vtable_->invoke_res(storage_, res);
0196     }
0197 };
0198 
0199 template<class F>
0200 struct decorator::vtable_impl<F, true>
0201 {
0202     template<class Arg>
0203     static
0204     vtable const*
0205     construct(storage& dst, Arg&& arg)
0206     {
0207         ::new (static_cast<void*>(&dst.buf_)) F(
0208             std::forward<Arg>(arg));
0209         return get();
0210     }
0211 
0212     static
0213     void
0214     move(storage& dst, storage& src) noexcept
0215     {
0216         auto& f = *beast::detail::launder_cast<F*>(&src.buf_);
0217         ::new (&dst.buf_) F(std::move(f));
0218     }
0219 
0220     static
0221     void
0222     destroy(storage& dst) noexcept
0223     {
0224         beast::detail::launder_cast<F*>(&dst.buf_)->~F();
0225     }
0226 
0227     static
0228     void
0229     invoke_req(storage& dst, request_type& req)
0230     {
0231         maybe_invoke<F, request_type>{}(
0232             *beast::detail::launder_cast<F*>(&dst.buf_), req);
0233     }
0234 
0235     static
0236     void
0237     invoke_res(storage& dst, response_type& res)
0238     {
0239         maybe_invoke<F, response_type>{}(
0240             *beast::detail::launder_cast<F*>(&dst.buf_), res);
0241     }
0242 
0243     static
0244     vtable
0245     const* get()
0246     {
0247         static constexpr vtable impl{
0248             &move,
0249             &destroy,
0250             &invoke_req,
0251             &invoke_res};
0252         return &impl;
0253     }
0254 };
0255 
0256 template<class F>
0257 struct decorator::vtable_impl<F, false>
0258 {
0259     template<class Arg>
0260     static
0261     vtable const*
0262     construct(storage& dst, Arg&& arg)
0263     {
0264         dst.p_ = new F(std::forward<Arg>(arg));
0265         return get();
0266     }
0267 
0268     static
0269     void
0270     move(storage& dst, storage& src) noexcept
0271     {
0272         dst.p_ = src.p_;
0273     }
0274 
0275     static
0276     void
0277     destroy(storage& dst) noexcept
0278     {
0279         delete static_cast<F*>(dst.p_);
0280     }
0281 
0282     static
0283     void
0284     invoke_req(
0285         storage& dst, request_type& req)
0286     {
0287         maybe_invoke<F, request_type>{}(
0288             *static_cast<F*>(dst.p_), req);
0289     }
0290 
0291     static
0292     void
0293     invoke_res(
0294         storage& dst, response_type& res)
0295     {
0296         maybe_invoke<F, response_type>{}(
0297             *static_cast<F*>(dst.p_), res);
0298     }
0299 
0300     static
0301     vtable const*
0302     get()
0303     {
0304         static constexpr vtable impl{&move,
0305             &destroy, &invoke_req, &invoke_res};
0306         return &impl;
0307     }
0308 };
0309 
0310 } // detail
0311 } // websocket
0312 } // beast
0313 } // boost
0314 
0315 #endif