diff --git a/CHANGELOG.md b/CHANGELOG.md index 24a04d0d..36f17631 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ Version 103: * Boost test matrix fixes +* Tidy up allocator usage -------------------------------------------------------------------------------- diff --git a/include/boost/beast/core/detail/allocator.hpp b/include/boost/beast/core/detail/allocator.hpp new file mode 100644 index 00000000..39b2aa5f --- /dev/null +++ b/include/boost/beast/core/detail/allocator.hpp @@ -0,0 +1,42 @@ +// +// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +#ifndef BOOST_BEAST_DETAIL_ALLOCATOR_HPP +#define BOOST_BEAST_DETAIL_ALLOCATOR_HPP + +#include +#if BOOST_NO_CXX11_ALLOCATOR +#include +#else +#include +#endif + +namespace boost { +namespace beast { +namespace detail { + +// This is a workaround for allocator_traits +// implementations which falsely claim C++11 +// compatibility. + +#if BOOST_NO_CXX11_ALLOCATOR +template +using allocator_traits = boost::container::allocator_traits; + +#else +template +using allocator_traits = std::allocator_traits; + +#endif + +} // detail +} // beast +} // boost + +#endif diff --git a/include/boost/beast/core/flat_buffer.hpp b/include/boost/beast/core/flat_buffer.hpp index 02b071d3..d6d5fa04 100644 --- a/include/boost/beast/core/flat_buffer.hpp +++ b/include/boost/beast/core/flat_buffer.hpp @@ -11,6 +11,7 @@ #define BOOST_BEAST_FLAT_BUFFER_HPP #include +#include #include #include #include @@ -44,21 +45,10 @@ template class basic_flat_buffer #if ! BOOST_BEAST_DOXYGEN : private detail::empty_base_optimization< - typename std::allocator_traits:: + typename detail::allocator_traits:: template rebind_alloc> #endif { -public: -#if BOOST_BEAST_DOXYGEN - /// The type of allocator used. - using allocator_type = Allocator; -#else - using allocator_type = typename - std::allocator_traits:: - template rebind_alloc; -#endif - -private: enum { min_size = 512 @@ -67,8 +57,12 @@ private: template friend class basic_flat_buffer; + using base_alloc_type = typename + detail::allocator_traits:: + template rebind_alloc; + using alloc_traits = - std::allocator_traits; + detail::allocator_traits; static inline @@ -86,6 +80,9 @@ private: std::size_t max_; public: + /// The type of allocator used. + using allocator_type = Allocator; + /// The type used to represent the input sequence as a list of buffers. using const_buffers_type = boost::asio::const_buffers_1; diff --git a/include/boost/beast/core/impl/flat_buffer.ipp b/include/boost/beast/core/impl/flat_buffer.ipp index 4b8ceac0..95c38d89 100644 --- a/include/boost/beast/core/impl/flat_buffer.ipp +++ b/include/boost/beast/core/impl/flat_buffer.ipp @@ -58,7 +58,7 @@ basic_flat_buffer(std::size_t limit) template basic_flat_buffer:: basic_flat_buffer(Allocator const& alloc) - : detail::empty_base_optimization(alloc) + : detail::empty_base_optimization(alloc) , begin_(nullptr) , in_(nullptr) , out_(nullptr) @@ -71,7 +71,7 @@ basic_flat_buffer(Allocator const& alloc) template basic_flat_buffer:: basic_flat_buffer(std::size_t limit, Allocator const& alloc) - : detail::empty_base_optimization(alloc) + : detail::empty_base_optimization(alloc) , begin_(nullptr) , in_(nullptr) , out_(nullptr) @@ -84,7 +84,7 @@ basic_flat_buffer(std::size_t limit, Allocator const& alloc) template basic_flat_buffer:: basic_flat_buffer(basic_flat_buffer&& other) - : detail::empty_base_optimization( + : detail::empty_base_optimization( std::move(other.member())) , begin_(other.begin_) , in_(other.in_) @@ -104,7 +104,7 @@ template basic_flat_buffer:: basic_flat_buffer(basic_flat_buffer&& other, Allocator const& alloc) - : detail::empty_base_optimization(alloc) + : detail::empty_base_optimization(alloc) { if(this->member() != other.member()) { @@ -136,7 +136,7 @@ basic_flat_buffer(basic_flat_buffer&& other, template basic_flat_buffer:: basic_flat_buffer(basic_flat_buffer const& other) - : detail::empty_base_optimization( + : detail::empty_base_optimization( alloc_traits::select_on_container_copy_construction( other.member())) , begin_(nullptr) @@ -153,7 +153,7 @@ template basic_flat_buffer:: basic_flat_buffer(basic_flat_buffer const& other, Allocator const& alloc) - : detail::empty_base_optimization(alloc) + : detail::empty_base_optimization(alloc) , begin_(nullptr) , in_(nullptr) , out_(nullptr) @@ -184,7 +184,7 @@ template basic_flat_buffer:: basic_flat_buffer(basic_flat_buffer const& other, Allocator const& alloc) - : detail::empty_base_optimization(alloc) + : detail::empty_base_optimization(alloc) , begin_(nullptr) , in_(nullptr) , out_(nullptr) @@ -202,8 +202,8 @@ operator=(basic_flat_buffer&& other) -> basic_flat_buffer& { if(this != &other) - move_assign(other, - typename alloc_traits::propagate_on_container_move_assignment{}); + move_assign(other, std::integral_constant{}); return *this; } @@ -214,8 +214,8 @@ operator=(basic_flat_buffer const& other) -> basic_flat_buffer& { if(this != &other) - copy_assign(other, - typename alloc_traits::propagate_on_container_copy_assignment{}); + copy_assign(other, std::integral_constant{}); return *this; } diff --git a/include/boost/beast/core/impl/multi_buffer.ipp b/include/boost/beast/core/impl/multi_buffer.ipp index e83a840d..e69bf472 100644 --- a/include/boost/beast/core/impl/multi_buffer.ipp +++ b/include/boost/beast/core/impl/multi_buffer.ipp @@ -92,7 +92,8 @@ class basic_multi_buffer::element boost::intrusive::link_mode< boost::intrusive::normal_link>> { - using size_type = typename std::allocator_traits::size_type; + using size_type = + typename detail::allocator_traits::size_type; size_type const size_; @@ -439,8 +440,9 @@ basic_multi_buffer(std::size_t limit) template basic_multi_buffer:: basic_multi_buffer(Allocator const& alloc) - : out_(list_.end()) - , alloc_(alloc) + : detail::empty_base_optimization< + base_alloc_type>(alloc) + , out_(list_.end()) { } @@ -448,21 +450,23 @@ template basic_multi_buffer:: basic_multi_buffer(std::size_t limit, Allocator const& alloc) - : max_(limit) + : detail::empty_base_optimization< + base_alloc_type>(alloc) + , max_(limit) , out_(list_.end()) - , alloc_(alloc) { } template basic_multi_buffer:: basic_multi_buffer(basic_multi_buffer&& other) - : max_(other.max_) + : detail::empty_base_optimization< + base_alloc_type>(std::move(other.member())) + , max_(other.max_) , in_size_(other.in_size_) , in_pos_(other.in_pos_) , out_pos_(other.out_pos_) , out_end_(other.out_end_) - , alloc_(std::move(other.alloc_)) { auto const at_end = other.out_ == other.list_.end(); @@ -479,10 +483,11 @@ template basic_multi_buffer:: basic_multi_buffer(basic_multi_buffer&& other, Allocator const& alloc) - : max_(other.max_) - , alloc_(alloc) + : detail::empty_base_optimization< + base_alloc_type>(alloc) + , max_(other.max_) { - if(alloc_ != other.alloc_) + if(this->member() != other.member()) { out_ = list_.end(); copy_from(other); @@ -509,11 +514,12 @@ basic_multi_buffer(basic_multi_buffer&& other, template basic_multi_buffer:: basic_multi_buffer(basic_multi_buffer const& other) - : max_(other.max_) - , out_(list_.end()) - , alloc_(alloc_traits:: + : detail::empty_base_optimization< + base_alloc_type>(alloc_traits:: select_on_container_copy_construction( - other.alloc_)) + other.member())) + , max_(other.max_) + , out_(list_.end()) { copy_from(other); } @@ -522,9 +528,10 @@ template basic_multi_buffer:: basic_multi_buffer(basic_multi_buffer const& other, Allocator const& alloc) - : max_(other.max_) + : detail::empty_base_optimization< + base_alloc_type>(alloc) + , max_(other.max_) , out_(list_.end()) - , alloc_(alloc) { copy_from(other); } @@ -545,9 +552,10 @@ basic_multi_buffer:: basic_multi_buffer( basic_multi_buffer const& other, allocator_type const& alloc) - : max_(other.max_) + : detail::empty_base_optimization< + base_alloc_type>(alloc) + , max_(other.max_) , out_(list_.end()) - , alloc_(alloc) { copy_from(other); } @@ -562,8 +570,8 @@ operator=(basic_multi_buffer&& other) -> return *this; reset(); max_ = other.max_; - move_assign(other, typename - alloc_traits::propagate_on_container_move_assignment{}); + move_assign(other, std::integral_constant{}); return *this; } @@ -575,8 +583,8 @@ basic_multi_buffer& { if(this == &other) return *this; - copy_assign(other, typename - alloc_traits::propagate_on_container_copy_assignment{}); + copy_assign(other, std::integral_constant{}); return *this; } @@ -678,34 +686,40 @@ prepare(size_type n) -> #endif } BOOST_ASSERT(total <= max_); - for(auto it = reuse.begin(); it != reuse.end();) + if(! reuse.empty() || n > 0) { - auto& e = *it++; - reuse.erase(list_.iterator_to(e)); - delete_element(e); - } - if(n > 0) - { - static auto const growth_factor = 2.0f; - auto const size = - std::min( - max_ - total, - std::max({ - static_cast( - in_size_ * growth_factor - in_size_), - 512, - n})); - auto& e = *reinterpret_cast(static_cast< - void*>(alloc_traits::allocate(alloc_, - sizeof(element) + size))); - alloc_traits::construct(alloc_, &e, size); - list_.push_back(e); - if(out_ == list_.end()) - out_ = list_.iterator_to(e); - out_end_ = n; - #if BOOST_BEAST_MULTI_BUFFER_DEBUG_CHECK - debug_check(); - #endif + for(auto it = reuse.begin(); it != reuse.end();) + { + auto& e = *it++; + reuse.erase(list_.iterator_to(e)); + auto const len = sizeof(e) + e.size(); + alloc_traits::destroy(this->member(), &e); + alloc_traits::deallocate(this->member(), + reinterpret_cast(&e), len); + } + if(n > 0) + { + static auto const growth_factor = 2.0f; + auto const size = + std::min( + max_ - total, + std::max({ + static_cast( + in_size_ * growth_factor - in_size_), + 512, + n})); + auto& e = *reinterpret_cast(static_cast< + void*>(alloc_traits::allocate(this->member(), + sizeof(element) + size))); + alloc_traits::construct(this->member(), &e, size); + list_.push_back(e); + if(out_ == list_.end()) + out_ = list_.iterator_to(e); + out_end_ = n; + #if BOOST_BEAST_MULTI_BUFFER_DEBUG_CHECK + debug_check(); + #endif + } } return mutable_buffers_type(*this); } @@ -784,7 +798,10 @@ consume(size_type n) in_pos_ = 0; auto& e = list_.front(); list_.erase(list_.iterator_to(e)); - delete_element(e); + auto const len = sizeof(e) + e.size(); + alloc_traits::destroy(this->member(), &e); + alloc_traits::deallocate(this->member(), + reinterpret_cast(&e), len); #if BOOST_BEAST_MULTI_BUFFER_DEBUG_CHECK debug_check(); #endif @@ -822,18 +839,6 @@ consume(size_type n) } } -template -inline -void -basic_multi_buffer:: -delete_element(element& e) -{ - auto const len = sizeof(e) + e.size(); - alloc_traits::destroy(alloc_, &e); - alloc_traits::deallocate(alloc_, - reinterpret_cast(&e), len); -} - template inline void @@ -841,7 +846,13 @@ basic_multi_buffer:: delete_list() { for(auto iter = list_.begin(); iter != list_.end();) - delete_element(*iter++); + { + auto& e = *iter++; + auto const len = sizeof(e) + e.size(); + alloc_traits::destroy(this->member(), &e); + alloc_traits::deallocate(this->member(), + reinterpret_cast(&e), len); + } } template @@ -879,7 +890,7 @@ void basic_multi_buffer:: move_assign(basic_multi_buffer& other, std::false_type) { - if(alloc_ != other.alloc_) + if(this->member() != other.member()) { copy_from(other); other.reset(); @@ -896,7 +907,7 @@ void basic_multi_buffer:: move_assign(basic_multi_buffer& other, std::true_type) { - alloc_ = std::move(alloc_); + this->member() = std::move(other.member()); auto const at_end = other.out_ == other.list_.end(); list_ = std::move(other.list_); @@ -935,7 +946,7 @@ copy_assign( { reset(); max_ = other.max_; - alloc_ = other.alloc_; + this->member() = other.member(); copy_from(other); } @@ -960,7 +971,7 @@ swap(basic_multi_buffer& other, std::true_type) out_ == list_.end(); auto const at_end1 = other.out_ == other.list_.end(); - swap(alloc_, other.alloc_); + swap(this->member(), other.member()); swap(list_, other.list_); swap(out_, other.out_); if(at_end1) @@ -979,7 +990,7 @@ void basic_multi_buffer:: swap(basic_multi_buffer& other, std::false_type) { - BOOST_ASSERT(alloc_ == other.alloc_); + BOOST_ASSERT(this->member() == other.member()); using std::swap; auto const at_end0 = out_ == list_.end(); diff --git a/include/boost/beast/core/multi_buffer.hpp b/include/boost/beast/core/multi_buffer.hpp index 2c23ad3d..b83d650e 100644 --- a/include/boost/beast/core/multi_buffer.hpp +++ b/include/boost/beast/core/multi_buffer.hpp @@ -11,6 +11,8 @@ #define BOOST_BEAST_MULTI_BUFFER_HPP #include +#include +#include #include #include #include @@ -34,30 +36,28 @@ namespace beast { */ template class basic_multi_buffer -{ -public: -#if BOOST_BEAST_DOXYGEN - /// The type of allocator used. - using allocator_type = Allocator; -#else - using allocator_type = typename - std::allocator_traits:: - template rebind_alloc; +#if ! BOOST_BEAST_DOXYGEN + : private detail::empty_base_optimization< + typename detail::allocator_traits:: + template rebind_alloc> #endif +{ + using base_alloc_type = typename + detail::allocator_traits:: + template rebind_alloc; -private: // 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; - using alloc_traits = std::allocator_traits; + using alloc_traits = detail::allocator_traits; using list_type = typename boost::intrusive::make_list>::type; using iter = typename list_type::iterator; using const_iter = typename list_type::const_iterator; - using size_type = typename std::allocator_traits::size_type; + using size_type = typename alloc_traits::size_type; using const_buffer = boost::asio::const_buffer; using mutable_buffer = boost::asio::mutable_buffer; @@ -77,9 +77,11 @@ private: size_type in_pos_ = 0; // input offset in list_.front() size_type out_pos_ = 0; // output offset in *out_ size_type out_end_ = 0; // output end offset in list_.back() - allocator_type alloc_; // the allocator public: + /// The type of allocator used. + using allocator_type = Allocator; + #if BOOST_BEAST_DOXYGEN /// The type used to represent the input sequence as a list of buffers. using const_buffers_type = implementation_defined; @@ -215,7 +217,7 @@ public: allocator_type get_allocator() const { - return alloc_; + return this->member(); } /// Returns the size of the input sequence. @@ -274,9 +276,6 @@ private: template friend class basic_multi_buffer; - void - delete_element(element& e); - void delete_list(); diff --git a/include/boost/beast/http/fields.hpp b/include/boost/beast/http/fields.hpp index 927ec049..e4a1d2a3 100644 --- a/include/boost/beast/http/fields.hpp +++ b/include/boost/beast/http/fields.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -259,9 +260,7 @@ public: allocator_type get_allocator() const { - return typename std::allocator_traits< - Allocator>::template rebind_alloc< - value_type>(alloc_); + return alloc_; } //-------------------------------------------------------------------------- @@ -675,15 +674,15 @@ private: template friend class basic_fields; - using alloc_type = typename - std::allocator_traits:: + using base_alloc_type = typename + beast::detail::allocator_traits:: template rebind_alloc; using alloc_traits = - std::allocator_traits; + beast::detail::allocator_traits; - using size_type = - typename std::allocator_traits::size_type; + using size_type = typename + beast::detail::allocator_traits::size_type; value_type& new_element(field name, @@ -730,7 +729,7 @@ private: void swap(basic_fields& other, std::false_type); - alloc_type alloc_; + base_alloc_type alloc_; set_t set_; list_t list_; string_view method_; diff --git a/include/boost/beast/http/impl/fields.ipp b/include/boost/beast/http/impl/fields.ipp index f28b19e4..13b70e43 100644 --- a/include/boost/beast/http/impl/fields.ipp +++ b/include/boost/beast/http/impl/fields.ipp @@ -432,8 +432,8 @@ operator=(basic_fields&& other) -> { if(this == &other) return *this; - move_assign(other, typename alloc_traits:: - propagate_on_container_move_assignment{}); + move_assign(other, std::integral_constant{}); return *this; } @@ -443,8 +443,8 @@ basic_fields:: operator=(basic_fields const& other) -> basic_fields& { - copy_assign(other, typename alloc_traits:: - propagate_on_container_copy_assignment{}); + copy_assign(other, std::integral_constant{}); return *this; } @@ -645,8 +645,8 @@ void basic_fields:: swap(basic_fields& other) { - swap(other, typename alloc_traits:: - propagate_on_container_swap{}); + swap(other, std::integral_constant{}); } template @@ -1009,7 +1009,7 @@ set_chunked_impl(bool value) std::string s; #else using rebind_type = - typename std::allocator_traits< + typename beast::detail::allocator_traits< Allocator>::template rebind_alloc; std::basic_string< char, @@ -1046,7 +1046,7 @@ set_chunked_impl(bool value) std::string s; #else using rebind_type = - typename std::allocator_traits< + typename beast::detail::allocator_traits< Allocator>::template rebind_alloc; std::basic_string< char, @@ -1103,7 +1103,7 @@ set_keep_alive_impl( std::string s; #else using rebind_type = - typename std::allocator_traits< + typename beast::detail::allocator_traits< Allocator>::template rebind_alloc; std::basic_string< char, @@ -1199,7 +1199,7 @@ realloc_string(string_view& dest, string_view s) { if(dest.empty() && s.empty()) return; - auto a = typename std::allocator_traits< + auto a = typename beast::detail::allocator_traits< Allocator>::template rebind_alloc< char>(alloc_); if(! dest.empty()) @@ -1227,7 +1227,7 @@ realloc_target( // the reader class. if(dest.empty() && s.empty()) return; - auto a = typename std::allocator_traits< + auto a = typename beast::detail::allocator_traits< Allocator>::template rebind_alloc< char>(alloc_); if(! dest.empty())