mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 04:47:29 +02:00
Fix multi_buffer allocation alignment
This commit is contained in:
@ -5,6 +5,7 @@ Version 261:
|
||||
* Remove redundant includes in websocket
|
||||
* Simplify websocket::detail::prng
|
||||
* Don't over-allocate in http::basic_fields
|
||||
* Fix multi_buffer allocation alignment
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
@ -87,41 +87,6 @@ namespace beast {
|
||||
in_pos_ out_pos_ == 0
|
||||
out_end_ == 0
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class Allocator>
|
||||
class basic_multi_buffer<Allocator>::element
|
||||
: public boost::intrusive::list_base_hook<
|
||||
boost::intrusive::link_mode<
|
||||
boost::intrusive::normal_link>>
|
||||
{
|
||||
using size_type = typename
|
||||
detail::allocator_traits<Allocator>::size_type;
|
||||
|
||||
size_type const size_;
|
||||
|
||||
public:
|
||||
element(element const&) = delete;
|
||||
|
||||
explicit
|
||||
element(size_type n) noexcept
|
||||
: size_(n)
|
||||
{
|
||||
}
|
||||
|
||||
size_type
|
||||
size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
char*
|
||||
data() const noexcept
|
||||
{
|
||||
return const_cast<char*>(
|
||||
reinterpret_cast<char const*>(this + 1));
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@ -486,7 +451,7 @@ template<class Allocator>
|
||||
basic_multi_buffer<Allocator>::
|
||||
basic_multi_buffer(
|
||||
Allocator const& alloc) noexcept
|
||||
: boost::empty_value<base_alloc_type>(
|
||||
: boost::empty_value<Allocator>(
|
||||
boost::empty_init_t(), alloc)
|
||||
, max_(alloc_traits::max_size(this->get()))
|
||||
, out_(list_.end())
|
||||
@ -498,8 +463,8 @@ basic_multi_buffer<Allocator>::
|
||||
basic_multi_buffer(
|
||||
std::size_t limit,
|
||||
Allocator const& alloc) noexcept
|
||||
: boost::empty_value<
|
||||
base_alloc_type>(boost::empty_init_t(), alloc)
|
||||
: boost::empty_value<Allocator>(
|
||||
boost::empty_init_t(), alloc)
|
||||
, max_(limit)
|
||||
, out_(list_.end())
|
||||
{
|
||||
@ -509,7 +474,7 @@ template<class Allocator>
|
||||
basic_multi_buffer<Allocator>::
|
||||
basic_multi_buffer(
|
||||
basic_multi_buffer&& other) noexcept
|
||||
: boost::empty_value<base_alloc_type>(
|
||||
: boost::empty_value<Allocator>(
|
||||
boost::empty_init_t(), std::move(other.get()))
|
||||
, max_(other.max_)
|
||||
, in_size_(boost::exchange(other.in_size_, 0))
|
||||
@ -529,8 +494,8 @@ basic_multi_buffer<Allocator>::
|
||||
basic_multi_buffer(
|
||||
basic_multi_buffer&& other,
|
||||
Allocator const& alloc)
|
||||
: boost::empty_value<
|
||||
base_alloc_type>(boost::empty_init_t(), alloc)
|
||||
: boost::empty_value<Allocator>(
|
||||
boost::empty_init_t(), alloc)
|
||||
, max_(other.max_)
|
||||
{
|
||||
if(this->get() != other.get())
|
||||
@ -561,7 +526,7 @@ template<class Allocator>
|
||||
basic_multi_buffer<Allocator>::
|
||||
basic_multi_buffer(
|
||||
basic_multi_buffer const& other)
|
||||
: boost::empty_value<base_alloc_type>(
|
||||
: boost::empty_value<Allocator>(
|
||||
boost::empty_init_t(), alloc_traits::
|
||||
select_on_container_copy_construction(
|
||||
other.get()))
|
||||
@ -576,7 +541,7 @@ basic_multi_buffer<Allocator>::
|
||||
basic_multi_buffer(
|
||||
basic_multi_buffer const& other,
|
||||
Allocator const& alloc)
|
||||
: boost::empty_value<base_alloc_type>(
|
||||
: boost::empty_value<Allocator>(
|
||||
boost::empty_init_t(), alloc)
|
||||
, max_(other.max_)
|
||||
, out_(list_.end())
|
||||
@ -600,8 +565,8 @@ basic_multi_buffer<Allocator>::
|
||||
basic_multi_buffer(
|
||||
basic_multi_buffer<OtherAlloc> const& other,
|
||||
allocator_type const& alloc)
|
||||
: boost::empty_value<
|
||||
base_alloc_type>(boost::empty_init_t(), alloc)
|
||||
: boost::empty_value<Allocator>(
|
||||
boost::empty_init_t(), alloc)
|
||||
, max_(other.max_)
|
||||
, out_(list_.end())
|
||||
{
|
||||
@ -991,6 +956,7 @@ consume(size_type n) noexcept
|
||||
{
|
||||
if(list_.empty())
|
||||
return;
|
||||
auto a = rebind_type{this->get()};
|
||||
for(;;)
|
||||
{
|
||||
if(list_.begin() != out_)
|
||||
@ -1013,8 +979,8 @@ consume(size_type n) noexcept
|
||||
list_.erase(list_.iterator_to(e));
|
||||
auto const len = sizeof(e) + e.size();
|
||||
e.~element();
|
||||
alloc_traits::deallocate(this->get(),
|
||||
reinterpret_cast<char*>(&e), len);
|
||||
alloc_traits::deallocate(a,
|
||||
reinterpret_cast<align_type*>(&e), len);
|
||||
#if BOOST_BEAST_MULTI_BUFFER_DEBUG_CHECK
|
||||
debug_check();
|
||||
#endif
|
||||
@ -1215,10 +1181,13 @@ void
|
||||
basic_multi_buffer<Allocator>::
|
||||
destroy(element& e)
|
||||
{
|
||||
auto const len = sizeof(e) + e.size();
|
||||
auto a = rebind_type{this->get()};
|
||||
auto const n =
|
||||
(sizeof(element) + e.size() + sizeof(align_type) - 1) /
|
||||
sizeof(align_type);
|
||||
e.~element();
|
||||
alloc_traits::deallocate(this->get(),
|
||||
reinterpret_cast<char*>(&e), len);
|
||||
alloc_traits::deallocate(a,
|
||||
reinterpret_cast<align_type*>(&e), n);
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
@ -1230,9 +1199,11 @@ alloc(std::size_t size) ->
|
||||
if(size > alloc_traits::max_size(this->get()))
|
||||
BOOST_THROW_EXCEPTION(std::length_error(
|
||||
"A basic_multi_buffer exceeded the allocator's maximum size"));
|
||||
return *::new(alloc_traits::allocate(
|
||||
this->get(),
|
||||
sizeof(element) + size)) element(size);
|
||||
auto a = rebind_type{this->get()};
|
||||
auto const p = alloc_traits::allocate(a,
|
||||
(sizeof(element) + size + sizeof(align_type) - 1) /
|
||||
sizeof(align_type));
|
||||
return *(::new(p) element(size));
|
||||
}
|
||||
|
||||
template<class Allocator>
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/core/empty_value.hpp>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <boost/type_traits/type_with_alignment.hpp>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
@ -62,14 +63,13 @@ namespace beast {
|
||||
template<class Allocator>
|
||||
class basic_multi_buffer
|
||||
#if ! BOOST_BEAST_DOXYGEN
|
||||
: private boost::empty_value<
|
||||
typename detail::allocator_traits<Allocator>::
|
||||
template rebind_alloc<char>>
|
||||
: private boost::empty_value<Allocator>
|
||||
#endif
|
||||
{
|
||||
using base_alloc_type = typename
|
||||
detail::allocator_traits<Allocator>::
|
||||
template rebind_alloc<char>;
|
||||
// Fancy pointers are not supported
|
||||
static_assert(std::is_pointer<typename
|
||||
std::allocator_traits<Allocator>::pointer>::value,
|
||||
"Allocator must use regular pointers");
|
||||
|
||||
static bool constexpr default_nothrow =
|
||||
std::is_nothrow_default_constructible<Allocator>::value;
|
||||
@ -77,19 +77,61 @@ class basic_multi_buffer
|
||||
// Storage for the list of buffers representing the input
|
||||
// and output sequences. The allocation for each element
|
||||
// contains `element` followed by raw storage bytes.
|
||||
class element;
|
||||
class element
|
||||
: public boost::intrusive::list_base_hook<
|
||||
boost::intrusive::link_mode<
|
||||
boost::intrusive::normal_link>>
|
||||
{
|
||||
using size_type = typename
|
||||
detail::allocator_traits<Allocator>::size_type;
|
||||
|
||||
size_type const size_;
|
||||
|
||||
public:
|
||||
element(element const&) = delete;
|
||||
|
||||
explicit
|
||||
element(size_type n) noexcept
|
||||
: size_(n)
|
||||
{
|
||||
}
|
||||
|
||||
size_type
|
||||
size() const noexcept
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
char*
|
||||
data() const noexcept
|
||||
{
|
||||
return const_cast<char*>(
|
||||
reinterpret_cast<char const*>(this + 1));
|
||||
}
|
||||
};
|
||||
|
||||
template<bool>
|
||||
class readable_bytes;
|
||||
|
||||
using alloc_traits =
|
||||
beast::detail::allocator_traits<base_alloc_type>;
|
||||
using list_type = typename boost::intrusive::make_list<element,
|
||||
boost::intrusive::constant_time_size<true>>::type;
|
||||
using iter = typename list_type::iterator;
|
||||
using const_iter = typename list_type::const_iterator;
|
||||
using size_type = typename
|
||||
detail::allocator_traits<Allocator>::size_type;
|
||||
|
||||
using size_type = typename alloc_traits::size_type;
|
||||
using align_type = typename
|
||||
boost::type_with_alignment<alignof(element)>::type;
|
||||
|
||||
using rebind_type = typename
|
||||
beast::detail::allocator_traits<Allocator>::
|
||||
template rebind_alloc<align_type>;
|
||||
|
||||
using alloc_traits =
|
||||
beast::detail::allocator_traits<rebind_type>;
|
||||
|
||||
using list_type = typename boost::intrusive::make_list<
|
||||
element, boost::intrusive::constant_time_size<true>>::type;
|
||||
|
||||
using iter = typename list_type::iterator;
|
||||
|
||||
using const_iter = typename list_type::const_iterator;
|
||||
|
||||
using pocma = typename
|
||||
alloc_traits::propagate_on_container_move_assignment;
|
||||
|
Reference in New Issue
Block a user