// // Copyright (c) 2013-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) // #ifndef BEAST_IMPL_HANDLER_PTR_HPP #define BEAST_IMPL_HANDLER_PTR_HPP #include #include #include #include #include namespace beast { template template inline handler_ptr::P:: P(DeducedHandler&& h, Args&&... args) : n(1) , handler(std::forward(h)) { using boost::asio::asio_handler_allocate; t = reinterpret_cast( asio_handler_allocate( sizeof(T), std::addressof(handler))); try { t = new(t) T{handler, std::forward(args)...}; } catch(...) { using boost::asio::asio_handler_deallocate; asio_handler_deallocate( t, sizeof(T), std::addressof(handler)); throw; } } template handler_ptr:: ~handler_ptr() { if(! p_) return; if(--p_->n) return; if(p_->t) { p_->t->~T(); using boost::asio::asio_handler_deallocate; asio_handler_deallocate( p_->t, sizeof(T), std::addressof(p_->handler)); } 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(); using boost::asio::asio_handler_deallocate; asio_handler_deallocate( p_->t, sizeof(T), std::addressof(p_->handler)); 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(); using boost::asio::asio_handler_deallocate; asio_handler_deallocate( p_->t, sizeof(T), std::addressof(p_->handler)); p_->t = nullptr; p_->handler(std::forward(args)...); } } // beast #endif