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.ipp149
1 files changed, 65 insertions, 84 deletions
diff --git a/boost/beast/core/impl/handler_ptr.ipp b/boost/beast/core/impl/handler_ptr.ipp
index 15a159a8fd..99d1a894d5 100644
--- a/boost/beast/core/impl/handler_ptr.ipp
+++ b/boost/beast/core/impl/handler_ptr.ipp
@@ -18,87 +18,72 @@ 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))
+void
+handler_ptr<T, Handler>::
+clear()
{
- 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;
- }
+ typename beast::detail::allocator_traits<
+ boost::asio::associated_allocator_t<
+ Handler>>::template rebind_alloc<T> alloc(
+ boost::asio::get_associated_allocator(
+ handler()));
+ beast::detail::allocator_traits<
+ decltype(alloc)>::destroy(alloc, t_);
+ beast::detail::allocator_traits<
+ decltype(alloc)>::deallocate(alloc, t_, 1);
+ t_ = nullptr;
}
template<class T, class Handler>
handler_ptr<T, Handler>::
~handler_ptr()
{
- if(! p_)
- return;
- if(--p_->n)
- return;
- if(p_->t)
+ if(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);
+ clear();
+ handler().~Handler();
}
- delete p_;
}
template<class T, class Handler>
handler_ptr<T, Handler>::
handler_ptr(handler_ptr&& other)
- : p_(other.p_)
+ : t_(other.t_)
{
- 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);
+ if(other.t_)
+ {
+ new(&h_) Handler(std::move(other.handler()));
+ other.handler().~Handler();
+ other.t_ = nullptr;
+ }
}
template<class T, class Handler>
-template<class... Args>
+template<class DeducedHandler, class... Args>
handler_ptr<T, Handler>::
-handler_ptr(Handler const& handler, Args&&... args)
- : p_(new P{handler, std::forward<Args>(args)...})
+handler_ptr(DeducedHandler&& h, Args&&... args)
{
BOOST_STATIC_ASSERT(! std::is_array<T>::value);
+ typename beast::detail::allocator_traits<
+ boost::asio::associated_allocator_t<
+ Handler>>::template rebind_alloc<T> alloc{
+ boost::asio::get_associated_allocator(h)};
+ using A = decltype(alloc);
+ bool destroy = false;
+ auto deleter = [&alloc, &destroy](T* p)
+ {
+ if(destroy)
+ beast::detail::allocator_traits<A>::destroy(alloc, p);
+ beast::detail::allocator_traits<A>::deallocate(alloc, p, 1);
+ };
+ std::unique_ptr<T, decltype(deleter)> t{
+ beast::detail::allocator_traits<A>::allocate(alloc, 1), deleter};
+ beast::detail::allocator_traits<A>::construct(alloc, t.get(),
+ static_cast<DeducedHandler const&>(h),
+ std::forward<Args>(args)...);
+ destroy = true;
+ new(&h_) Handler(std::forward<DeducedHandler>(h));
+ t_ = t.release();
}
template<class T, class Handler>
@@ -107,18 +92,16 @@ 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);
+ BOOST_ASSERT(t_);
+ clear();
+ auto deleter = [](Handler* h)
+ {
+ h->~Handler();
+ };
+ std::unique_ptr<
+ Handler, decltype(deleter)> destroyer{
+ &handler(), deleter};
+ return std::move(handler());
}
template<class T, class Handler>
@@ -127,18 +110,16 @@ 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)...);
+ BOOST_ASSERT(t_);
+ clear();
+ auto deleter = [](Handler* h)
+ {
+ h->~Handler();
+ };
+ std::unique_ptr<
+ Handler, decltype(deleter)> destroyer{
+ &handler(), deleter};
+ handler()(std::forward<Args>(args)...);
}
} // beast