// // 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 #include #include namespace boost { namespace beast { template template inline handler_ptr::P:: P(DeducedHandler&& h, Args&&... args) : n(1) , handler(std::forward(h)) { typename std::allocator_traits< boost::asio::associated_allocator_t>:: template rebind_alloc alloc{ boost::asio::get_associated_allocator(handler)}; t = std::allocator_traits::allocate(alloc, 1); try { t = new(t) T{handler, std::forward(args)...}; } catch(...) { std::allocator_traits< decltype(alloc)>::deallocate(alloc, t, 1); throw; } } template handler_ptr:: ~handler_ptr() { if(! p_) return; if(--p_->n) return; if(p_->t) { p_->t->~T(); typename std::allocator_traits< boost::asio::associated_allocator_t>:: template rebind_alloc alloc{ boost::asio::get_associated_allocator( p_->handler)}; std::allocator_traits< decltype(alloc)>::deallocate(alloc, p_->t, 1); } delete p_; } template handler_ptr:: handler_ptr(handler_ptr&& other) : p_(other.p_) { other.p_ = nullptr; } template handler_ptr:: handler_ptr(handler_ptr const& other) : p_(other.p_) { if(p_) ++p_->n; } template template handler_ptr:: handler_ptr(Handler&& handler, Args&&... args) : p_(new P{std::move(handler), std::forward(args)...}) { BOOST_STATIC_ASSERT(! std::is_array::value); } template template handler_ptr:: handler_ptr(Handler const& handler, Args&&... args) : p_(new P{handler, std::forward(args)...}) { BOOST_STATIC_ASSERT(! std::is_array::value); } template auto handler_ptr:: release_handler() -> handler_type { BOOST_ASSERT(p_); BOOST_ASSERT(p_->t); p_->t->~T(); typename std::allocator_traits< boost::asio::associated_allocator_t>:: template rebind_alloc 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 template void handler_ptr:: invoke(Args&&... args) { BOOST_ASSERT(p_); BOOST_ASSERT(p_->t); p_->t->~T(); typename std::allocator_traits< boost::asio::associated_allocator_t>:: template rebind_alloc 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)...); } } // beast } // boost #endif