Boost logo

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