summaryrefslogtreecommitdiff
path: root/boost/beast/core/impl/handler_ptr.ipp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/core/impl/handler_ptr.ipp')
-rw-r--r--boost/beast/core/impl/handler_ptr.ipp147
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