From 120d663949a0818bce0d9e1087c496109cc977c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ion=20Gazta=C3=B1aga?= Date: Sun, 18 Jan 2026 16:15:01 +0100 Subject: [PATCH] Make node pool based allocators support overaligned types. To avoid breaking ABI, pack overalignment value in spare bits on existing fields. Probably in the future we want to break ABI to simplify the maintenance. --- include/boost/container/adaptive_pool.hpp | 24 +- .../container/detail/adaptive_node_pool.hpp | 8 +- .../detail/adaptive_node_pool_impl.hpp | 255 +++++++++++++----- .../boost/container/detail/node_pool_impl.hpp | 8 +- 4 files changed, 199 insertions(+), 96 deletions(-) diff --git a/include/boost/container/adaptive_pool.hpp b/include/boost/container/adaptive_pool.hpp index f1f6119..950df51 100644 --- a/include/boost/container/adaptive_pool.hpp +++ b/include/boost/container/adaptive_pool.hpp @@ -354,30 +354,11 @@ class adaptive_pool } }; - - - - - - - - - - - - - - - - - - - template < class T , std::size_t NodesPerBlock = ADP_nodes_per_block , std::size_t MaxFreeBlocks = ADP_max_free_blocks , std::size_t OverheadPercent = ADP_overhead_percent - , unsigned Version = 2 + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I unsigned Version = 2) > class private_adaptive_pool { @@ -398,7 +379,8 @@ class private_adaptive_pool BOOST_CONTAINER_DOCIGN(BOOST_CONTAINER_STATIC_ASSERT((Version <=2))); typedef dtl::private_adaptive_node_pool - pool_t; + < sizeof(T), NodesPerBlock, MaxFreeBlocks + , OverheadPercent, dtl::alignment_of::value> pool_t; pool_t m_pool; public: diff --git a/include/boost/container/detail/adaptive_node_pool.hpp b/include/boost/container/detail/adaptive_node_pool.hpp index 816b95d..5cd1831 100644 --- a/include/boost/container/detail/adaptive_node_pool.hpp +++ b/include/boost/container/detail/adaptive_node_pool.hpp @@ -47,6 +47,7 @@ template< std::size_t NodeSize , std::size_t NodesPerBlock , std::size_t MaxFreeBlocks , std::size_t OverheadPercent + , std::size_t NodeAlign > class private_adaptive_node_pool : public private_adaptive_node_pool_impl_ct @@ -55,6 +56,7 @@ class private_adaptive_node_pool , NodeSize , NodesPerBlock , OverheadPercent + , NodeAlign , unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only | ::boost::container::adaptive_pool_flag::size_ordered | ::boost::container::adaptive_pool_flag::address_ordered @@ -66,6 +68,7 @@ class private_adaptive_node_pool , NodeSize , NodesPerBlock , OverheadPercent + , NodeAlign , unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only | ::boost::container::adaptive_pool_flag::size_ordered | ::boost::container::adaptive_pool_flag::address_ordered @@ -92,14 +95,15 @@ template< std::size_t NodeSize , std::size_t NodesPerBlock , std::size_t MaxFreeBlocks , std::size_t OverheadPercent + , std::size_t NodeAlign = 0 > class shared_adaptive_node_pool : public private_adaptive_node_pool - + { private: typedef private_adaptive_node_pool - private_node_allocator_t; + private_node_allocator_t; public: typedef typename private_node_allocator_t::multiallocation_chain multiallocation_chain; diff --git a/include/boost/container/detail/adaptive_node_pool_impl.hpp b/include/boost/container/detail/adaptive_node_pool_impl.hpp index 119b5b6..e5e6a1d 100644 --- a/include/boost/container/detail/adaptive_node_pool_impl.hpp +++ b/include/boost/container/detail/adaptive_node_pool_impl.hpp @@ -35,6 +35,8 @@ #include #include #include +#include + // intrusive #include #include @@ -375,6 +377,7 @@ inline void candidate_power_of_2_rt ( std::size_t initial_alignment , std::size_t &num_subblocks , std::size_t &real_num_node) { + bool overhead_satisfied = false; std::size_t num_b_subblock = 0; std::size_t total_nodes = 0; @@ -453,9 +456,27 @@ class private_adaptive_node_pool_impl_common typedef typename adaptive_pool_types_t::hdr_offset_holder hdr_offset_holder; typedef private_adaptive_node_pool_impl_common this_type; - BOOST_STATIC_CONSTEXPR size_type MaxAlign = alignment_of::value; - BOOST_STATIC_CONSTEXPR size_type HdrSize = ((sizeof(block_info_t)-1)/MaxAlign+1)*MaxAlign; - BOOST_STATIC_CONSTEXPR size_type HdrOffsetSize = ((sizeof(hdr_offset_holder)-1)/MaxAlign+1)*MaxAlign; + //BOOST_STATIC_CONSTEXPR size_type MaxAlign = alignment_of::value; + //BOOST_STATIC_CONSTEXPR size_type HdrSize = ((sizeof(block_info_t)-1)/MaxAlign+1)*MaxAlign; + //BOOST_STATIC_CONSTEXPR size_type HdrOffsetSize = ((sizeof(hdr_offset_holder)-1)/MaxAlign+1)*MaxAlign; + + static size_type get_hdr_size(size_type real_node_align) + { return ((sizeof(block_info_t)-1)/real_node_align+1)*real_node_align; } + + static size_type get_hdr_off_size(size_type real_node_align) + { return ((sizeof(hdr_offset_holder)-1)/real_node_align+1)*real_node_align; } + + template + struct get_hdr_size_ct + { + BOOST_STATIC_CONSTEXPR size_type value = ((sizeof(block_info_t) - 1)/RealNodeAlign + 1)*RealNodeAlign; + }; + + template + struct get_hdr_off_size_ct + { + BOOST_STATIC_CONSTEXPR size_type value = ((sizeof(hdr_offset_holder) - 1)/RealNodeAlign + 1)*RealNodeAlign; + }; segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager block_container_t m_block_container; //Intrusive block list @@ -644,6 +665,7 @@ class private_adaptive_node_pool_impl_common , const size_type max_free_blocks , const size_type real_block_alignment, const size_type real_node_size , const size_type real_num_node, const size_type num_subblocks + , const size_type real_node_align , AlignOnlyTrue) { (void)num_subblocks; @@ -660,11 +682,11 @@ class private_adaptive_node_pool_impl_common if(!mem_address){ //In case of error, free memory deallocating all nodes (the new ones allocated //in this function plus previously stored nodes in chain). - this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment); + this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment, real_node_align); throw_bad_alloc(); } - block_info_t &c_info = *new(mem_address, boost_container_new_t())block_info_t(); - mem_address += HdrSize; + block_info_t &c_info = *new(mem_address, boost_container_new_t()) block_info_t(); + mem_address += get_hdr_size(real_node_align); this->priv_fill_chain_remaining_to_block(chain, target_elem_in_chain, c_info, mem_address, real_num_node, real_node_size); const size_type free_nodes = c_info.free_nodes.size(); if(free_nodes){ @@ -680,15 +702,18 @@ class private_adaptive_node_pool_impl_common , const size_type max_free_blocks , const size_type real_block_alignment, const size_type real_node_size , const size_type real_num_node, const size_type num_subblocks + , const size_type real_node_align , AlignOnlyFalse) { BOOST_ASSERT(m_block_container.empty()); BOOST_ASSERT(min_elements > 0); const size_type n = (min_elements - 1)/real_num_node + 1; const size_type real_block_size = real_block_alignment*num_subblocks - PayloadPerAllocation; - const size_type elements_per_subblock_mid = (real_block_alignment - HdrOffsetSize)/real_node_size; - const size_type elements_per_subblock_end = (real_block_alignment - HdrOffsetSize - PayloadPerAllocation) / real_node_size; - const size_type hdr_subblock_elements = (real_block_alignment - HdrSize - PayloadPerAllocation)/real_node_size; + const size_type hdr_size = get_hdr_size(real_node_align); + const size_type hdr_off_size = get_hdr_off_size(real_node_align); + const size_type elements_per_subblock_mid = (real_block_alignment - hdr_off_size)/real_node_size; + const size_type elements_per_subblock_end = (real_block_alignment - hdr_off_size - PayloadPerAllocation) / real_node_size; + const size_type hdr_subblock_elements = (real_block_alignment - hdr_size - PayloadPerAllocation)/real_node_size; const size_type target_elem_in_chain = chain.size() + min_elements; for(size_type i = 0; i != n; ++i){ @@ -699,12 +724,12 @@ class private_adaptive_node_pool_impl_common if(!mem_address){ //In case of error, free memory deallocating all nodes (the new ones allocated //in this function plus previously stored nodes in chain). - this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment); + this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment, real_node_align); throw_bad_alloc(); } //First initialize header information on the last subblock char *hdr_addr = mem_address + real_block_alignment*(num_subblocks-1); - block_info_t &c_info = *new(hdr_addr, boost_container_new_t())block_info_t(); + block_info_t &c_info = *new(hdr_addr, boost_container_new_t()) block_info_t(); //Some structural checks BOOST_ASSERT(static_cast(&static_cast(c_info).hdr_offset) == static_cast(&c_info)); (void)c_info; @@ -715,10 +740,10 @@ class private_adaptive_node_pool_impl_common new(mem_address, boost_container_new_t()) hdr_offset_holder(size_type(hdr_addr - mem_address)); const size_type elements_per_subblock = (subblock != (maxsubblock - 1)) ? elements_per_subblock_mid : elements_per_subblock_end; this->priv_fill_chain_remaining_to_block - (chain, target_elem_in_chain, c_info, mem_address + HdrOffsetSize, elements_per_subblock, real_node_size); + (chain, target_elem_in_chain, c_info, mem_address + hdr_off_size, elements_per_subblock, real_node_size); } this->priv_fill_chain_remaining_to_block - (chain, target_elem_in_chain, c_info, hdr_addr + HdrSize, hdr_subblock_elements, real_node_size); + (chain, target_elem_in_chain, c_info, hdr_addr + hdr_size, hdr_subblock_elements, real_node_size); m_totally_free_blocks += static_cast(c_info.free_nodes.size() == real_num_node); if (c_info.free_nodes.size()) m_block_container.push_front(c_info); @@ -727,7 +752,7 @@ class private_adaptive_node_pool_impl_common //!Allocates array of count elements. Can throw void *priv_allocate_node( const size_type max_free_blocks, const size_type real_block_alignment, const size_type real_node_size - , const size_type real_num_node, const size_type num_subblocks) + , const size_type real_num_node, const size_type num_subblocks, const size_type real_node_align) { this->priv_invariants(real_num_node, num_subblocks, real_block_alignment); //If there are no free nodes we allocate a new block @@ -747,7 +772,7 @@ class private_adaptive_node_pool_impl_common else{ multiallocation_chain chain; this->priv_append_from_new_blocks - (1, chain, max_free_blocks, real_block_alignment, real_node_size, real_num_node, num_subblocks, IsAlignOnly()); + (1, chain, max_free_blocks, real_block_alignment, real_node_size, real_num_node, num_subblocks, real_node_align, IsAlignOnly()); void *node = boost::movelib::to_raw_pointer(chain.pop_front()); this->priv_invariants(real_num_node, num_subblocks, real_block_alignment); return node; @@ -756,7 +781,7 @@ class private_adaptive_node_pool_impl_common void priv_allocate_nodes( const size_type n, multiallocation_chain &chain , const size_type max_free_blocks, const size_type real_block_alignment, const size_type real_node_size - , const size_type real_num_node, const size_type num_subblocks) + , const size_type real_num_node, const size_type num_subblocks, const size_type real_node_align) { size_type i = 0; BOOST_CONTAINER_TRY{ @@ -765,7 +790,7 @@ class private_adaptive_node_pool_impl_common //If there are no free nodes we allocate all needed blocks if (m_block_container.empty()){ this->priv_append_from_new_blocks - (n - i, chain, max_free_blocks, real_block_alignment, real_node_size, real_num_node, num_subblocks, IsAlignOnly()); + (n - i, chain, max_free_blocks, real_block_alignment, real_node_size, real_num_node, num_subblocks, real_node_align, IsAlignOnly()); BOOST_ASSERT(m_block_container.empty() || (++m_block_container.cbegin() == m_block_container.cend())); BOOST_ASSERT(chain.size() == n); break; @@ -800,7 +825,7 @@ class private_adaptive_node_pool_impl_common } } BOOST_CONTAINER_CATCH(...){ - this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment); + this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment, real_node_align); this->priv_invariants(real_num_node, num_subblocks, real_block_alignment); BOOST_CONTAINER_RETHROW } @@ -811,7 +836,8 @@ class private_adaptive_node_pool_impl_common //!Deallocates an array pointed by ptr. Never throws void priv_deallocate_node( void *pElem , const size_type max_free_blocks, const size_type real_num_node - , const size_type num_subblocks, const size_type real_block_alignment) + , const size_type num_subblocks, const size_type real_block_alignment + , const size_type /*real_node_align*/) { this->priv_invariants(real_num_node, num_subblocks, real_block_alignment); block_info_t &block_info = *this->priv_block_from_node(pElem, real_block_alignment); @@ -829,7 +855,8 @@ class private_adaptive_node_pool_impl_common void priv_deallocate_nodes( multiallocation_chain &nodes , const size_type max_free_blocks, const size_type real_num_node - , const size_type num_subblocks, const size_type real_block_alignment) + , const size_type num_subblocks, const size_type real_block_alignment + , const size_type /*real_node_align*/) { this->priv_invariants(real_num_node, num_subblocks, real_block_alignment); //To take advantage of node locality, wait until two @@ -978,10 +1005,12 @@ template< class SizeType , std::size_t NodesPerBlock , std::size_t HdrOffsetSize , std::size_t OverheadPercent + , std::size_t NodeAlign , bool AlignOnly> struct calculate_alignment_ct { - BOOST_STATIC_CONSTEXPR std::size_t alignment = upper_power_of_2_ct::value; + BOOST_STATIC_CONSTEXPR std::size_t initial_alignment = upper_power_of_2_ct::value; + BOOST_STATIC_CONSTEXPR std::size_t alignment = NodeAlign > initial_alignment ? NodeAlign : initial_alignment; BOOST_STATIC_CONSTEXPR std::size_t num_subblocks = 0; BOOST_STATIC_CONSTEXPR std::size_t real_num_node = (alignment - PayloadPerAllocation - HdrSize)/RealNodeSize; }; @@ -992,7 +1021,9 @@ template< class SizeType , std::size_t RealNodeSize , std::size_t NodesPerBlock , std::size_t HdrOffsetSize - , std::size_t OverheadPercent> + , std::size_t OverheadPercent + , std::size_t NodeAlign + > struct calculate_alignment_ct < SizeType , HdrSize @@ -1001,10 +1032,14 @@ struct calculate_alignment_ct , NodesPerBlock , HdrOffsetSize , OverheadPercent + , NodeAlign , false> { + BOOST_STATIC_CONSTEXPR std::size_t proposed_alignment = upper_power_of_2_ct::value; + BOOST_STATIC_CONSTEXPR std::size_t initial_alignment = NodeAlign > proposed_alignment ? NodeAlign : proposed_alignment; + typedef typename candidate_power_of_2_ct - < upper_power_of_2_ct::value + < initial_alignment , RealNodeSize , PayloadPerAllocation , NodesPerBlock @@ -1029,6 +1064,7 @@ template< class SegmentManagerBase , std::size_t NodeSize , std::size_t NodesPerBlock , std::size_t OverheadPercent + , std::size_t InitialNodeAlign , unsigned int Flags> class private_adaptive_node_pool_impl_ct : public private_adaptive_node_pool_impl_common @@ -1052,15 +1088,17 @@ class private_adaptive_node_pool_impl_ct BOOST_STATIC_CONSTEXPR bool AlignOnly = base_t::AlignOnly; private: - BOOST_STATIC_CONSTEXPR size_type MaxAlign = base_t::MaxAlign; - BOOST_STATIC_CONSTEXPR size_type HdrSize = base_t::HdrSize; - BOOST_STATIC_CONSTEXPR size_type HdrOffsetSize = base_t::HdrOffsetSize; + BOOST_STATIC_CONSTEXPR size_type VoidPtrAlign = alignment_of::value; + BOOST_STATIC_CONSTEXPR size_type RealNodeAlign = InitialNodeAlign > VoidPtrAlign ? InitialNodeAlign : VoidPtrAlign; - BOOST_STATIC_CONSTEXPR size_type RealNodeSize = lcm_ct::value>::value; + BOOST_STATIC_CONSTEXPR size_type RealNodePtrAlign = lcm_ct ::value; + BOOST_STATIC_CONSTEXPR size_type RealNodeSize = lcm_ct< RealNodePtrAlign, RealNodeAlign>::value; + BOOST_STATIC_CONSTEXPR size_type HdrSize = base_t::template get_hdr_size_ct::value; + BOOST_STATIC_CONSTEXPR size_type HdrOffsetSize = base_t::template get_hdr_off_size_ct::value; typedef calculate_alignment_ct < size_type, HdrSize, PayloadPerAllocation - , RealNodeSize, NodesPerBlock, HdrOffsetSize, OverheadPercent, AlignOnly> data_t; + , RealNodeSize, NodesPerBlock, HdrOffsetSize, OverheadPercent, RealNodeAlign, AlignOnly> data_t; //Round the size to a power of two value. //This is the total memory size (including payload) that we want to @@ -1088,7 +1126,7 @@ class private_adaptive_node_pool_impl_ct void *allocate_node() { return this->priv_allocate_node - (MaxFreeBlocks, data_t::alignment, RealNodeSize, RealNumNode, NumSubBlocks); + (MaxFreeBlocks, data_t::alignment, RealNodeSize, RealNumNode, NumSubBlocks, RealNodeAlign); } //!Allocates n nodes. @@ -1096,19 +1134,19 @@ class private_adaptive_node_pool_impl_ct void allocate_nodes(const size_type n, multiallocation_chain &chain) { this->priv_allocate_nodes - (n, chain, MaxFreeBlocks, data_t::alignment, RealNodeSize, RealNumNode, NumSubBlocks); + (n, chain, MaxFreeBlocks, data_t::alignment, RealNodeSize, RealNumNode, NumSubBlocks, RealNodeAlign); } //!Deallocates an array pointed by ptr. Never throws void deallocate_node(void *pElem) { - this->priv_deallocate_node(pElem, MaxFreeBlocks, RealNumNode, NumSubBlocks, RealBlockAlignment); + this->priv_deallocate_node(pElem, MaxFreeBlocks, RealNumNode, NumSubBlocks, RealBlockAlignment, RealNodeAlign); } //!Deallocates a linked list of nodes. Never throws void deallocate_nodes(multiallocation_chain &nodes) { - this->priv_deallocate_nodes(nodes, MaxFreeBlocks, RealNumNode, NumSubBlocks, data_t::alignment); + this->priv_deallocate_nodes(nodes, MaxFreeBlocks, RealNumNode, NumSubBlocks, data_t::alignment, RealNodeAlign); } void deallocate_free_blocks() @@ -1129,20 +1167,76 @@ struct private_adaptive_node_pool_impl_rt_data { typedef SizeType size_type; - private_adaptive_node_pool_impl_rt_data(size_type max_free_blocks, size_type real_node_size) - : m_max_free_blocks(max_free_blocks), m_real_node_size(real_node_size) - , m_real_block_alignment(), m_num_subblocks(), m_real_num_node() + BOOST_STATIC_CONSTEXPR size_type node_align = alignment_of::value; + BOOST_STATIC_CONSTEXPR size_type node_align_bits + = boost::container::dtl::log2_pow2::value; + + typedef packed_3n_bits_ref packed_bits_t; + + private_adaptive_node_pool_impl_rt_data(size_type max_free_blocks) + : m_max_free_blocks(max_free_blocks) + , m_packed_low() + , m_real_block_alignment() + , m_packed_high1() + , m_packed_high2() {} - const size_type m_max_free_blocks; - const size_type m_real_node_size; - //Round the size to a power of two value. - //This is the total memory size (including payload) that we want to - //allocate from the general-purpose allocator - size_type m_real_block_alignment; - size_type m_num_subblocks; - //This is the real number of nodes per block - size_type m_real_num_node; + void set_node_alignment(size_type alignment) + { + const size_type aligned_multiplier = alignment/node_align; + const size_type aligned_shift = log2_ceil(aligned_multiplier); + return packed_bits().store(aligned_shift); + } + + size_type get_node_alignment() const + { return node_align << packed_bits().load(); } + + size_type get_max_free_blocks() const + { return m_max_free_blocks; } + + size_type get_real_block_alignment() const + { return m_real_block_alignment; } + + size_type get_real_node_size() const + { return packed_bits().low_unpacked(); } + + size_type get_num_subblocks() const + { return packed_bits().high1_unpacked(); } + + size_type get_real_num_node() const + { return packed_bits().high2_unpacked(); } + + void set_real_block_alignment(size_type v) + { m_real_block_alignment = v; } + + void set_real_node_size(size_type v) + { packed_bits().set_low_unpacked(v); } + + void set_num_subblocks(size_type v) + { packed_bits().set_high1_unpacked(v); } + + void set_real_num_node(size_type v) + { packed_bits().set_high2_unpacked(v); } + +private: + packed_bits_t packed_bits() + { + return packed_bits_t(m_packed_low, m_packed_high1, m_packed_high2); + } + + const packed_bits_t packed_bits() const + { + return packed_bits_t(const_cast(m_packed_low), + const_cast(m_packed_high1), + const_cast(m_packed_high2)); + } + + //Maintain info from original members before bit-packing, to avoid breaking ABI + const size_type m_max_free_blocks; //No changes + size_type m_packed_low; // stores "m_real_node_size" in low N bits + size_type m_real_block_alignment; //No changes + size_type m_packed_high1; // stores "m_num_subblocks"in high N bits + size_type m_packed_high2; // stores "m_real_num_node" in high N bits }; @@ -1171,8 +1265,11 @@ class private_adaptive_node_pool_impl_rt //align_only BOOST_STATIC_CONSTEXPR bool AlignOnly = impl_t::AlignOnly; - BOOST_STATIC_CONSTEXPR size_type HdrSize = impl_t::HdrSize; - BOOST_STATIC_CONSTEXPR size_type HdrOffsetSize = impl_t::HdrOffsetSize; + //BOOST_STATIC_CONSTEXPR size_type HdrSize = impl_t::HdrSize; + //BOOST_STATIC_CONSTEXPR size_type HdrOffsetSize = impl_t::HdrOffsetSize; + + using impl_t::get_hdr_size; + using impl_t::get_hdr_off_size; public: @@ -1186,40 +1283,59 @@ class private_adaptive_node_pool_impl_rt , size_type nodes_per_block , size_type max_free_blocks , unsigned char overhead_percent + , size_type node_align ) - : data_t(max_free_blocks, lcm(node_size, size_type(alignment_of::value))) + : data_t(max_free_blocks) , impl_t(segment_mngr_base) { + if (node_align < alignment_of::value) + node_align = alignment_of::value; + node_size = lcm(node_size, node_align); + this->data_t::set_real_node_size(node_size); + this->data_t::set_node_alignment(node_align); + + const size_type hdr_size = get_hdr_size(node_align); if(AlignOnly){ - this->m_real_block_alignment = upper_power_of_2(HdrSize + this->m_real_node_size*nodes_per_block); - this->m_real_num_node = (this->m_real_block_alignment - PayloadPerAllocation - HdrSize)/this->m_real_node_size; + this->data_t::set_real_block_alignment(upper_power_of_2(hdr_size + this->get_real_node_size() * nodes_per_block)); + this->data_t::set_real_num_node((this->get_real_block_alignment() - PayloadPerAllocation - hdr_size)/this->get_real_node_size()); } else{ - candidate_power_of_2_rt ( upper_power_of_2(HdrSize + PayloadPerAllocation + this->m_real_node_size) - , this->m_real_node_size + size_type real_block_alignment = 0; + size_type num_subblocks = 0; + size_type real_num_node = 0; + const size_type hdr_off_size = get_hdr_off_size(node_align); + size_type initial_alignment = upper_power_of_2(hdr_size + PayloadPerAllocation + this->get_real_node_size()); + if (initial_alignment < node_align) + initial_alignment = node_align; + candidate_power_of_2_rt ( initial_alignment + , this->get_real_node_size() , PayloadPerAllocation , nodes_per_block - , HdrSize - , HdrOffsetSize + , hdr_size + , hdr_off_size , overhead_percent - , this->m_real_block_alignment - , this->m_num_subblocks - , this->m_real_num_node); + , real_block_alignment + , num_subblocks + , real_num_node); + this->data_t::set_real_block_alignment(real_block_alignment); + this->data_t::set_num_subblocks(num_subblocks); + this->data_t::set_real_num_node(real_num_node); } } //!Destructor. Deallocates all allocated blocks. Never throws ~private_adaptive_node_pool_impl_rt() - { this->priv_clear(this->m_num_subblocks, this->m_real_block_alignment, this->m_real_num_node); } + { this->impl_t::priv_clear(this->get_num_subblocks(), this->get_real_block_alignment(), this->get_real_num_node()); } size_type get_real_num_node() const - { return this->m_real_num_node; } + { return data_t::get_real_num_node(); } //!Allocates array of count elements. Can throw void *allocate_node() { - return this->priv_allocate_node - (this->m_max_free_blocks, this->m_real_block_alignment, this->m_real_node_size, this->m_real_num_node, this->m_num_subblocks); + return this->impl_t::priv_allocate_node + ( this->get_max_free_blocks(), this->get_real_block_alignment() + , this->get_real_node_size(), this->get_real_num_node(), this->get_num_subblocks(), this->get_node_alignment()); } //!Allocates n nodes. @@ -1227,30 +1343,29 @@ class private_adaptive_node_pool_impl_rt void allocate_nodes(const size_type n, multiallocation_chain &chain) { - this->priv_allocate_nodes - (n, chain, this->m_max_free_blocks, this->m_real_block_alignment, this->m_real_node_size, this->m_real_num_node, this->m_num_subblocks); + this->impl_t::priv_allocate_nodes + ( n, chain, this->get_max_free_blocks(), this->get_real_block_alignment(), this->get_real_node_size() + , this->get_real_num_node(), this->get_num_subblocks(), this->get_node_alignment()); } //!Deallocates an array pointed by ptr. Never throws void deallocate_node(void *pElem) { - this->priv_deallocate_node(pElem, this->m_max_free_blocks, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment); + this->impl_t::priv_deallocate_node( pElem, this->get_max_free_blocks(), this->get_real_num_node() + , this->get_num_subblocks(), this->get_real_block_alignment(), this->get_node_alignment()); } //!Deallocates a linked list of nodes. Never throws void deallocate_nodes(multiallocation_chain &nodes) { - this->priv_deallocate_nodes(nodes, this->m_max_free_blocks, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment); + this->impl_t::priv_deallocate_nodes( nodes, this->get_max_free_blocks(), this->get_real_num_node() + , this->get_num_subblocks(), this->get_real_block_alignment(), this->get_node_alignment()); } void deallocate_free_blocks() - { this->priv_deallocate_free_blocks(0, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment); } - - //Deprecated, use deallocate_free_blocks - void deallocate_free_chunks() - { this->priv_deallocate_free_blocks(0, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment); } + { this->impl_t::priv_deallocate_free_blocks( 0, this->get_real_num_node(), this->get_num_subblocks() + , this->get_real_block_alignment()); } }; - } //namespace dtl { } //namespace container { } //namespace boost { diff --git a/include/boost/container/detail/node_pool_impl.hpp b/include/boost/container/detail/node_pool_impl.hpp index 39254f2..47e7e7d 100644 --- a/include/boost/container/detail/node_pool_impl.hpp +++ b/include/boost/container/detail/node_pool_impl.hpp @@ -171,10 +171,12 @@ public: size_type& raw_high2() { return m_high2; } size_type raw_high2() const { return m_high2; } + packed_3n_bits_ref(const packed_3n_bits_ref& v) + : m_low(v.m_low), m_high1(v.m_high1), m_high2(v.m_high2) + {} private: - // Non-copyable (references can't be reseated) - packed_3n_bits_ref(const packed_3n_bits_ref&); - packed_3n_bits_ref& operator=(const packed_3n_bits_ref&); + + //packed_3n_bits_ref& operator=(const packed_3n_bits_ref&); }; //This class uses packed_3n_bits_ref to store overalignment