diff options
Diffstat (limited to 'boost/beast/core/impl/handler_ptr.ipp')
-rw-r--r-- | boost/beast/core/impl/handler_ptr.ipp | 149 |
1 files changed, 65 insertions, 84 deletions
diff --git a/boost/beast/core/impl/handler_ptr.ipp b/boost/beast/core/impl/handler_ptr.ipp index 15a159a8fd..99d1a894d5 100644 --- a/boost/beast/core/impl/handler_ptr.ipp +++ b/boost/beast/core/impl/handler_ptr.ipp @@ -18,87 +18,72 @@ namespace boost { namespace beast { template<class T, class Handler> -template<class DeducedHandler, class... Args> -inline -handler_ptr<T, Handler>::P:: -P(DeducedHandler&& h, Args&&... args) - : n(1) - , handler(std::forward<DeducedHandler>(h)) +void +handler_ptr<T, Handler>:: +clear() { - typename std::allocator_traits< - boost::asio::associated_allocator_t<Handler>>:: - template rebind_alloc<T> alloc{ - boost::asio::get_associated_allocator(handler)}; - t = std::allocator_traits<decltype(alloc)>::allocate(alloc, 1); - try - { - t = new(t) T{handler, - std::forward<Args>(args)...}; - } - catch(...) - { - std::allocator_traits< - decltype(alloc)>::deallocate(alloc, t, 1); - throw; - } + typename beast::detail::allocator_traits< + boost::asio::associated_allocator_t< + Handler>>::template rebind_alloc<T> alloc( + boost::asio::get_associated_allocator( + handler())); + beast::detail::allocator_traits< + decltype(alloc)>::destroy(alloc, t_); + beast::detail::allocator_traits< + decltype(alloc)>::deallocate(alloc, t_, 1); + t_ = nullptr; } template<class T, class Handler> handler_ptr<T, Handler>:: ~handler_ptr() { - if(! p_) - return; - if(--p_->n) - return; - if(p_->t) + if(t_) { - p_->t->~T(); - typename std::allocator_traits< - boost::asio::associated_allocator_t<Handler>>:: - template rebind_alloc<T> alloc{ - boost::asio::get_associated_allocator( - p_->handler)}; - std::allocator_traits< - decltype(alloc)>::deallocate(alloc, p_->t, 1); + clear(); + handler().~Handler(); } - delete p_; } template<class T, class Handler> handler_ptr<T, Handler>:: handler_ptr(handler_ptr&& other) - : p_(other.p_) + : t_(other.t_) { - other.p_ = nullptr; -} - -template<class T, class Handler> -handler_ptr<T, Handler>:: -handler_ptr(handler_ptr const& other) - : p_(other.p_) -{ - if(p_) - ++p_->n; -} - -template<class T, class Handler> -template<class... Args> -handler_ptr<T, Handler>:: -handler_ptr(Handler&& handler, Args&&... args) - : p_(new P{std::move(handler), - std::forward<Args>(args)...}) -{ - BOOST_STATIC_ASSERT(! std::is_array<T>::value); + if(other.t_) + { + new(&h_) Handler(std::move(other.handler())); + other.handler().~Handler(); + other.t_ = nullptr; + } } template<class T, class Handler> -template<class... Args> +template<class DeducedHandler, class... Args> handler_ptr<T, Handler>:: -handler_ptr(Handler const& handler, Args&&... args) - : p_(new P{handler, std::forward<Args>(args)...}) +handler_ptr(DeducedHandler&& h, Args&&... args) { BOOST_STATIC_ASSERT(! std::is_array<T>::value); + typename beast::detail::allocator_traits< + boost::asio::associated_allocator_t< + Handler>>::template rebind_alloc<T> alloc{ + boost::asio::get_associated_allocator(h)}; + using A = decltype(alloc); + bool destroy = false; + auto deleter = [&alloc, &destroy](T* p) + { + if(destroy) + beast::detail::allocator_traits<A>::destroy(alloc, p); + beast::detail::allocator_traits<A>::deallocate(alloc, p, 1); + }; + std::unique_ptr<T, decltype(deleter)> t{ + beast::detail::allocator_traits<A>::allocate(alloc, 1), deleter}; + beast::detail::allocator_traits<A>::construct(alloc, t.get(), + static_cast<DeducedHandler const&>(h), + std::forward<Args>(args)...); + destroy = true; + new(&h_) Handler(std::forward<DeducedHandler>(h)); + t_ = t.release(); } template<class T, class Handler> @@ -107,18 +92,16 @@ handler_ptr<T, Handler>:: release_handler() -> handler_type { - BOOST_ASSERT(p_); - BOOST_ASSERT(p_->t); - p_->t->~T(); - typename std::allocator_traits< - boost::asio::associated_allocator_t<Handler>>:: - template rebind_alloc<T> alloc{ - boost::asio::get_associated_allocator( - p_->handler)}; - std::allocator_traits< - decltype(alloc)>::deallocate(alloc, p_->t, 1); - p_->t = nullptr; - return std::move(p_->handler); + BOOST_ASSERT(t_); + clear(); + auto deleter = [](Handler* h) + { + h->~Handler(); + }; + std::unique_ptr< + Handler, decltype(deleter)> destroyer{ + &handler(), deleter}; + return std::move(handler()); } template<class T, class Handler> @@ -127,18 +110,16 @@ void handler_ptr<T, Handler>:: invoke(Args&&... args) { - BOOST_ASSERT(p_); - BOOST_ASSERT(p_->t); - p_->t->~T(); - typename std::allocator_traits< - boost::asio::associated_allocator_t<Handler>>:: - template rebind_alloc<T> alloc{ - boost::asio::get_associated_allocator( - p_->handler)}; - std::allocator_traits< - decltype(alloc)>::deallocate(alloc, p_->t, 1); - p_->t = nullptr; - p_->handler(std::forward<Args>(args)...); + BOOST_ASSERT(t_); + clear(); + auto deleter = [](Handler* h) + { + h->~Handler(); + }; + std::unique_ptr< + Handler, decltype(deleter)> destroyer{ + &handler(), deleter}; + handler()(std::forward<Args>(args)...); } } // beast |