forked from boostorg/beast
Refactor basic_fields allocator internals:
fix #857 * Use empty base optimization to store the allocator * Rebind to a smaller aligned type to reduce waste
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
Version 145:
|
Version 145:
|
||||||
|
|
||||||
* Rename some detail functions
|
* Rename some detail functions
|
||||||
|
* Refactor basic_fields allocator internals
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#include <boost/beast/core/string_param.hpp>
|
#include <boost/beast/core/string_param.hpp>
|
||||||
#include <boost/beast/core/string.hpp>
|
#include <boost/beast/core/string.hpp>
|
||||||
#include <boost/beast/core/detail/allocator.hpp>
|
#include <boost/beast/core/detail/allocator.hpp>
|
||||||
|
#include <boost/beast/core/detail/empty_base_optimization.hpp>
|
||||||
#include <boost/beast/http/field.hpp>
|
#include <boost/beast/http/field.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/intrusive/list.hpp>
|
#include <boost/intrusive/list.hpp>
|
||||||
@@ -51,6 +52,9 @@ namespace http {
|
|||||||
*/
|
*/
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
class basic_fields
|
class basic_fields
|
||||||
|
#ifndef BOOST_BEAST_DOXYGEN
|
||||||
|
: private beast::detail::empty_base_optimization<Allocator>
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
friend class fields_test; // for `header`
|
friend class fields_test; // for `header`
|
||||||
|
|
||||||
@@ -260,7 +264,7 @@ public:
|
|||||||
allocator_type
|
allocator_type
|
||||||
get_allocator() const
|
get_allocator() const
|
||||||
{
|
{
|
||||||
return alloc_;
|
return this->member();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
@@ -681,12 +685,15 @@ private:
|
|||||||
template<class OtherAlloc>
|
template<class OtherAlloc>
|
||||||
friend class basic_fields;
|
friend class basic_fields;
|
||||||
|
|
||||||
using base_alloc_type = typename
|
using align_type = typename
|
||||||
|
boost::type_with_alignment<alignof(value_type)>::type;
|
||||||
|
|
||||||
|
using rebind_type = typename
|
||||||
beast::detail::allocator_traits<Allocator>::
|
beast::detail::allocator_traits<Allocator>::
|
||||||
template rebind_alloc<value_type>;
|
template rebind_alloc<align_type>;
|
||||||
|
|
||||||
using alloc_traits =
|
using alloc_traits =
|
||||||
beast::detail::allocator_traits<base_alloc_type>;
|
beast::detail::allocator_traits<rebind_type>;
|
||||||
|
|
||||||
using size_type = typename
|
using size_type = typename
|
||||||
beast::detail::allocator_traits<Allocator>::size_type;
|
beast::detail::allocator_traits<Allocator>::size_type;
|
||||||
@@ -736,7 +743,6 @@ private:
|
|||||||
void
|
void
|
||||||
swap(basic_fields& other, std::false_type);
|
swap(basic_fields& other, std::false_type);
|
||||||
|
|
||||||
base_alloc_type alloc_;
|
|
||||||
set_t set_;
|
set_t set_;
|
||||||
list_t list_;
|
list_t list_;
|
||||||
string_view method_;
|
string_view method_;
|
||||||
|
@@ -350,14 +350,15 @@ basic_fields<Allocator>::
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_fields<Allocator>::
|
basic_fields<Allocator>::
|
||||||
basic_fields(Allocator const& alloc)
|
basic_fields(Allocator const& alloc)
|
||||||
: alloc_(alloc)
|
: beast::detail::empty_base_optimization<Allocator>(alloc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_fields<Allocator>::
|
basic_fields<Allocator>::
|
||||||
basic_fields(basic_fields&& other)
|
basic_fields(basic_fields&& other)
|
||||||
: alloc_(std::move(other.alloc_))
|
: beast::detail::empty_base_optimization<Allocator>(
|
||||||
|
std::move(other.member()))
|
||||||
, set_(std::move(other.set_))
|
, set_(std::move(other.set_))
|
||||||
, list_(std::move(other.list_))
|
, list_(std::move(other.list_))
|
||||||
, method_(other.method_)
|
, method_(other.method_)
|
||||||
@@ -370,9 +371,9 @@ basic_fields(basic_fields&& other)
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_fields<Allocator>::
|
basic_fields<Allocator>::
|
||||||
basic_fields(basic_fields&& other, Allocator const& alloc)
|
basic_fields(basic_fields&& other, Allocator const& alloc)
|
||||||
: alloc_(alloc)
|
: beast::detail::empty_base_optimization<Allocator>(alloc)
|
||||||
{
|
{
|
||||||
if(alloc_ != other.alloc_)
|
if(this->member() != other.member())
|
||||||
{
|
{
|
||||||
copy_all(other);
|
copy_all(other);
|
||||||
other.clear_all();
|
other.clear_all();
|
||||||
@@ -389,8 +390,8 @@ basic_fields(basic_fields&& other, Allocator const& alloc)
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
basic_fields<Allocator>::
|
basic_fields<Allocator>::
|
||||||
basic_fields(basic_fields const& other)
|
basic_fields(basic_fields const& other)
|
||||||
: alloc_(alloc_traits::
|
: beast::detail::empty_base_optimization<Allocator>(alloc_traits::
|
||||||
select_on_container_copy_construction(other.alloc_))
|
select_on_container_copy_construction(other.member()))
|
||||||
{
|
{
|
||||||
copy_all(other);
|
copy_all(other);
|
||||||
}
|
}
|
||||||
@@ -399,7 +400,7 @@ template<class Allocator>
|
|||||||
basic_fields<Allocator>::
|
basic_fields<Allocator>::
|
||||||
basic_fields(basic_fields const& other,
|
basic_fields(basic_fields const& other,
|
||||||
Allocator const& alloc)
|
Allocator const& alloc)
|
||||||
: alloc_(alloc)
|
: beast::detail::empty_base_optimization<Allocator>(alloc)
|
||||||
{
|
{
|
||||||
copy_all(other);
|
copy_all(other);
|
||||||
}
|
}
|
||||||
@@ -417,7 +418,7 @@ template<class OtherAlloc>
|
|||||||
basic_fields<Allocator>::
|
basic_fields<Allocator>::
|
||||||
basic_fields(basic_fields<OtherAlloc> const& other,
|
basic_fields(basic_fields<OtherAlloc> const& other,
|
||||||
Allocator const& alloc)
|
Allocator const& alloc)
|
||||||
: alloc_(alloc)
|
: beast::detail::empty_base_optimization<Allocator>(alloc)
|
||||||
{
|
{
|
||||||
copy_all(other);
|
copy_all(other);
|
||||||
}
|
}
|
||||||
@@ -1014,13 +1015,13 @@ set_chunked_impl(bool value)
|
|||||||
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
|
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
|
||||||
std::string s;
|
std::string s;
|
||||||
#else
|
#else
|
||||||
using rebind_type =
|
using A =
|
||||||
typename beast::detail::allocator_traits<
|
typename beast::detail::allocator_traits<
|
||||||
Allocator>::template rebind_alloc<char>;
|
Allocator>::template rebind_alloc<char>;
|
||||||
std::basic_string<
|
std::basic_string<
|
||||||
char,
|
char,
|
||||||
std::char_traits<char>,
|
std::char_traits<char>,
|
||||||
rebind_type> s{rebind_type{alloc_}};
|
A> s{A{this->member()}};
|
||||||
#endif
|
#endif
|
||||||
s.reserve(it->value().size() + 9);
|
s.reserve(it->value().size() + 9);
|
||||||
s.append(it->value().data(), it->value().size());
|
s.append(it->value().data(), it->value().size());
|
||||||
@@ -1051,13 +1052,13 @@ set_chunked_impl(bool value)
|
|||||||
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
|
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
|
||||||
std::string s;
|
std::string s;
|
||||||
#else
|
#else
|
||||||
using rebind_type =
|
using A =
|
||||||
typename beast::detail::allocator_traits<
|
typename beast::detail::allocator_traits<
|
||||||
Allocator>::template rebind_alloc<char>;
|
Allocator>::template rebind_alloc<char>;
|
||||||
std::basic_string<
|
std::basic_string<
|
||||||
char,
|
char,
|
||||||
std::char_traits<char>,
|
std::char_traits<char>,
|
||||||
rebind_type> s{rebind_type{alloc_}};
|
A> s{A{this->member()}};
|
||||||
#endif
|
#endif
|
||||||
s.reserve(it->value().size());
|
s.reserve(it->value().size());
|
||||||
detail::filter_token_list_last(s, it->value(),
|
detail::filter_token_list_last(s, it->value(),
|
||||||
@@ -1108,13 +1109,13 @@ set_keep_alive_impl(
|
|||||||
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
|
// Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437
|
||||||
std::string s;
|
std::string s;
|
||||||
#else
|
#else
|
||||||
using rebind_type =
|
using A =
|
||||||
typename beast::detail::allocator_traits<
|
typename beast::detail::allocator_traits<
|
||||||
Allocator>::template rebind_alloc<char>;
|
Allocator>::template rebind_alloc<char>;
|
||||||
std::basic_string<
|
std::basic_string<
|
||||||
char,
|
char,
|
||||||
std::char_traits<char>,
|
std::char_traits<char>,
|
||||||
rebind_type> s{rebind_type{alloc_}};
|
A> s{A{this->member()}};
|
||||||
#endif
|
#endif
|
||||||
s.reserve(value.size());
|
s.reserve(value.size());
|
||||||
detail::keep_alive_impl(
|
detail::keep_alive_impl(
|
||||||
@@ -1148,13 +1149,14 @@ new_element(field name,
|
|||||||
static_cast<off_t>(sname.size() + 2);
|
static_cast<off_t>(sname.size() + 2);
|
||||||
std::uint16_t const len =
|
std::uint16_t const len =
|
||||||
static_cast<off_t>(value.size());
|
static_cast<off_t>(value.size());
|
||||||
auto const p = alloc_traits::allocate(alloc_,
|
auto a = rebind_type{this->member()};
|
||||||
1 + (off + len + 2 + sizeof(value_type) - 1) /
|
auto const p = alloc_traits::allocate(a,
|
||||||
sizeof(value_type));
|
(sizeof(value_type) + off + len + 2 + sizeof(align_type) - 1) /
|
||||||
|
sizeof(align_type));
|
||||||
// VFALCO allocator can't call the constructor because its private
|
// VFALCO allocator can't call the constructor because its private
|
||||||
//alloc_traits::construct(alloc_, p, name, sname, value);
|
//alloc_traits::construct(a, p, name, sname, value);
|
||||||
new(p) value_type{name, sname, value};
|
new(p) value_type{name, sname, value};
|
||||||
return *p;
|
return *reinterpret_cast<value_type*>(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
@@ -1162,10 +1164,14 @@ void
|
|||||||
basic_fields<Allocator>::
|
basic_fields<Allocator>::
|
||||||
delete_element(value_type& e)
|
delete_element(value_type& e)
|
||||||
{
|
{
|
||||||
auto const n = 1 + (e.off_ + e.len_ + 2 +
|
auto a = rebind_type{this->member()};
|
||||||
sizeof(value_type) - 1) / sizeof(value_type);
|
auto const n =
|
||||||
alloc_traits::destroy(alloc_, &e);
|
(sizeof(value_type) + e.off_ + e.len_ + 2 + sizeof(align_type) - 1) /
|
||||||
alloc_traits::deallocate(alloc_, &e, n);
|
sizeof(align_type);
|
||||||
|
//alloc_traits::destroy(a, &e);
|
||||||
|
e.~value_type();
|
||||||
|
alloc_traits::deallocate(a,
|
||||||
|
reinterpret_cast<align_type*>(&e), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
@@ -1207,7 +1213,7 @@ realloc_string(string_view& dest, string_view s)
|
|||||||
return;
|
return;
|
||||||
auto a = typename beast::detail::allocator_traits<
|
auto a = typename beast::detail::allocator_traits<
|
||||||
Allocator>::template rebind_alloc<
|
Allocator>::template rebind_alloc<
|
||||||
char>(alloc_);
|
char>(this->member());
|
||||||
if(! dest.empty())
|
if(! dest.empty())
|
||||||
{
|
{
|
||||||
a.deallocate(const_cast<char*>(
|
a.deallocate(const_cast<char*>(
|
||||||
@@ -1235,7 +1241,7 @@ realloc_target(
|
|||||||
return;
|
return;
|
||||||
auto a = typename beast::detail::allocator_traits<
|
auto a = typename beast::detail::allocator_traits<
|
||||||
Allocator>::template rebind_alloc<
|
Allocator>::template rebind_alloc<
|
||||||
char>(alloc_);
|
char>(this->member());
|
||||||
if(! dest.empty())
|
if(! dest.empty())
|
||||||
{
|
{
|
||||||
a.deallocate(const_cast<char*>(
|
a.deallocate(const_cast<char*>(
|
||||||
@@ -1298,7 +1304,7 @@ move_assign(basic_fields& other, std::true_type)
|
|||||||
target_or_reason_ = other.target_or_reason_;
|
target_or_reason_ = other.target_or_reason_;
|
||||||
other.method_.clear();
|
other.method_.clear();
|
||||||
other.target_or_reason_.clear();
|
other.target_or_reason_.clear();
|
||||||
alloc_ = other.alloc_;
|
this->member() = other.member();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
@@ -1308,7 +1314,7 @@ basic_fields<Allocator>::
|
|||||||
move_assign(basic_fields& other, std::false_type)
|
move_assign(basic_fields& other, std::false_type)
|
||||||
{
|
{
|
||||||
clear_all();
|
clear_all();
|
||||||
if(alloc_ != other.alloc_)
|
if(this->member() != other.member())
|
||||||
{
|
{
|
||||||
copy_all(other);
|
copy_all(other);
|
||||||
other.clear_all();
|
other.clear_all();
|
||||||
@@ -1331,7 +1337,7 @@ basic_fields<Allocator>::
|
|||||||
copy_assign(basic_fields const& other, std::true_type)
|
copy_assign(basic_fields const& other, std::true_type)
|
||||||
{
|
{
|
||||||
clear_all();
|
clear_all();
|
||||||
alloc_ = other.alloc_;
|
this->member() = other.member();
|
||||||
copy_all(other);
|
copy_all(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1352,7 +1358,7 @@ basic_fields<Allocator>::
|
|||||||
swap(basic_fields& other, std::true_type)
|
swap(basic_fields& other, std::true_type)
|
||||||
{
|
{
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(alloc_, other.alloc_);
|
swap(this->member(), other.member());
|
||||||
swap(set_, other.set_);
|
swap(set_, other.set_);
|
||||||
swap(list_, other.list_);
|
swap(list_, other.list_);
|
||||||
swap(method_, other.method_);
|
swap(method_, other.method_);
|
||||||
@@ -1365,7 +1371,7 @@ void
|
|||||||
basic_fields<Allocator>::
|
basic_fields<Allocator>::
|
||||||
swap(basic_fields& other, std::false_type)
|
swap(basic_fields& other, std::false_type)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(alloc_ == other.alloc_);
|
BOOST_ASSERT(this->member() == other.member());
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(set_, other.set_);
|
swap(set_, other.set_);
|
||||||
swap(list_, other.list_);
|
swap(list_, other.list_);
|
||||||
|
@@ -862,7 +862,8 @@ struct message
|
|||||||
#endif
|
#endif
|
||||||
body()& noexcept
|
body()& noexcept
|
||||||
{
|
{
|
||||||
return this->member();
|
return this->beast::detail::empty_base_optimization<
|
||||||
|
typename Body::value_type>::member();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the body
|
/// Returns the body
|
||||||
@@ -873,7 +874,9 @@ struct message
|
|||||||
#endif
|
#endif
|
||||||
body()&& noexcept
|
body()&& noexcept
|
||||||
{
|
{
|
||||||
return std::move(this->member());
|
return std::move(
|
||||||
|
this->beast::detail::empty_base_optimization<
|
||||||
|
typename Body::value_type>::member());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the body
|
/// Returns the body
|
||||||
@@ -884,7 +887,8 @@ struct message
|
|||||||
#endif
|
#endif
|
||||||
body() const& noexcept
|
body() const& noexcept
|
||||||
{
|
{
|
||||||
return this->member();
|
return this->beast::detail::empty_base_optimization<
|
||||||
|
typename Body::value_type>::member();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Reference in New Issue
Block a user