Back to home page

EIC code displayed by LXR

 
 

    


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

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_CORE_IMPL_SAVED_HANDLER_HPP
0011 #define BOOST_BEAST_CORE_IMPL_SAVED_HANDLER_HPP
0012 
0013 #include <boost/beast/core/detail/allocator.hpp>
0014 #include <boost/asio/associated_allocator.hpp>
0015 #include <boost/asio/associated_cancellation_slot.hpp>
0016 #include <boost/asio/associated_executor.hpp>
0017 #include <boost/asio/error.hpp>
0018 #include <boost/asio/executor_work_guard.hpp>
0019 #include <boost/assert.hpp>
0020 #include <boost/core/empty_value.hpp>
0021 #include <boost/core/exchange.hpp>
0022 #include <utility>
0023 
0024 namespace boost {
0025 namespace beast {
0026 
0027 //------------------------------------------------------------------------------
0028 
0029 class saved_handler::base
0030 {
0031 protected:
0032     ~base() = default;
0033     saved_handler * owner_;
0034 public:
0035     base(saved_handler * owner) : owner_(owner){}
0036     void set_owner(saved_handler * new_owner) { owner_ = new_owner;}
0037     virtual void destroy() = 0;
0038     virtual void invoke() = 0;
0039 };
0040 
0041 //------------------------------------------------------------------------------
0042 
0043 template<class Handler, class Alloc>
0044 class saved_handler::impl final : public base
0045 {
0046     using alloc_type = typename
0047         beast::detail::allocator_traits<
0048             Alloc>::template rebind_alloc<impl>;
0049 
0050     using alloc_traits =
0051         beast::detail::allocator_traits<alloc_type>;
0052 
0053     struct ebo_pair : boost::empty_value<alloc_type>
0054     {
0055         Handler h;
0056 
0057         template<class Handler_>
0058         ebo_pair(
0059             alloc_type const& a,
0060             Handler_&& h_)
0061             : boost::empty_value<alloc_type>(
0062                 boost::empty_init_t{}, a)
0063             , h(std::forward<Handler_>(h_))
0064         {
0065         }
0066     };
0067 
0068     ebo_pair v_;
0069 #if defined(BOOST_ASIO_NO_TS_EXECUTORS)
0070     typename std::decay<decltype(net::prefer(std::declval<
0071         net::associated_executor_t<Handler>>(),
0072         net::execution::outstanding_work.tracked))>::type
0073           wg2_;
0074 #else // defined(BOOST_ASIO_NO_TS_EXECUTORS)
0075     net::executor_work_guard<
0076         net::associated_executor_t<Handler>> wg2_;
0077 #endif // defined(BOOST_ASIO_NO_TS_EXECUTORS)
0078     net::cancellation_slot slot_{net::get_associated_cancellation_slot(v_.h)};
0079 public:
0080     template<class Handler_>
0081     impl(alloc_type const& a, Handler_&& h, 
0082          saved_handler * owner)
0083         : base(owner), v_(a, std::forward<Handler_>(h))
0084 #if defined(BOOST_ASIO_NO_TS_EXECUTORS)
0085         , wg2_(net::prefer(
0086             net::get_associated_executor(v_.h),
0087             net::execution::outstanding_work.tracked))
0088 #else // defined(BOOST_ASIO_NO_TS_EXECUTORS)
0089         , wg2_(net::get_associated_executor(v_.h))
0090 #endif // defined(BOOST_ASIO_NO_TS_EXECUTORS)
0091     {
0092     }
0093 
0094     ~impl()
0095     {
0096     }
0097 
0098     void
0099     destroy() override
0100     {
0101         auto v = std::move(v_);
0102         slot_.clear();
0103         alloc_traits::destroy(v.get(), this);
0104         alloc_traits::deallocate(v.get(), this, 1);
0105     }
0106 
0107     void
0108     invoke() override
0109     {
0110         slot_.clear();
0111         auto v = std::move(v_);
0112         alloc_traits::destroy(v.get(), this);
0113         alloc_traits::deallocate(v.get(), this, 1);
0114         v.h();
0115     }
0116 
0117     void self_complete()
0118     {
0119         slot_.clear();
0120         owner_->p_ = nullptr;
0121         auto v = std::move(v_);
0122         alloc_traits::destroy(v.get(), this);
0123         alloc_traits::deallocate(v.get(), this, 1);
0124         v.h(net::error::operation_aborted);
0125     }
0126 };
0127 
0128 //------------------------------------------------------------------------------
0129 
0130 template<class Handler, class Allocator>
0131 void
0132 saved_handler::
0133 emplace(Handler&& handler, Allocator const& alloc,
0134         net::cancellation_type cancel_type)
0135 {
0136     // Can't delete a handler before invoking
0137     BOOST_ASSERT(! has_value());
0138     using handler_type =
0139         typename std::decay<Handler>::type;
0140     using alloc_type = typename
0141         detail::allocator_traits<Allocator>::
0142             template rebind_alloc<impl<
0143                 handler_type, Allocator>>;
0144     using alloc_traits =
0145         beast::detail::allocator_traits<alloc_type>;
0146     struct storage
0147     {
0148         alloc_type a;
0149         impl<Handler, Allocator>* p;
0150 
0151         explicit
0152         storage(Allocator const& a_)
0153             : a(a_)
0154             , p(alloc_traits::allocate(a, 1))
0155         {
0156         }
0157 
0158         ~storage()
0159         {
0160             if(p)
0161                 alloc_traits::deallocate(a, p, 1);
0162         }
0163     };
0164 
0165 
0166     auto cancel_slot = net::get_associated_cancellation_slot(handler);
0167     storage s(alloc);
0168     alloc_traits::construct(s.a, s.p,
0169         s.a, std::forward<Handler>(handler), this);
0170     
0171     auto tmp = boost::exchange(s.p, nullptr);
0172     p_ = tmp;
0173 
0174     if (cancel_slot.is_connected())
0175     {
0176         struct cancel_op
0177         {
0178             impl<Handler, Allocator>* p;
0179             net::cancellation_type accepted_ct;
0180             cancel_op(impl<Handler, Allocator>* p,
0181                       net::cancellation_type accepted_ct) 
0182                         : p(p), accepted_ct(accepted_ct) {}
0183 
0184             void operator()(net::cancellation_type ct)
0185             {
0186                 if ((ct & accepted_ct) != net::cancellation_type::none)
0187                     p->self_complete();
0188             }
0189         };
0190         cancel_slot.template emplace<cancel_op>(tmp, cancel_type);
0191     }
0192 }
0193 
0194 template<class Handler>
0195 void
0196 saved_handler::
0197 emplace(Handler&& handler, net::cancellation_type cancel_type)
0198 {
0199     // Can't delete a handler before invoking
0200     BOOST_ASSERT(! has_value());
0201     emplace(
0202         std::forward<Handler>(handler),
0203         net::get_associated_allocator(handler),
0204         cancel_type);
0205 }
0206 
0207 } // beast
0208 } // boost
0209 
0210 #endif