boost/beast/core/impl/handler_ptr.ipp
// // Copyright (c) 2016-2017 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_IMPL_HANDLER_PTR_HPP #define BOOST_BEAST_IMPL_HANDLER_PTR_HPP #include <boost/asio/associated_allocator.hpp> #include <boost/assert.hpp> #include <memory> 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)) { 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; } } template<class T, class Handler> handler_ptr<T, Handler>:: ~handler_ptr() { if(! p_) return; if(--p_->n) return; if(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); } delete p_; } template<class T, class Handler> handler_ptr<T, Handler>:: handler_ptr(handler_ptr&& other) : p_(other.p_) { 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); } template<class T, class Handler> template<class... Args> handler_ptr<T, Handler>:: handler_ptr(Handler const& handler, Args&&... args) : p_(new P{handler, std::forward<Args>(args)...}) { BOOST_STATIC_ASSERT(! std::is_array<T>::value); } template<class T, class Handler> auto 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); } template<class T, class Handler> template<class... Args> 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)...); } } // beast } // boost #endif