diff options
Diffstat (limited to 'boost/beast/core/impl/handler_ptr.ipp')
-rw-r--r-- | boost/beast/core/impl/handler_ptr.ipp | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/boost/beast/core/impl/handler_ptr.ipp b/boost/beast/core/impl/handler_ptr.ipp new file mode 100644 index 0000000000..15a159a8fd --- /dev/null +++ b/boost/beast/core/impl/handler_ptr.ipp @@ -0,0 +1,147 @@ +// +// 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 |