Update of /cvsroot/boost/boost/boost/interprocess/allocators/detail
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv22035/allocators/detail

Modified Files:
        node_pool.hpp 
Log Message:
New Interprocess version

Index: node_pool.hpp
===================================================================
RCS file: 
/cvsroot/boost/boost/boost/interprocess/allocators/detail/node_pool.hpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- node_pool.hpp       23 Jun 2007 12:53:00 -0000      1.6
+++ node_pool.hpp       22 Jul 2007 14:05:59 -0000      1.7
@@ -24,9 +24,11 @@
 #include <boost/interprocess/exceptions.hpp>
 #include <boost/intrusive/slist.hpp>
 #include <boost/math/common_factor_ct.hpp>
+#include <boost/interprocess/detail/math_functions.hpp>
 #include <boost/interprocess/allocators/detail/node_tools.hpp>
 #include <cstddef>
 #include <functional>
+#include <algorithm>
 #include <assert.h>
 
 /*!\file
@@ -37,23 +39,17 @@
 namespace interprocess {
 namespace detail {
 
-//!Pooled shared memory allocator using single segregated storage. Includes
-//!a reference count but the class does not delete itself, this is  
-//!responsibility of user classes. Node size (NodeSize) and the number of
-//!nodes allocated per chunk (NumAlloc) are known at compile time
-template< class SegmentManager, std::size_t NodeSize, std::size_t NumAlloc >
-class private_node_pool
+template<class SegmentManagerBase>
+class private_node_pool_impl
 {
    //Non-copyable
-   private_node_pool();
-   private_node_pool(const private_node_pool &);
-   private_node_pool &operator=(const private_node_pool &);
-
-   typedef typename SegmentManager::void_pointer void_pointer;
-   typedef typename pointer_to_other<void_pointer, char>::type char_ptr_t;
+   private_node_pool_impl();
+   private_node_pool_impl(const private_node_pool_impl &);
+   private_node_pool_impl &operator=(const private_node_pool_impl &);
 
    //A node object will hold node_t when it's not allocated
    public:
+   typedef typename SegmentManagerBase::void_pointer           void_pointer;
    typedef typename node_slist<void_pointer>::slist_hook_t  slist_hook_t;
    typedef typename node_slist<void_pointer>::node_t        node_t;
    typedef typename node_slist<void_pointer>::node_slist_t  free_nodes_t;
@@ -62,43 +58,42 @@
    typedef boost::intrusive::slist
       <typename slist_hook_t::template value_traits<node_t>, false > 
chunkslist_t;
 
-   enum { RealNodeSize  = 
-            boost::math::static_lcm<NodeSize, sizeof(node_t)>::value };
-   enum { BlockSize     = 
-            detail::ct_rounded_size<RealNodeSize*NumAlloc, 
sizeof(node_t)>::value  };
-   enum { ChunkSize     = BlockSize + sizeof(node_t) };
-   enum { NumNode       = NumAlloc };
-
    public:
 
-   enum  {  nodes_per_chunk   = NumNode     };
-   enum  {  node_size         = NodeSize        };
-
    //!Segment manager typedef
-   typedef SegmentManager                 segment_manager;
+   typedef SegmentManagerBase segment_manager_base_type;
 
    //!Constructor from a segment manager. Never throws
-   private_node_pool(segment_manager *segment_mngr)
-   :  //General purpose allocator
-      mp_segment_mngr(segment_mngr),
+   private_node_pool_impl(segment_manager_base_type *segment_mngr_base, 
std::size_t node_size, std::size_t nodes_per_chunk)
+   :  m_node_size(node_size)
+   ,  m_nodes_per_chunk(nodes_per_chunk)
+   ,  m_real_node_size(detail::lcm(node_size, sizeof(node_t)))
+   ,  
m_block_size(detail::get_rounded_size(m_real_node_size*m_nodes_per_chunk, 
sizeof(node_t)))
+      //General purpose allocator
+   ,  mp_segment_mngr_base(segment_mngr_base)
+   ,  m_chunklist()
+   ,  m_freelist()
       //Debug node count
-      m_allocated(0)
+   ,  m_allocated(0)
    {}
 
    //!Destructor. Deallocates all allocated chunks. Never throws
-   ~private_node_pool()
+   ~private_node_pool_impl()
    {  priv_clear();  }
 
    //!Returns the segment manager. Never throws
-   segment_manager* get_segment_manager()const
-   {  return detail::get_pointer(mp_segment_mngr);  }
+   segment_manager_base_type* get_segment_manager_base()const
+   {  return detail::get_pointer(mp_segment_mngr_base);  }
 
    //!Allocates array of count elements. Can throw 
boost::interprocess::bad_alloc
    void *allocate(std::size_t count)
    {
-      std::size_t bytes = count*NodeSize;
-      if(bytes > RealNodeSize)//Normal allocation, no pooling used
-         return mp_segment_mngr->allocate(bytes);
+      std::size_t bytes = count*m_node_size;
+      if(bytes > m_real_node_size){//Normal allocation, no pooling used
+         void *addr = mp_segment_mngr_base->allocate(bytes);
+         if(!addr)   throw bad_alloc();
+         return addr;
+      }
       else                    //Node allocation, pooling used
          return priv_alloc_node();
    }
@@ -106,9 +101,9 @@
    //!Deallocates an array pointed by ptr. Never throws
    void deallocate(void *ptr, std::size_t count)
    {
-      std::size_t bytes = count*NodeSize;
-      if(bytes > RealNodeSize)//Normal allocation was used
-         mp_segment_mngr->deallocate(ptr);
+      std::size_t bytes = count*m_node_size;
+      if(bytes > m_real_node_size)//Normal allocation was used
+         mp_segment_mngr_base->deallocate(ptr);
       else                    //Node allocation was used
          priv_dealloc_node(ptr);
    }
@@ -137,12 +132,21 @@
    void deallocate_nodes(free_nodes_t &nodes, std::size_t n)
    {  priv_deallocate_nodes(nodes, n);  }
 
+   //!Deallocates all the free chunks of memory. Never throws
    void deallocate_free_chunks()
    {  priv_deallocate_free_chunks();   }
 
    std::size_t num_free_nodes()
    {  return m_freelist.size();  }
 
+   void swap(private_node_pool_impl &other)
+   {
+      std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
+      m_chunklist.swap(other.m_chunklist);
+      m_freelist.swap(other.m_freelist);
+      std::swap(m_allocated, other.m_allocated);
+   }
+
    private:
 
    void priv_deallocate_nodes(free_nodes_t &nodes, const std::size_t num)
@@ -209,15 +213,15 @@
 
          //Execute the algorithm and get an iterator to the last value
          m_freelist.remove_and_dispose_if
-            (is_between(addr, BlockSize), push_in_list(free_nodes, last_it));
+            (is_between(addr, m_block_size), push_in_list(free_nodes, 
last_it));
 
-         //If the number of nodes is equal to nodes_per_chunk
+         //If the number of nodes is equal to m_nodes_per_chunk
          //this means that the block can be deallocated
-         if(free_nodes.size() == nodes_per_chunk){
+         if(free_nodes.size() == m_nodes_per_chunk){
             //Unlink the nodes
             free_nodes.clear();
             it = m_chunklist.erase_after(bit);
-            mp_segment_mngr->deallocate((void*)addr);
+            mp_segment_mngr_base->deallocate((void*)addr);
          }
          //Otherwise, insert them in the backup list, since the
          //next "remove_if" does not need to check them again.
@@ -262,7 +266,7 @@
       while(!m_chunklist.empty()){
          void *addr = get_chunk_from_hook(&m_chunklist.front());
          m_chunklist.pop_front();
-         mp_segment_mngr->deallocate(addr);
+         mp_segment_mngr_base->deallocate(addr);
       }  
    }
 
@@ -296,63 +300,97 @@
    {
       //We allocate a new NodeBlock and put it as first
       //element in the free Node list
-      char *pNode = 
detail::char_ptr_cast(mp_segment_mngr->allocate(ChunkSize));
+      char *pNode = 
detail::char_ptr_cast(mp_segment_mngr_base->allocate(m_block_size + 
sizeof(node_t)));
+      if(!pNode)  throw bad_alloc();
       char *pBlock = pNode;
       m_chunklist.push_front(get_chunk_hook(pBlock));
 
       //We initialize all Nodes in Node Block to insert 
       //them in the free Node list
-      for(std::size_t i = 0; i < NumAlloc; ++i, pNode += RealNodeSize){
+      for(std::size_t i = 0; i < m_nodes_per_chunk; ++i, pNode += 
m_real_node_size){
          m_freelist.push_front(*new (pNode) node_t);
       }
    }
 
- private:
+   private:
    //!Returns a reference to the chunk hook placed in the end of the chunk
-   static inline node_t & get_chunk_hook (void *chunk)
+   inline node_t & get_chunk_hook (void *chunk)
    {  
       return *static_cast<node_t*>(
-               static_cast<void*>((detail::char_ptr_cast(chunk)+BlockSize)));  
+               
static_cast<void*>((detail::char_ptr_cast(chunk)+m_block_size)));  
    }
 
    //!Returns the starting address of the chunk reference to the chunk hook 
placed in the end of the chunk
-   static inline void *get_chunk_from_hook (node_t *hook)
+   inline void *get_chunk_from_hook (node_t *hook)
    {  
-      return static_cast<void*>((detail::char_ptr_cast(hook) - BlockSize));  
+      return static_cast<void*>((detail::char_ptr_cast(hook) - m_block_size)); 
 
    }
 
- private:
+   private:
    typedef typename pointer_to_other
-      <void_pointer, segment_manager>::type   segment_mngr_ptr_t;
+      <void_pointer, segment_manager_base_type>::type   
segment_mngr_base_ptr_t;
 
-   segment_mngr_ptr_t   mp_segment_mngr;  //Segment manager
-   
-   chunkslist_t   m_chunklist;      //Intrusive container of chunks
-   free_nodes_t   m_freelist;       //Intrusive container of free nods
-   std::size_t    m_allocated;      //Used nodes for debugging
+   const std::size_t m_node_size;
+   const std::size_t m_nodes_per_chunk;
+   const std::size_t m_real_node_size;
+   const std::size_t m_block_size;
+   segment_mngr_base_ptr_t mp_segment_mngr_base;   //Segment manager
+   chunkslist_t      m_chunklist;      //Intrusive container of chunks
+   free_nodes_t      m_freelist;       //Intrusive container of free nods
+   std::size_t       m_allocated;      //Used nodes for debugging
 };
 
 
 //!Pooled shared memory allocator using single segregated storage. Includes
 //!a reference count but the class does not delete itself, this is  
 //!responsibility of user classes. Node size (NodeSize) and the number of
-//!nodes allocated per chunk (NumAlloc) are known at compile time
-template<class SegmentManager, class Mutex,
-         std::size_t NodeSize, std::size_t NumAlloc>
+//!nodes allocated per chunk (NodesPerChunk) are known at compile time
+template< class SegmentManager, std::size_t NodeSize, std::size_t 
NodesPerChunk >
+class private_node_pool
+   //Inherit from the implementation to avoid template bloat
+   :  public private_node_pool_impl<typename 
SegmentManager::segment_manager_base_type>
+{
+   typedef private_node_pool_impl<typename 
SegmentManager::segment_manager_base_type> base_t;
+   //Non-copyable
+   private_node_pool();
+   private_node_pool(const private_node_pool &);
+   private_node_pool &operator=(const private_node_pool &);
+
+   public:
+   typedef SegmentManager segment_manager;
+
+   static const std::size_t nodes_per_chunk = NodesPerChunk;
+
+   //!Constructor from a segment manager. Never throws
+   private_node_pool(segment_manager *segment_mngr)
+      :  base_t(segment_mngr, NodeSize, NodesPerChunk)
+   {}
+
+   //!Returns the segment manager. Never throws
+   segment_manager* get_segment_manager() const
+   {  return 
static_cast<segment_manager*>(base_t::get_segment_manager_base()); }
+};
+
+
+//!Pooled shared memory allocator using single segregated storage. Includes
+//!a reference count but the class does not delete itself, this is  
+//!responsibility of user classes. Node size (NodeSize) and the number of
+//!nodes allocated per chunk (NodesPerChunk) are known at compile time
+template< class SegmentManager
+        , class Mutex
+        , std::size_t NodeSize
+        , std::size_t NodesPerChunk
+        >
 class shared_node_pool 
-   : public private_node_pool 
-      <SegmentManager, NodeSize, NumAlloc> 
+   : public private_node_pool<SegmentManager, NodeSize, NodesPerChunk> 
 {
- private:
+   private:
    typedef typename SegmentManager::void_pointer void_pointer;
-   typedef typename pointer_to_other<void_pointer, char>::type char_ptr_t;
    typedef private_node_pool
-      <SegmentManager, 
-       NodeSize, NumAlloc>                private_node_allocator_t;
- public:
-   //!Segment manager typedef
-   typedef SegmentManager   segment_manager;
+      <SegmentManager, NodeSize, NodesPerChunk> private_node_allocator_t;
 
+   public:
+   typedef SegmentManager   segment_manager;
    typedef typename private_node_allocator_t::free_nodes_t  free_nodes_t;
 
    //!Constructor from a segment manager. Never throws
@@ -360,7 +398,7 @@
    : private_node_allocator_t(segment_mngr){}
 
    //!Destructor. Deallocates all allocated chunks. Never throws
-  ~shared_node_pool()
+   ~shared_node_pool()
    {}
 
    //!Allocates array of count elements. Can throw 
boost::interprocess::bad_alloc
@@ -408,6 +446,15 @@
       private_node_allocator_t::deallocate_nodes(nodes);
    }
 
+   //!Deallocates all the free chunks of memory. Never throws
+   void deallocate_free_chunks()
+   {
+      //-----------------------
+      boost::interprocess::scoped_lock<Mutex> guard(m_header);
+      //-----------------------
+      private_node_allocator_t::deallocate_free_chunks();
+   }
+
    //!Increments internal reference count and returns new count. Never throws
    std::size_t inc_ref_count()
    {
@@ -427,7 +474,7 @@
       return --m_header.m_usecount;
    }
 
- private:
+   private:
    //!This struct includes needed data and derives from
    //!interprocess_mutex to allow EBO when using null_mutex
    struct header_t : Mutex


-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
Boost-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-cvs

Reply via email to