Alien-boost-mini
view release on metacpan or search on metacpan
include/boost/container/detail/adaptive_node_pool_impl.hpp view on Meta::CPAN
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2005-2013. 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)
//
// See http://www.boost.org/libs/container for documentation.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
#define BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
#ifndef BOOST_CONFIG_HPP
# include <boost/config.hpp>
#endif
#if defined(BOOST_HAS_PRAGMA_ONCE)
# pragma once
#endif
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
// container
#include <boost/container/container_fwd.hpp>
#include <boost/container/throw_exception.hpp>
// container/detail
#include <boost/container/detail/pool_common.hpp>
#include <boost/container/detail/iterator.hpp>
#include <boost/move/detail/iterator_to_raw_pointer.hpp>
#include <boost/container/detail/math_functions.hpp>
#include <boost/container/detail/mpl.hpp>
#include <boost/move/detail/to_raw_pointer.hpp>
#include <boost/container/detail/type_traits.hpp>
// intrusive
#include <boost/intrusive/pointer_traits.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/intrusive/slist.hpp>
// other
#include <boost/assert.hpp>
#include <boost/core/no_exceptions_support.hpp>
#include <cstddef>
namespace boost {
namespace container {
namespace adaptive_pool_flag {
static const unsigned int none = 0u;
static const unsigned int align_only = 1u << 0u;
static const unsigned int size_ordered = 1u << 1u;
static const unsigned int address_ordered = 1u << 2u;
} //namespace adaptive_pool_flag{
namespace dtl {
template<class size_type>
struct hdr_offset_holder_t
{
hdr_offset_holder_t(size_type offset = 0)
: hdr_offset(offset)
{}
size_type hdr_offset;
};
template<class SizeType, unsigned int Flags>
struct less_func;
template<class SizeType>
struct less_func<SizeType, adaptive_pool_flag::none>
{
static bool less(SizeType, SizeType, const void *, const void *)
{ return true; }
};
template<class SizeType>
struct less_func<SizeType, adaptive_pool_flag::size_ordered>
{
static bool less(SizeType ls, SizeType rs, const void *, const void *)
{ return ls < rs; }
};
template<class SizeType>
struct less_func<SizeType, adaptive_pool_flag::address_ordered>
include/boost/container/detail/adaptive_node_pool_impl.hpp view on Meta::CPAN
{
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
//Now check if we've reached the free nodes limit
//and check if we have free blocks. If so, deallocate as much
//as we can to stay below the limit
multiallocation_chain chain;
{
if(Flags & adaptive_pool_flag::size_ordered){
const_block_iterator it = m_block_container.cend();
--it;
size_type totally_free_blocks = m_totally_free_blocks;
for( ; totally_free_blocks > max_free_blocks; --totally_free_blocks){
BOOST_ASSERT(it->free_nodes.size() == real_num_node);
void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it), num_subblocks, real_block_alignment);
--it;
block_container_traits_t::erase_last(m_block_container);
chain.push_front(void_pointer(addr));
}
}
else{
const_block_iterator it = m_block_container.cend();
size_type totally_free_blocks = m_totally_free_blocks;
while(totally_free_blocks > max_free_blocks){
--it;
if(it->free_nodes.size() == real_num_node){
void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it), num_subblocks, real_block_alignment);
it = m_block_container.erase(it);
chain.push_front(void_pointer(addr));
--totally_free_blocks;
}
}
}
BOOST_ASSERT((m_totally_free_blocks - max_free_blocks) == chain.size());
m_totally_free_blocks = max_free_blocks;
}
this->mp_segment_mngr_base->deallocate_many(chain);
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
}
void priv_fill_chain_remaining_to_block
( multiallocation_chain &chain, size_type target_elem_in_chain, block_info_t &c_info
, char *mem_address, size_type max_node_in_mem
, const size_type real_node_size)
{
BOOST_ASSERT(chain.size() <= target_elem_in_chain);
//First add all possible nodes to the chain
const size_type left = target_elem_in_chain - chain.size();
const size_type add_to_chain = (max_node_in_mem < left) ? max_node_in_mem : left;
char *free_mem_address = static_cast<char *>(boost::movelib::to_raw_pointer
(chain.incorporate_after(chain.last(), void_pointer(mem_address), real_node_size, add_to_chain)));
//Now store remaining nodes in the free list
if(const size_type free = max_node_in_mem - add_to_chain){
free_nodes_t & free_nodes = c_info.free_nodes;
free_nodes.incorporate_after(free_nodes.last(), void_pointer(free_mem_address), real_node_size, free);
}
}
//!Allocates a several blocks of nodes. Can throw
void priv_append_from_new_blocks( size_type min_elements, 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
, AlignOnlyTrue)
{
(void)num_subblocks;
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 - PayloadPerAllocation;
const size_type target_elem_in_chain = chain.size() + min_elements;
for(size_type i = 0; i != n; ++i){
//We allocate a new NodeBlock and put it the last
//element of the tree
char *mem_address = static_cast<char*>
(mp_segment_mngr_base->allocate_aligned(real_block_size, real_block_alignment));
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);
throw_bad_alloc();
}
block_info_t &c_info = *new(mem_address)block_info_t();
mem_address += HdrSize;
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){
const bool is_full = free_nodes == real_num_node;
BOOST_ASSERT(free_nodes < real_num_node);
m_totally_free_blocks += static_cast<size_type>(is_full);
block_container_traits_t::insert_was_empty(m_block_container, c_info, is_full);
}
}
}
void priv_append_from_new_blocks( size_type min_elements, 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
, 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 target_elem_in_chain = chain.size() + min_elements;
for(size_type i = 0; i != n; ++i){
//We allocate a new NodeBlock and put it the last
//element of the tree
char *mem_address = static_cast<char*>
(mp_segment_mngr_base->allocate_aligned(real_block_size, real_block_alignment));
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);
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)block_info_t();
//Some structural checks
BOOST_ASSERT(static_cast<void*>(&static_cast<hdr_offset_holder&>(c_info).hdr_offset) ==
static_cast<void*>(&c_info)); (void)c_info;
for( size_type subblock = 0, maxsubblock = num_subblocks - 1
; subblock < maxsubblock
; ++subblock, mem_address += real_block_alignment){
//Initialize header offset mark
new(mem_address) 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);
}
this->priv_fill_chain_remaining_to_block
(chain, target_elem_in_chain, c_info, hdr_addr + HdrSize, hdr_subblock_elements, real_node_size);
m_totally_free_blocks += static_cast<size_type>(c_info.free_nodes.size() == real_num_node);
if (c_info.free_nodes.size())
m_block_container.push_front(c_info);
}
}
//!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)
{
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
//If there are no free nodes we allocate a new block
if(!m_block_container.empty()){
//We take the first free node the multiset can't be empty
free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
BOOST_ASSERT(!free_nodes.empty());
const size_type free_nodes_count = free_nodes.size();
void *first_node = boost::movelib::to_raw_pointer(free_nodes.pop_front());
if(free_nodes.empty()){
block_container_traits_t::erase_first(m_block_container);
}
m_totally_free_blocks -= static_cast<size_type>(free_nodes_count == real_num_node);
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
return first_node;
}
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());
void *node = boost::movelib::to_raw_pointer(chain.pop_front());
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
return node;
}
}
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)
{
size_type i = 0;
BOOST_TRY{
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
while(i != n){
//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());
BOOST_ASSERT(m_block_container.empty() || (++m_block_container.cbegin() == m_block_container.cend()));
BOOST_ASSERT(chain.size() == n);
break;
}
free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
const size_type free_nodes_count_before = free_nodes.size();
m_totally_free_blocks -= static_cast<size_type>(free_nodes_count_before == real_num_node);
const size_type num_left = n-i;
const size_type num_elems = (num_left < free_nodes_count_before) ? num_left : free_nodes_count_before;
typedef typename free_nodes_t::iterator free_nodes_iterator;
if(num_left < free_nodes_count_before){
const free_nodes_iterator it_bbeg(free_nodes.before_begin());
free_nodes_iterator it_bend(it_bbeg);
for(size_type j = 0; j != num_elems; ++j){
++it_bend;
}
free_nodes_iterator it_end = it_bend; ++it_end;
free_nodes_iterator it_beg = it_bbeg; ++it_beg;
free_nodes.erase_after(it_bbeg, it_end, num_elems);
chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
//chain.splice_after(chain.last(), free_nodes, it_bbeg, it_bend, num_elems);
BOOST_ASSERT(!free_nodes.empty());
}
else{
const free_nodes_iterator it_beg(free_nodes.begin()), it_bend(free_nodes.last());
free_nodes.clear();
chain.incorporate_after(chain.last(), &*it_beg, &*it_bend, num_elems);
block_container_traits_t::erase_first(m_block_container);
}
i += num_elems;
}
}
BOOST_CATCH(...){
this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
BOOST_RETHROW
}
BOOST_CATCH_END
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
}
//!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)
{
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);
const size_type prev_free_nodes = block_info.free_nodes.size();
BOOST_ASSERT(block_info.free_nodes.size() < real_num_node);
//We put the node at the beginning of the free node list
block_info.free_nodes.push_back(void_pointer(pElem));
//The loop reinserts all blocks except the last one
this->priv_reinsert_block(block_info, prev_free_nodes == 0, real_num_node);
this->priv_deallocate_free_blocks(max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
}
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)
{
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
//To take advantage of node locality, wait until two
//nodes belong to different blocks. Only then reinsert
//the block of the first node in the block tree.
//Cache of the previous block
block_info_t *prev_block_info = 0;
//If block was empty before this call, it's not already
//inserted in the block tree.
bool prev_block_was_empty = false;
typedef typename free_nodes_t::iterator free_nodes_iterator;
{
const free_nodes_iterator itbb(nodes.before_begin()), ite(nodes.end());
free_nodes_iterator itf(nodes.begin()), itbf(itbb);
size_type splice_node_count = size_type(-1);
while(itf != ite){
void *pElem = boost::movelib::to_raw_pointer(boost::movelib::iterator_to_raw_pointer(itf));
block_info_t &block_info = *this->priv_block_from_node(pElem, real_block_alignment);
BOOST_ASSERT(block_info.free_nodes.size() < real_num_node);
++splice_node_count;
//If block change is detected calculate the cached block position in the tree
if(&block_info != prev_block_info){
if(prev_block_info){ //Make sure we skip the initial "dummy" cache
free_nodes_iterator it(itbb); ++it;
nodes.erase_after(itbb, itf, splice_node_count);
prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*it, &*itbf, splice_node_count);
this->priv_reinsert_block(*prev_block_info, prev_block_was_empty, real_num_node);
splice_node_count = 0;
}
//Update cache with new data
prev_block_was_empty = block_info.free_nodes.empty();
prev_block_info = &block_info;
}
itbf = itf;
++itf;
}
}
if(prev_block_info){
//The loop reinserts all blocks except the last one
const free_nodes_iterator itfirst(nodes.begin()), itlast(nodes.last());
const size_type splice_node_count = nodes.size();
nodes.clear();
prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*itfirst, &*itlast, splice_node_count);
this->priv_reinsert_block(*prev_block_info, prev_block_was_empty, real_num_node);
this->priv_deallocate_free_blocks(max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
}
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
}
void priv_reinsert_block(block_info_t &prev_block_info, const bool prev_block_was_empty, const size_type real_num_node)
{
//Cache the free nodes from the block
const size_type this_block_free_nodes = prev_block_info.free_nodes.size();
const bool is_full = this_block_free_nodes == real_num_node;
//Update free block count
m_totally_free_blocks += static_cast<size_type>(is_full);
if(prev_block_was_empty){
block_container_traits_t::insert_was_empty(m_block_container, prev_block_info, is_full);
}
else{
block_container_traits_t::reinsert_was_used(m_block_container, prev_block_info, is_full);
}
}
block_info_t *priv_block_from_node(void *node, const size_type real_block_alignment, AlignOnlyFalse) const
{
hdr_offset_holder *hdr_off_holder =
reinterpret_cast<hdr_offset_holder*>((std::size_t)node & size_type(~(real_block_alignment - 1)));
BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (real_block_alignment - 1)));
BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (real_block_alignment - 1)));
block_info_t *block = reinterpret_cast<block_info_t *>
(reinterpret_cast<char*>(hdr_off_holder) + hdr_off_holder->hdr_offset);
BOOST_ASSERT(block->hdr_offset == 0);
return block;
}
block_info_t *priv_block_from_node(void *node, const size_type real_block_alignment, AlignOnlyTrue) const
{
return (block_info_t *)((std::size_t)node & std::size_t(~(real_block_alignment - 1)));
}
block_info_t *priv_block_from_node(void *node, const size_type real_block_alignment) const
{ return this->priv_block_from_node(node, real_block_alignment, IsAlignOnly()); }
//!Deallocates all used memory. Never throws
void priv_clear(const size_type num_subblocks, const size_type real_block_alignment, const size_type real_num_node)
{
#ifndef NDEBUG
block_iterator it = m_block_container.begin();
block_iterator itend = m_block_container.end();
size_type n_free_nodes = 0;
for(; it != itend; ++it){
//Check for memory leak
BOOST_ASSERT(it->free_nodes.size() == real_num_node);
++n_free_nodes;
}
BOOST_ASSERT(n_free_nodes == m_totally_free_blocks);
#endif
//Check for memory leaks
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
multiallocation_chain chain;
m_block_container.clear_and_dispose(block_destroyer(this, chain, num_subblocks, real_block_alignment, real_num_node));
this->mp_segment_mngr_base->deallocate_many(chain);
m_totally_free_blocks = 0;
this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
}
public:
private_adaptive_node_pool_impl_common(segment_manager_base_type *segment_mngr_base)
//General purpose allocator
: mp_segment_mngr_base(segment_mngr_base)
, m_block_container()
, m_totally_free_blocks(0)
{}
size_type num_free_nodes()
{
typedef typename block_container_t::const_iterator citerator;
size_type count = 0;
citerator it (m_block_container.begin()), itend(m_block_container.end());
for(; it != itend; ++it){
count += it->free_nodes.size();
}
return count;
}
void swap(private_adaptive_node_pool_impl_common &other)
{
std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
std::swap(m_totally_free_blocks, other.m_totally_free_blocks);
m_block_container.swap(other.m_block_container);
}
//!Returns the segment manager. Never throws
segment_manager_base_type* get_segment_manager_base()const
{ return boost::movelib::to_raw_pointer(mp_segment_mngr_base); }
};
template< class SizeType
, std::size_t HdrSize
, std::size_t PayloadPerAllocation
, std::size_t RealNodeSize
, std::size_t NodesPerBlock
, std::size_t HdrOffsetSize
, std::size_t OverheadPercent
, bool AlignOnly>
struct calculate_alignment_ct
{
static const std::size_t alignment = upper_power_of_2_ct<SizeType, HdrSize + RealNodeSize*NodesPerBlock>::value;
static const std::size_t num_subblocks = 0;
static const std::size_t real_num_node = (alignment - PayloadPerAllocation - HdrSize)/RealNodeSize;
};
template< class SizeType
, std::size_t HdrSize
, std::size_t PayloadPerAllocation
, std::size_t RealNodeSize
, std::size_t NodesPerBlock
, std::size_t HdrOffsetSize
, std::size_t OverheadPercent>
struct calculate_alignment_ct
< SizeType
, HdrSize
, PayloadPerAllocation
, RealNodeSize
, NodesPerBlock
, HdrOffsetSize
, OverheadPercent
, false>
{
typedef typename candidate_power_of_2_ct
< upper_power_of_2_ct<SizeType, HdrSize + PayloadPerAllocation + RealNodeSize>::value
, RealNodeSize
, PayloadPerAllocation
, NodesPerBlock
, HdrSize
, HdrOffsetSize
, OverheadPercent
>::type type;
static const std::size_t alignment = type::alignment;
static const std::size_t num_subblocks = type::num_subblocks;
static const std::size_t real_num_node = type::real_num_node;
};
/////////////////////////////////////////////
//
// private_adaptive_node_pool_impl_ct
//
/////////////////////////////////////////////
template< class SegmentManagerBase
, std::size_t MaxFreeBlocks
, std::size_t NodeSize
, std::size_t NodesPerBlock
, std::size_t OverheadPercent
, unsigned int Flags>
class private_adaptive_node_pool_impl_ct
: public private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags>
{
typedef private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags> base_t;
//Non-copyable
private_adaptive_node_pool_impl_ct();
private_adaptive_node_pool_impl_ct(const private_adaptive_node_pool_impl_ct &);
private_adaptive_node_pool_impl_ct &operator=(const private_adaptive_node_pool_impl_ct &);
public:
typedef typename base_t::void_pointer void_pointer;
typedef typename base_t::size_type size_type;
typedef typename base_t::multiallocation_chain multiallocation_chain;
typedef typename base_t::segment_manager_base_type segment_manager_base_type;
static const typename base_t::size_type PayloadPerAllocation = base_t::PayloadPerAllocation;
//align_only
static const bool AlignOnly = base_t::AlignOnly;
private:
static const size_type MaxAlign = base_t::MaxAlign;
static const size_type HdrSize = base_t::HdrSize;
static const size_type HdrOffsetSize = base_t::HdrOffsetSize;
static const size_type RealNodeSize = lcm_ct<NodeSize, alignment_of<void_pointer>::value>::value;
typedef calculate_alignment_ct
< size_type, HdrSize, PayloadPerAllocation
, RealNodeSize, NodesPerBlock, HdrOffsetSize, OverheadPercent, AlignOnly> data_t;
//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
static const size_type NumSubBlocks = data_t::num_subblocks;
static const size_type RealNumNode = data_t::real_num_node;
static const size_type RealBlockAlignment = data_t::alignment;
public:
//!Constructor from a segment manager. Never throws
private_adaptive_node_pool_impl_ct(typename base_t::segment_manager_base_type *segment_mngr_base)
//General purpose allocator
: base_t(segment_mngr_base)
{}
//!Destructor. Deallocates all allocated blocks. Never throws
~private_adaptive_node_pool_impl_ct()
{ this->priv_clear(NumSubBlocks, data_t::alignment, RealNumNode); }
size_type get_real_num_node() const
{ return RealNumNode; }
//!Allocates array of count elements. Can throw
void *allocate_node()
{
return this->priv_allocate_node
(MaxFreeBlocks, data_t::alignment, RealNodeSize, RealNumNode, NumSubBlocks);
}
//!Allocates n nodes.
//!Can throw
void allocate_nodes(const size_type n, multiallocation_chain &chain)
{
this->priv_allocate_nodes
(n, chain, MaxFreeBlocks, data_t::alignment, RealNodeSize, RealNumNode, NumSubBlocks);
}
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *pElem)
{
this->priv_deallocate_node(pElem, MaxFreeBlocks, RealNumNode, NumSubBlocks, RealBlockAlignment);
}
//!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);
}
void deallocate_free_blocks()
{ this->priv_deallocate_free_blocks(0, RealNumNode, NumSubBlocks, data_t::alignment); }
//Deprecated, use deallocate_free_blocks
void deallocate_free_chunks()
{ this->priv_deallocate_free_blocks(0, RealNumNode, NumSubBlocks, data_t::alignment); }
};
/////////////////////////////////////////////
//
// private_adaptive_node_pool_impl_rt
//
/////////////////////////////////////////////
template<class SizeType>
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()
{}
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;
};
template<class SegmentManagerBase, unsigned int Flags>
class private_adaptive_node_pool_impl_rt
: private private_adaptive_node_pool_impl_rt_data<typename SegmentManagerBase::size_type>
, public private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags>
{
typedef private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags> impl_t;
typedef private_adaptive_node_pool_impl_rt_data<typename SegmentManagerBase::size_type> data_t;
//Non-copyable
private_adaptive_node_pool_impl_rt();
private_adaptive_node_pool_impl_rt(const private_adaptive_node_pool_impl_rt &);
private_adaptive_node_pool_impl_rt &operator=(const private_adaptive_node_pool_impl_rt &);
protected:
typedef typename impl_t::void_pointer void_pointer;
typedef typename impl_t::size_type size_type;
typedef typename impl_t::multiallocation_chain multiallocation_chain;
static const typename impl_t::size_type PayloadPerAllocation = impl_t::PayloadPerAllocation;
//Flags
//align_only
static const bool AlignOnly = impl_t::AlignOnly;
static const size_type HdrSize = impl_t::HdrSize;
static const size_type HdrOffsetSize = impl_t::HdrOffsetSize;
public:
//!Segment manager typedef
typedef SegmentManagerBase segment_manager_base_type;
//!Constructor from a segment manager. Never throws
private_adaptive_node_pool_impl_rt
( segment_manager_base_type *segment_mngr_base
, size_type node_size
, size_type nodes_per_block
, size_type max_free_blocks
, unsigned char overhead_percent
)
: data_t(max_free_blocks, lcm(node_size, size_type(alignment_of<void_pointer>::value)))
, impl_t(segment_mngr_base)
{
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;
}
else{
candidate_power_of_2_rt ( upper_power_of_2(HdrSize + PayloadPerAllocation + this->m_real_node_size)
, this->m_real_node_size
, PayloadPerAllocation
, nodes_per_block
, HdrSize
, HdrOffsetSize
, overhead_percent
, this->m_real_block_alignment
, this->m_num_subblocks
, this->m_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); }
size_type get_real_num_node() const
{ return this->m_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);
}
//!Allocates n nodes.
//!Can throw
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);
}
//!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);
}
//!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);
}
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); }
};
} //namespace dtl {
} //namespace container {
} //namespace boost {
#include <boost/container/detail/config_end.hpp>
#endif //#ifndef BOOST_CONTAINER_DETAIL_ADAPTIVE_NODE_POOL_IMPL_HPP
( run in 0.385 second using v1.01-cache-2.11-cpan-56fb94df46f )