Simplify handler_ptr:

Replace aligned_union in handler_ptr with the built-in one to reduce
the number of template instantiations and remove the reinterpret_casts
that were required.

Signed-off-by: Damian Jarek <damian.jarek93@gmail.com>
This commit is contained in:
Damian Jarek
2018-11-02 14:15:25 +01:00
committed by Vinnie Falco
parent 587929edf6
commit 34037d538e
3 changed files with 29 additions and 24 deletions

View File

@@ -2,6 +2,7 @@ Version 196:
* Tidy up calls to placement new * Tidy up calls to placement new
* Remove unused type_traits * Remove unused type_traits
* Simplify handler_ptr
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@@ -12,7 +12,6 @@
#include <boost/beast/core/detail/allocator.hpp> #include <boost/beast/core/detail/allocator.hpp>
#include <boost/beast/core/detail/config.hpp> #include <boost/beast/core/detail/config.hpp>
#include <boost/beast/core/detail/type_traits.hpp>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
@@ -50,10 +49,11 @@ namespace beast {
template<class T, class Handler> template<class T, class Handler>
class handler_ptr class handler_ptr
{ {
using handler_storage_t = typename detail::aligned_union<1, Handler>::type;
T* t_ = nullptr; T* t_ = nullptr;
handler_storage_t h_; union
{
Handler h_;
};
void clear(); void clear();
@@ -113,20 +113,21 @@ public:
the owned object's constructor. the owned object's constructor.
*/ */
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
explicit handler_ptr(DeducedHandler&& handler, Args&&... args); explicit
handler_ptr(DeducedHandler&& handler, Args&&... args);
/// Return a reference to the handler /// Return a reference to the handler
handler_type const& handler_type const&
handler() const handler() const
{ {
return *reinterpret_cast<Handler const*>(&h_); return h_;
} }
/// Return a reference to the handler /// Return a reference to the handler
handler_type& handler_type&
handler() handler()
{ {
return *reinterpret_cast<Handler*>(&h_); return h_;
} }
/// Return `true` if `*this` owns an object /// Return `true` if `*this` owns an object
@@ -167,7 +168,7 @@ public:
return t_; return t_;
} }
/** Return ownership of the handler /** Returns ownership of the handler
Before this function returns, the owned object is Before this function returns, the owned object is
destroyed, satisfying the deallocation-before-invocation destroyed, satisfying the deallocation-before-invocation

View File

@@ -41,7 +41,7 @@ handler_ptr<T, Handler>::
if(t_) if(t_)
{ {
clear(); clear();
handler().~Handler(); h_.~Handler();
} }
} }
@@ -52,8 +52,9 @@ handler_ptr(handler_ptr&& other)
{ {
if(other.t_) if(other.t_)
{ {
new(&h_) Handler(std::move(other.handler())); ::new(static_cast<void*>(std::addressof(h_)))
other.handler().~Handler(); Handler(std::move(other.h_));
other.h_.~Handler();
other.t_ = nullptr; other.t_ = nullptr;
} }
} }
@@ -64,25 +65,27 @@ handler_ptr<T, Handler>::
handler_ptr(DeducedHandler&& h, Args&&... args) handler_ptr(DeducedHandler&& h, Args&&... args)
{ {
BOOST_STATIC_ASSERT(! std::is_array<T>::value); BOOST_STATIC_ASSERT(! std::is_array<T>::value);
typename beast::detail::allocator_traits< using A = typename beast::detail::allocator_traits<
net::associated_allocator_t< net::associated_allocator_t<
Handler>>::template rebind_alloc<T> alloc{ Handler>>::template rebind_alloc<T>;
net::get_associated_allocator(h)}; A alloc{net::get_associated_allocator(h)};
using A = decltype(alloc); using traits =
typename beast::detail::allocator_traits<A>;
bool destroy = false; bool destroy = false;
auto deleter = [&alloc, &destroy](T* p) auto deleter = [&alloc, &destroy](T* p)
{ {
if(destroy) if(destroy)
beast::detail::allocator_traits<A>::destroy(alloc, p); traits::destroy(alloc, p);
beast::detail::allocator_traits<A>::deallocate(alloc, p, 1); traits::deallocate(alloc, p, 1);
}; };
std::unique_ptr<T, decltype(deleter)> t{ std::unique_ptr<T, decltype(deleter)> t{
beast::detail::allocator_traits<A>::allocate(alloc, 1), deleter}; traits::allocate(alloc, 1), deleter};
beast::detail::allocator_traits<A>::construct(alloc, t.get(), traits::construct(alloc, t.get(),
static_cast<DeducedHandler const&>(h), static_cast<DeducedHandler const&>(h),
std::forward<Args>(args)...); std::forward<Args>(args)...);
destroy = true; destroy = true;
new(&h_) Handler(std::forward<DeducedHandler>(h)); ::new(static_cast<void*>(std::addressof(h_)))
Handler(std::forward<DeducedHandler>(h));
t_ = t.release(); t_ = t.release();
} }
@@ -100,8 +103,8 @@ release_handler() ->
}; };
std::unique_ptr< std::unique_ptr<
Handler, decltype(deleter)> destroyer{ Handler, decltype(deleter)> destroyer{
&handler(), deleter}; std::addressof(h_), deleter};
return std::move(handler()); return std::move(h_);
} }
template<class T, class Handler> template<class T, class Handler>
@@ -119,8 +122,8 @@ invoke(Args&&... args)
}; };
std::unique_ptr< std::unique_ptr<
Handler, decltype(deleter)> destroyer{ Handler, decltype(deleter)> destroyer{
&handler(), deleter}; std::addressof(h_), deleter};
handler()(std::forward<Args>(args)...); h_(std::forward<Args>(args)...);
} }
} // beast } // beast