|
Boost-Commit : |
From: igaztanaga_at_[hidden]
Date: 2008-01-22 11:49:23
Author: igaztanaga
Date: 2008-01-22 11:49:22 EST (Tue, 22 Jan 2008)
New Revision: 42911
URL: http://svn.boost.org/trac/boost/changeset/42911
Log:
Refactor some allocation code and fix instantiation problem in 64 bit platforms
Text files modified:
trunk/boost/interprocess/allocators/allocator.hpp | 9 +-
trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp | 156 +++++++++++++++++++++------------------
trunk/boost/interprocess/allocators/detail/node_pool.hpp | 53 +++++-------
trunk/boost/interprocess/detail/utilities.hpp | 48 ++++++++++++
trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp | 96 +++++++----------------
trunk/libs/interprocess/test/memory_algorithm_test.cpp | 8 +
6 files changed, 196 insertions(+), 174 deletions(-)
Modified: trunk/boost/interprocess/allocators/allocator.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/allocator.hpp (original)
+++ trunk/boost/interprocess/allocators/allocator.hpp 2008-01-22 11:49:22 EST (Tue, 22 Jan 2008)
@@ -101,10 +101,11 @@
typedef transform_iterator
< typename SegmentManager::
multiallocation_iterator
- , detail::cast_functor <T> > multiallocation_iterator;
- typedef typename SegmentManager::
- multiallocation_chain multiallocation_chain;
-
+ , detail::cast_functor <T> > multiallocation_iterator;
+ typedef detail::multiallocation_chain_adaptor
+ <typename SegmentManager::
+ multiallocation_chain
+ , T> multiallocation_chain;
/// @endcond
//!Obtains an allocator that allocates
Modified: trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp (original)
+++ trunk/boost/interprocess/allocators/detail/adaptive_node_pool.hpp 2008-01-22 11:49:22 EST (Tue, 22 Jan 2008)
@@ -186,39 +186,11 @@
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *pElem)
{
- priv_invariants();
- chunk_info_t *chunk_info = priv_chunk_from_node(pElem);
- assert(chunk_info->free_nodes.size() < m_real_num_node);
- //We put the node at the beginning of the free node list
- node_t * to_deallocate = static_cast<node_t*>(pElem);
- chunk_info->free_nodes.push_front(*to_deallocate);
-
- chunk_iterator this_chunk(chunk_multiset_t::s_iterator_to(*chunk_info));
- chunk_iterator next_chunk(this_chunk);
- ++next_chunk;
-
- //Cache the free nodes from the chunk
- std::size_t this_chunk_free_nodes = this_chunk->free_nodes.size();
-
- if(this_chunk_free_nodes == 1){
- m_chunk_multiset.insert(m_chunk_multiset.begin(), *chunk_info);
- }
- else{
- chunk_iterator next_chunk(this_chunk);
- ++next_chunk;
- if(next_chunk != m_chunk_multiset.end()){
- std::size_t next_free_nodes = next_chunk->free_nodes.size();
- if(this_chunk_free_nodes > next_free_nodes){
- //Now move the chunk to the new position
- m_chunk_multiset.erase(this_chunk);
- m_chunk_multiset.insert(*chunk_info);
- }
- }
- }
+ this->priv_reinsert_nodes_in_chunk
+ (multiallocation_iterator::create_simple_range(pElem));
//Update free chunk count
- if(this_chunk_free_nodes == m_real_num_node){
- ++m_totally_free_chunks;
- priv_deallocate_free_chunks(m_max_free_chunks);
+ if(m_totally_free_chunks > m_max_free_chunks){
+ this->priv_deallocate_free_chunks(m_max_free_chunks);
}
priv_invariants();
}
@@ -239,8 +211,8 @@
}
}
catch(...){
- priv_deallocate_nodes(nodes, nodes.size());
- priv_deallocate_free_chunks(m_max_free_chunks);
+ this->deallocate_nodes(nodes, nodes.size());
+ this->priv_deallocate_free_chunks(m_max_free_chunks);
throw;
}
//remove me
@@ -259,25 +231,31 @@
//!Deallocates a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes)
- { priv_deallocate_nodes(nodes, nodes.size()); }
+ {
+ this->deallocate_nodes(nodes.get_it());
+ nodes.reset();
+ }
//!Deallocates the first n nodes of a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes, std::size_t n)
- { priv_deallocate_nodes(nodes, n); }
+ {
+ assert(nodes.size() >= n);
+ for(std::size_t i = 0; i < n; ++i){
+ this->deallocate_node(nodes.pop_front());
+ }
+ }
//!Deallocates the nodes pointed by the multiallocation iterator. Never throws
void deallocate_nodes(multiallocation_iterator it)
{
- multiallocation_iterator itend;
- while(it != itend){
- void *addr = &*it;
- ++it;
- deallocate_node(addr);
+ this->priv_reinsert_nodes_in_chunk(it);
+ if(m_totally_free_chunks > m_max_free_chunks){
+ this->priv_deallocate_free_chunks(m_max_free_chunks);
}
}
void deallocate_free_chunks()
- { priv_deallocate_free_chunks(0); }
+ { this->priv_deallocate_free_chunks(0); }
std::size_t num_free_nodes()
{
@@ -302,6 +280,71 @@
}
private:
+ void priv_deallocate_free_chunks(std::size_t max_free_chunks)
+ {
+ priv_invariants();
+ //Now check if we've reached the free nodes limit
+ //and check if we have free chunks. If so, deallocate as much
+ //as we can to stay below the limit
+ for( chunk_iterator itend = m_chunk_multiset.end()
+ ; m_totally_free_chunks > max_free_chunks
+ ; --m_totally_free_chunks
+ ){
+ assert(!m_chunk_multiset.empty());
+ chunk_iterator it = itend;
+ --it;
+ std::size_t num_nodes = it->free_nodes.size();
+ assert(num_nodes == m_real_num_node);
+ (void)num_nodes;
+ m_chunk_multiset.erase_and_dispose
+ (it, chunk_destroyer(this));
+ }
+ }
+
+ void priv_reinsert_nodes_in_chunk(multiallocation_iterator it)
+ {
+ multiallocation_iterator itend;
+ chunk_iterator chunk_it(m_chunk_multiset.end());
+ while(it != itend){
+ void *pElem = &*it;
+ ++it;
+ priv_invariants();
+ chunk_info_t *chunk_info = this->priv_chunk_from_node(pElem);
+ assert(chunk_info->free_nodes.size() < m_real_num_node);
+ //We put the node at the beginning of the free node list
+ node_t * to_deallocate = static_cast<node_t*>(pElem);
+ chunk_info->free_nodes.push_front(*to_deallocate);
+
+ chunk_iterator this_chunk(chunk_multiset_t::s_iterator_to(*chunk_info));
+ chunk_iterator next_chunk(this_chunk);
+ ++next_chunk;
+
+ //Cache the free nodes from the chunk
+ std::size_t this_chunk_free_nodes = this_chunk->free_nodes.size();
+
+ if(this_chunk_free_nodes == 1){
+ m_chunk_multiset.insert(m_chunk_multiset.begin(), *chunk_info);
+ }
+ else{
+ chunk_iterator next_chunk(this_chunk);
+ ++next_chunk;
+ if(next_chunk != chunk_it){
+ std::size_t next_free_nodes = next_chunk->free_nodes.size();
+ if(this_chunk_free_nodes > next_free_nodes){
+ //Now move the chunk to the new position
+ m_chunk_multiset.erase(this_chunk);
+ m_chunk_multiset.insert(*chunk_info);
+ }
+ }
+ }
+ //Update free chunk count
+ if(this_chunk_free_nodes == m_real_num_node){
+ ++m_totally_free_chunks;
+ }
+ priv_invariants();
+ }
+ }
+
node_t *priv_take_first_node()
{
assert(m_chunk_multiset.begin() != m_chunk_multiset.end());
@@ -321,14 +364,6 @@
return first_node;
}
- void priv_deallocate_nodes(multiallocation_chain &nodes, const std::size_t num)
- {
- assert(nodes.size() >= num);
- for(std::size_t i = 0; i < num; ++i){
- deallocate_node(nodes.pop_front());
- }
- }
-
class chunk_destroyer;
friend class chunk_destroyer;
@@ -451,27 +486,6 @@
return hdr_off_holder;
}
- void priv_deallocate_free_chunks(std::size_t max_free_chunks)
- {
- priv_invariants();
- //Now check if we've reached the free nodes limit
- //and check if we have free chunks. If so, deallocate as much
- //as we can to stay below the limit
- for( chunk_iterator itend = m_chunk_multiset.end()
- ; m_totally_free_chunks > max_free_chunks
- ; --m_totally_free_chunks
- ){
- assert(!m_chunk_multiset.empty());
- chunk_iterator it = itend;
- --it;
- std::size_t num_nodes = it->free_nodes.size();
- assert(num_nodes == m_real_num_node);
- (void)num_nodes;
- m_chunk_multiset.erase_and_dispose
- (it, chunk_destroyer(this));
- }
- }
-
//!Allocates a several chunks of nodes. Can throw boost::interprocess::bad_alloc
void priv_alloc_chunk(std::size_t n)
{
Modified: trunk/boost/interprocess/allocators/detail/node_pool.hpp
==============================================================================
--- trunk/boost/interprocess/allocators/detail/node_pool.hpp (original)
+++ trunk/boost/interprocess/allocators/detail/node_pool.hpp 2008-01-22 11:49:22 EST (Tue, 22 Jan 2008)
@@ -91,11 +91,26 @@
//!Allocates array of count elements. Can throw boost::interprocess::bad_alloc
void *allocate_node()
- { return priv_alloc_node(); }
+ {
+ //If there are no free nodes we allocate a new block
+ if (m_freelist.empty())
+ priv_alloc_chunk();
+ //We take the first free node
+ node_t *n = (node_t*)&m_freelist.front();
+ m_freelist.pop_front();
+ ++m_allocated;
+ return n;
+ }
//!Deallocates an array pointed by ptr. Never throws
void deallocate_node(void *ptr)
- { priv_dealloc_node(ptr); }
+ {
+ //We put the node at the beginning of the free node list
+ node_t * to_deallocate = static_cast<node_t*>(ptr);
+ m_freelist.push_front(*to_deallocate);
+ assert(m_allocated>0);
+ --m_allocated;
+ }
//!Allocates a singly linked list of n nodes ending in null pointer and pushes them in the chain.
//!can throw boost::interprocess::bad_alloc
@@ -104,7 +119,7 @@
std::size_t i = 0;
try{
for(; i < n; ++i){
- nodes.push_front(priv_alloc_node());
+ nodes.push_front(this->allocate_node());
}
}
catch(...){
@@ -121,7 +136,7 @@
std::size_t i = 0;
try{
for(; i < n; ++i){
- nodes.push_front(priv_alloc_node());
+ nodes.push_front(this->allocate_node());
}
}
catch(...){
@@ -133,7 +148,10 @@
//!Deallocates a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes)
- { this->deallocate_nodes(nodes.get_it()); }
+ {
+ this->deallocate_nodes(nodes.get_it());
+ nodes.reset();
+ }
//!Deallocates the first n nodes of a linked list of nodes. Never throws
void deallocate_nodes(multiallocation_chain &nodes, std::size_t num)
@@ -287,31 +305,6 @@
const char * end_;
};
- //!Allocates one node, using single segregated storage algorithm.
- //!Never throws
- node_t *priv_alloc_node()
- {
- //If there are no free nodes we allocate a new block
- if (m_freelist.empty())
- priv_alloc_chunk();
- //We take the first free node
- node_t *n = (node_t*)&m_freelist.front();
- m_freelist.pop_front();
- ++m_allocated;
- return n;
- }
-
- //!Deallocates one node, using single segregated storage algorithm.
- //!Never throws
- void priv_dealloc_node(void *pElem)
- {
- //We put the node at the beginning of the free node list
- node_t * to_deallocate = static_cast<node_t*>(pElem);
- m_freelist.push_front(*to_deallocate);
- assert(m_allocated>0);
- --m_allocated;
- }
-
//!Allocates a chunk of nodes. Can throw boost::interprocess::bad_alloc
void priv_alloc_chunk()
{
Modified: trunk/boost/interprocess/detail/utilities.hpp
==============================================================================
--- trunk/boost/interprocess/detail/utilities.hpp (original)
+++ trunk/boost/interprocess/detail/utilities.hpp 2008-01-22 11:49:22 EST (Tue, 22 Jan 2008)
@@ -26,7 +26,7 @@
#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/interprocess/detail/min_max.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
-#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/iterators.hpp>
#include <boost/interprocess/detail/version_type.hpp>
#include <utility>
#include <algorithm>
@@ -678,6 +678,52 @@
{ return *static_cast<T*>(static_cast<void*>(&ptr)); }
};
+template<class MultiallocChain, class T>
+class multiallocation_chain_adaptor
+{
+ private:
+ MultiallocChain chain_;
+
+ multiallocation_chain_adaptor
+ (const multiallocation_chain_adaptor &);
+ multiallocation_chain_adaptor &operator=
+ (const multiallocation_chain_adaptor &);
+
+ public:
+ typedef transform_iterator
+ < typename MultiallocChain::
+ multiallocation_iterator
+ , detail::cast_functor <T> > multiallocation_iterator;
+
+ multiallocation_chain_adaptor()
+ : chain_()
+ {}
+
+ void push_back(T *mem)
+ { chain_.push_back(mem); }
+
+ void push_front(T *mem)
+ { chain_.push_front(mem); }
+
+ void swap(multiallocation_chain_adaptor &other_chain)
+ { chain_.swap(other_chain.chain_); }
+
+ void splice_back(multiallocation_chain_adaptor &other_chain)
+ { chain_.splice_back(other_chain.chain_); }
+
+ T *pop_front()
+ { return static_cast<T*>(chain_.pop_front()); }
+
+ bool empty() const
+ { return chain_.empty(); }
+
+ multiallocation_iterator get_it() const
+ { return multiallocation_iterator(chain_.get_it()); }
+
+ std::size_t size() const
+ { return chain_.size(); }
+};
+
} //namespace detail {
//!The pair is movable if any of its members is movable
Modified: trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp
==============================================================================
--- trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp (original)
+++ trunk/boost/interprocess/mem_algo/detail/mem_algo_common.hpp 2008-01-22 11:49:22 EST (Tue, 22 Jan 2008)
@@ -22,6 +22,7 @@
#include <boost/interprocess/allocators/allocation_type.hpp>
#include <boost/interprocess/detail/utilities.hpp>
#include <boost/interprocess/detail/type_traits.hpp>
+#include <boost/interprocess/detail/iterators.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
@@ -100,6 +101,16 @@
pointer operator->() const
{ return &(*(*this)); }
+ static basic_multiallocation_iterator create_simple_range(void *mem)
+ {
+ basic_multiallocation_iterator it;
+ typedef multi_allocation_next<VoidPointer> next_impl_t;
+ next_impl_t * tmp_mem = static_cast<next_impl_t*>(mem);
+ it = basic_multiallocation_iterator<VoidPointer>(tmp_mem);
+ tmp_mem->next_ = 0;
+ return it;
+ }
+
private:
multi_allocation_next<VoidPointer> next_alloc_;
};
@@ -122,6 +133,13 @@
: it_(0), last_mem_(0), num_mem_(0)
{}
+ void reset()
+ {
+ this->it_ = multiallocation_iterator();
+ this->last_mem_ = 0;
+ this->num_mem_ = 0;
+ }
+
void push_back(void *mem)
{
typedef multi_allocation_next<VoidPointer> next_impl_t;
@@ -138,35 +156,21 @@
++num_mem_;
}
- void push_back(multiallocation_iterator it, std::size_t n)
+ void push_front(void *mem)
{
typedef multi_allocation_next<VoidPointer> next_impl_t;
- next_impl_t * tmp_mem = (next_impl_t*)(&*it);
-
- if(!this->last_mem_){
- this->it_ = it;
- }
- else{
- static_cast<next_impl_t*>(detail::get_pointer(this->last_mem_))->next_ = tmp_mem;
- }
- tmp_mem->next_ = 0;
- this->last_mem_ = tmp_mem;
+ next_impl_t * tmp_mem = static_cast<next_impl_t*>(mem);
++num_mem_;
- }
- void push_front(void *mem)
- {
- typedef multi_allocation_next<VoidPointer> next_impl_t;
-
if(!this->last_mem_){
- push_back(mem);
+ this->it_ = basic_multiallocation_iterator<VoidPointer>(tmp_mem);
+ tmp_mem->next_ = 0;
+ this->last_mem_ = tmp_mem;
}
else{
- next_impl_t * tmp_mem = static_cast<next_impl_t*>(mem);
next_impl_t * old_first = (next_impl_t*)(&*this->it_);
- static_cast<next_impl_t*>(mem)->next_ = old_first;
+ tmp_mem->next_ = old_first;
this->it_ = basic_multiallocation_iterator<VoidPointer>(tmp_mem);
- ++num_mem_;
}
}
@@ -186,14 +190,15 @@
if(end_it == other_it){
return;
}
- else if(end_it == other_it){
+ else if(end_it == this_it){
this->swap(other_chain);
}
-
- static_cast<next_impl_t*>(detail::get_pointer(this->last_mem_))->next_
- = (next_impl_t*)&*this->it_;
- this->last_mem_ = other_chain.last_mem_;
- this->num_mem_ += other_chain.num_mem_;
+ else{
+ static_cast<next_impl_t*>(detail::get_pointer(this->last_mem_))->next_
+ = (next_impl_t*)&*other_chain.it_;
+ this->last_mem_ = other_chain.last_mem_;
+ this->num_mem_ += other_chain.num_mem_;
+ }
}
void *pop_front()
@@ -226,45 +231,6 @@
{ return num_mem_; }
};
-template<class Allocator>
-class allocator_multiallocation_chain
-{
- typedef typename detail::
- pointer_to_other<typename Allocator::pointer, void>::type
- void_ptr;
-
- typedef typename Allocator::multiallocation_iterator multiallocation_iterator;
- basic_multiallocation_chain<void_ptr> chain_;
-
- public:
-
- allocator_multiallocation_chain()
- : chain_()
- {}
-
- void push_back(void *mem)
- { chain_.push_back(mem); }
-
- multiallocation_iterator get_it() const
- { return multiallocation_iterator(chain_.get_it()); }
-};
-
-
-#define BOOST_MULTIALLOC_IT_CHAIN_INIT(IT_CHAIN) ((IT_CHAIN).it.next = 0, (IT_CHAIN).last_mem = 0)
-#define BOOST_MULTIALLOC_IT_CHAIN_ADD(IT_CHAIN, MEM)\
- do{\
- multialloc_it_t *____tmp_mem____ = (multialloc_it_t*)(MEM);\
- if(!IT_CHAIN.last_mem){\
- (IT_CHAIN).it.next = ____tmp_mem____;\
- }else{\
- ((multialloc_it_t*)(IT_CHAIN.last_mem))->next = ____tmp_mem____;\
- }\
- ____tmp_mem____->next = 0;\
- IT_CHAIN.last_mem = ____tmp_mem____;\
- }while(0)
-
-#define BOOST_MULTIALLOC_IT_CHAIN_IT(IT_CHAIN) ((IT_CHAIN).it)
-
//!This class implements several allocation functions shared by different algorithms
//!(aligned allocation, multiple allocation...).
Modified: trunk/libs/interprocess/test/memory_algorithm_test.cpp
==============================================================================
--- trunk/libs/interprocess/test/memory_algorithm_test.cpp (original)
+++ trunk/libs/interprocess/test/memory_algorithm_test.cpp 2008-01-22 11:49:22 EST (Tue, 22 Jan 2008)
@@ -14,6 +14,7 @@
#include <boost/interprocess/mem_algo/rbtree_best_fit.hpp>
#include <boost/interprocess/indexes/null_index.hpp>
#include <boost/interprocess/sync/mutex_family.hpp>
+#include <boost/interprocess/detail/type_traits.hpp>
#include "memory_algorithm_test_template.hpp"
#include <iostream>
#include <string>
@@ -67,16 +68,17 @@
int main ()
{
+ const std::size_t void_ptr_align = detail::alignment_of<void*>::value;
if(test_simple_seq_fit()){
return 1;
}
- if(test_rbtree_best_fit<4>()){
+ if(test_rbtree_best_fit<void_ptr_align>()){
return 1;
}
- if(test_rbtree_best_fit<8>()){
+ if(test_rbtree_best_fit<2*void_ptr_align>()){
return 1;
}
- if(test_rbtree_best_fit<16>()){
+ if(test_rbtree_best_fit<4*void_ptr_align>()){
return 1;
}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk