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

View File

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