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