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

Modified Files:
        allocation_type.hpp allocator.hpp cached_node_allocator.hpp 
        node_allocator.hpp private_node_allocator.hpp 
Log Message:
Changes for official inclusion in the regression tests

Index: allocation_type.hpp
===================================================================
RCS file: 
/cvsroot/boost/boost/boost/interprocess/allocators/allocation_type.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- allocation_type.hpp 27 Jul 2006 10:27:36 -0000      1.2
+++ allocation_type.hpp 4 May 2007 20:53:07 -0000       1.3
@@ -1,10 +1,10 @@
 ///////////////////////////////////////////////////////////////////////////////
 //
-// (C) Copyright Ion Gaztañaga 2005-2006. Distributed under the Boost
+// (C) Copyright Ion Gaztañaga 2005-2007. 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/interprocess/ for documentation.
+// See http://www.boost.org/libs/interprocess for documentation.
 //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -19,11 +19,11 @@
 #include <boost/interprocess/detail/workaround.hpp>
 
 namespace boost {
-
 namespace interprocess {
 
+/// @cond
 enum allocation_type_v
-{
+{   
    // constants for allocation commands
    allocate_new_v   = 0x01,
    expand_fwd_v     = 0x02,
@@ -33,7 +33,9 @@
    shrink_in_place_v = 0x08,
    nothrow_allocation_v = 0x10
 };
+
 typedef int allocation_type;
+/// @endcond
 static const allocation_type allocate_new       = 
(allocation_type)allocate_new_v;
 static const allocation_type expand_fwd         = 
(allocation_type)expand_fwd_v;
 static const allocation_type expand_bwd         = 
(allocation_type)expand_bwd_v;
@@ -41,7 +43,6 @@
 static const allocation_type nothrow_allocation = 
(allocation_type)nothrow_allocation_v;
 
 }  //namespace interprocess {
-
 }  //namespace boost {
 
 #include <boost/interprocess/detail/config_end.hpp>

Index: allocator.hpp
===================================================================
RCS file: /cvsroot/boost/boost/boost/interprocess/allocators/allocator.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- allocator.hpp       15 Oct 2006 13:11:05 -0000      1.2
+++ allocator.hpp       4 May 2007 20:53:07 -0000       1.3
@@ -1,6 +1,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 //
-// (C) Copyright Ion Gaztañaga 2005-2006. Distributed under the Boost
+// (C) Copyright Ion Gaztañaga 2005-2007. 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)
 //
@@ -25,6 +25,8 @@
 #include <boost/interprocess/detail/version_type.hpp>
 #include <boost/interprocess/exceptions.hpp>
 #include <boost/assert.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
 #include <memory>
 #include <algorithm>
 #include <cstddef>
@@ -46,7 +48,8 @@
 template<class T, class SegmentManager>
 class allocator 
 {
- private:
+   /// @cond
+   private:
    /*!Self type*/
    typedef allocator<T, SegmentManager>   self_t;
 
@@ -66,16 +69,17 @@
       <cvoid_ptr, segment_manager>::type     alloc_ptr_t;
 
    /*!Not assignable from related allocator*/
-   template<class T2, class AllocAlgo2>
-   allocator& operator=(const allocator<T2, AllocAlgo2>&);
+   template<class T2, class SegmentManager2>
+   allocator& operator=(const allocator<T2, SegmentManager2>&);
 
    /*!Not assignable from other allocator*/
    allocator& operator=(const allocator&);
 
    /*!Pointer to the allocator*/
    alloc_ptr_t mp_mngr;
+   /// @endcond
 
- public:
+   public:
    typedef T                                    value_type;
    typedef typename detail::pointer_to_other
       <cvoid_ptr, T>::type                      pointer;
@@ -90,7 +94,6 @@
 
    typedef detail::version_type<allocator, 2>   version;
 
-
    /*!Obtains an allocator of other type*/
    template<class T2>
    struct rebind
@@ -126,7 +129,11 @@
    /*!Allocates memory for an array of count elements. 
       Throws boost::interprocess::bad_alloc if there is no enough memory*/
    pointer allocate(size_type count, cvoid_ptr hint = 0)
-   {  return 
pointer((value_type*)mp_mngr->allocate(count*sizeof(value_type)));  }
+   {
+      if(count > ((size_type)-1)/sizeof(value_type))
+         throw bad_alloc();
+      return pointer((value_type*)mp_mngr->allocate(count*sizeof(value_type)));
+   }
 
    /*!Deallocates memory previously allocated. Never throws*/
    void deallocate(const pointer &ptr, size_type)
@@ -149,7 +156,7 @@
 
    /*!Returns the number of elements that could be allocated. Never throws*/
    size_type max_size() const
-   {  return mp_mngr->get_size();   }
+   {  return mp_mngr->get_size()/sizeof(value_type);   }
 
    /*!Swap segment manager. Does not throw. If each allocator is placed in
       different memory segments, the result is undefined.*/
@@ -164,13 +171,26 @@
                          size_type preferred_size,
                          size_type &received_size, const pointer &reuse = 0)
    {
+      std::pair<pointer, bool> ret;
+      size_type max_count = ((size_type)-1)/sizeof(value_type);
+      if(limit_size > max_count || preferred_size > max_count){
+         if(command & nothrow_allocation){
+            throw bad_alloc();
+         }
+         else{
+            ret.first = 0;
+            return ret;
+         }
+      }
+
       std::size_t l_size = limit_size*sizeof(value_type);
       std::size_t p_size = preferred_size*sizeof(value_type);
       std::size_t r_size;
       std::pair<void *, bool> result =
          mp_mngr->allocation_command
-            (command, l_size, p_size, r_size, detail::get_pointer(reuse));
+            (command, l_size, p_size, r_size, detail::get_pointer(reuse), 
sizeof(value_type));
       received_size = r_size/sizeof(value_type);
+      BOOST_ASSERT(0 == ((std::size_t)result.first % 
boost::alignment_of<value_type>::value));
       return std::pair<pointer, bool> 
          (static_cast<value_type*>(result.first), result.second);
    }
@@ -208,6 +228,7 @@
                 const allocator<T, SegmentManager>  &alloc2)
    {  return alloc1.get_segment_manager() != alloc2.get_segment_manager(); }
 
+/// @cond
 /*!This specialization indicates that the construct function allows
    convertible types to construct the value type. This allows
    storing less allocator instances in containers.*/
@@ -217,10 +238,18 @@
 {
    enum {   value = true };
 };
-
+/// @endcond
 
 }  //namespace interprocess {
 
+/// @cond
+template<class T, class SegmentManager>
+struct has_trivial_destructor
+   <boost::interprocess::allocator <T, SegmentManager> >
+   :  public ::boost::true_type
+{};
+/// @endcond
+
 }  //namespace boost {
 
 #include <boost/interprocess/detail/config_end.hpp>

Index: cached_node_allocator.hpp
===================================================================
RCS file: 
/cvsroot/boost/boost/boost/interprocess/allocators/cached_node_allocator.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- cached_node_allocator.hpp   7 Aug 2006 13:58:38 -0000       1.2
+++ cached_node_allocator.hpp   4 May 2007 20:53:07 -0000       1.3
@@ -1,6 +1,6 @@
 //////////////////////////////////////////////////////////////////////////////
 //
-// (C) Copyright Ion Gaztañaga 2005-2006. Distributed under the Boost
+// (C) Copyright Ion Gaztañaga 2005-2007. 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)
 //
@@ -46,11 +46,10 @@
    cached_node_allocator with equal sizeof(T) placed in the same fixed size 
    memory segment. But also caches some nodes privately to
    avoid some synchronization overhead.*/
-template<class T, class SegmentManager>
+template<class T, class SegmentManager, std::size_t NodesPerChunk>
 class cached_node_allocator
 {
-   enum {   NumAlloc = 64  };
- 
+   /// @cond
    typedef typename SegmentManager::void_pointer          void_pointer;
    typedef typename detail::
       pointer_to_other<void_pointer, const void>::type    cvoid_pointer;
@@ -58,8 +57,11 @@
    typedef typename detail::
       pointer_to_other<void_pointer, char>::type          char_pointer;
    typedef typename SegmentManager::mutex_family::mutex_type mutex_type;
-   typedef cached_node_allocator<T, SegmentManager>       self_t;
+   typedef cached_node_allocator<T, SegmentManager, NodesPerChunk>   self_t;
    enum { DEFAULT_MAX_CACHED_NODES = 64 };
+   typedef typename detail::node_slist<void_pointer>::node_t         node_t;
+   typedef typename detail::node_slist<void_pointer>::node_slist_t   
cached_list_t;
+   /// @endcond
 
    public:
    //-------
@@ -75,46 +77,43 @@
    typedef std::size_t                                   size_type;
    typedef std::ptrdiff_t                                difference_type;
 
-   /*!Obtains cached_node_allocator from other cached_node_allocator*/
+   //!Obtains cached_node_allocator from other cached_node_allocator
    template<class T2>
    struct rebind
    {  
-      typedef cached_node_allocator<T2, SegmentManager>   other;
+      typedef cached_node_allocator<T2, SegmentManager, NodesPerChunk>   other;
    };
 
- private:
+   /// @cond
+   private:
 
-   /*!Not assignable from related cached_node_allocator*/
-   template<class T2, class AllogAlgo2>
+   //!Not assignable from related cached_node_allocator
+   template<class T2, class SegmentManager2, std::size_t N2>
    cached_node_allocator& operator=
-      (const cached_node_allocator<T2, AllogAlgo2>&);
+      (const cached_node_allocator<T2, SegmentManager2, N2>&);
 
    /*!Not assignable from other cached_node_allocator*/
    cached_node_allocator& operator=(const cached_node_allocator&);
+   /// @endcond
 
- public:
+   public:
    /*!Constructor from a segment manager. If not present, constructs
       a node pool. Increments the reference count of the node pool.
       Can throw boost::interprocess::bad_alloc*/
    cached_node_allocator(segment_manager *segment_mngr,
                          std::size_t max_cached_nodes = 
DEFAULT_MAX_CACHED_NODES) 
       : mp_node_pool(priv_get_or_create(segment_mngr)),
-        mp_cached(0),
-        m_cached_nodes(0),
         m_max_cached_nodes(max_cached_nodes)
-        
-        { }
+   {}
 
    /*!Copy constructor from other cached_node_allocator. Increments the 
       reference count of the associated node pool. Never throws*/
    cached_node_allocator(const cached_node_allocator &other) 
       : mp_node_pool(other.get_node_pool()),
-        mp_cached(0),
-        m_cached_nodes(0),
         m_max_cached_nodes(other.get_max_cached_nodes())
    {  
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), NumAlloc>   node_pool_t;
+               <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   
node_pool_t;
       node_pool_t *node_pool = 
static_cast<node_pool_t*>(other.get_node_pool());
       node_pool->inc_ref_count();   
    }
@@ -124,10 +123,8 @@
       Can throw boost::interprocess::bad_alloc*/
    template<class T2>
    cached_node_allocator
-      (const cached_node_allocator<T2, SegmentManager> &other)
+      (const cached_node_allocator<T2, SegmentManager, NodesPerChunk> &other)
       : mp_node_pool(priv_get_or_create(other.get_segment_manager())),
-        mp_cached(0),
-        m_cached_nodes(0), 
         m_max_cached_nodes(other.get_max_cached_nodes())
          { }
 
@@ -147,7 +144,7 @@
    segment_manager* get_segment_manager()const
    {  
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), NumAlloc>   node_pool_t;
+               <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   
node_pool_t;
       node_pool_t *node_pool = 
static_cast<node_pool_t*>(detail::get_pointer(mp_node_pool));
       return node_pool->get_segment_manager();  
    }
@@ -184,29 +181,27 @@
 
    /*!Returns the number of elements that could be allocated. Never throws*/
    size_type max_size() const
-      {  return this->get_segment_manager()->get_size();  }
+      {  return this->get_segment_manager()->get_size()/sizeof(value_type);  }
 
    /*!Allocate memory for an array of count elements. 
       Throws boost::interprocess::bad_alloc if there is no enough memory*/
    pointer allocate(size_type count, cvoid_pointer hint = 0)
    {  
+      if(count > ((size_type)-1)/sizeof(value_type))
+         throw bad_alloc();
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), NumAlloc>   node_pool_t;
+               <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   
node_pool_t;
       
       void * ret;
       
       if(count == 1){
-         //If don't have any cached node, we have to get a null
-         //terminated linked list of n nodes from the pool
-         if(!mp_cached){
+         //If don't have any cached node, we have to get a new list of free 
nodes from the pool
+         if(m_cached_nodes.empty()){
             node_pool_t *node_pool = 
static_cast<node_pool_t*>(detail::get_pointer(mp_node_pool));
-            mp_cached = 
detail::char_ptr_cast(node_pool->allocate_nodes(m_max_cached_nodes/2));
-            m_cached_nodes = m_max_cached_nodes/2;
+            node_pool->allocate_nodes(m_max_cached_nodes/2, m_cached_nodes);
          }
-         //Get the first node
-         ret = detail::get_pointer(mp_cached);
-         mp_cached = node_pool_t::next_node(detail::get_pointer(mp_cached));
-         --m_cached_nodes;
+         ret = &m_cached_nodes.front();
+         m_cached_nodes.pop_front();
       }
       else{
          node_pool_t *node_pool = 
static_cast<node_pool_t*>(detail::get_pointer(mp_node_pool));
@@ -219,21 +214,18 @@
    void deallocate(const pointer &ptr, size_type count)
    {
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), NumAlloc>   node_pool_t;
+               <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   
node_pool_t;
 
       if(count == 1){
          //Check if cache is full
-         if(m_cached_nodes >= m_max_cached_nodes){
+         if(m_cached_nodes.size() >= m_max_cached_nodes){
             //This only occurs if this allocator deallocate memory allocated
             //with other equal allocator. Since the cache is full, and more 
             //deallocations are probably coming, we'll make some room in cache
             //in a single, efficient multi node deallocation.
-            priv_deallocate_n_nodes(m_cached_nodes - m_max_cached_nodes/2);
+            priv_deallocate_n_nodes(m_cached_nodes.size() - 
m_max_cached_nodes/2);
          }
-         char *node = detail::char_ptr_cast(detail::get_pointer(ptr));         
-         node_pool_t::next_node(detail::get_pointer(node)) = mp_cached;
-         mp_cached        = node;
-         ++m_cached_nodes;
+         
m_cached_nodes.push_front(*(node_t*)detail::char_ptr_cast(detail::get_pointer(ptr)));
       }
       else{
          node_pool_t *node_pool = static_cast<node_pool_t*>
@@ -252,17 +244,19 @@
       detail::do_swap(alloc1.m_max_cached_nodes, alloc2.m_max_cached_nodes);
    }
 
-   void clear_cache()
+   //!Returns the cached nodes to the shared pool
+   void deallocate_cache()
       {  this->priv_deallocate_all_cached_nodes(); }
 
- private:
+   /// @cond
+   private:
 
    /*!Object function that creates the node allocator if it is not created and
       increments reference count if it is already created*/
    struct get_or_create_func
    {
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), NumAlloc>   node_pool_t;
+               <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   
node_pool_t;
 
       /*!This connects or constructs the unique instance of node_pool_t
          Can throw boost::interprocess::bad_alloc*/
@@ -287,44 +281,29 @@
    void priv_deallocate_all_cached_nodes()
    {
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), NumAlloc>   node_pool_t;
-      node_pool_t *node_pool = static_cast<node_pool_t*>
-         (detail::get_pointer(mp_node_pool));
-      node_pool->deallocate_nodes(detail::get_pointer(mp_cached));
-      mp_cached = 0;
+               <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   
node_pool_t;
+      node_pool_t *node_pool = 
static_cast<node_pool_t*>(detail::get_pointer(mp_node_pool));
+      node_pool->deallocate_nodes(m_cached_nodes);
    }
 
    /*!Frees all cached nodes at once. Never throws*/
    void priv_deallocate_remaining_nodes()
    {
-      if(m_cached_nodes > m_max_cached_nodes){
-         priv_deallocate_n_nodes(m_cached_nodes);
+      if(m_cached_nodes.size() > m_max_cached_nodes){
+         priv_deallocate_n_nodes(m_cached_nodes.size()-m_max_cached_nodes);
       }
    }
 
    /*!Frees n cached nodes at once. Never throws*/
    void priv_deallocate_n_nodes(std::size_t n)
    {
-      //Check n
-      if(n==0) return;   
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), NumAlloc>   node_pool_t;
+         <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   node_pool_t;
       node_pool_t *node_pool = static_cast<node_pool_t*>
          (detail::get_pointer(mp_node_pool));
 
-      //Create a new linked list of n nodes ending in null
-      //taking the first n bytes of cached nodes list
-      m_cached_nodes -= n;
-      char_pointer head = mp_cached, prev;
-      while(n--){ 
-         prev = mp_cached;   
-         mp_cached = node_pool_t::next_node(detail::get_pointer(mp_cached));
-      }
-
-      node_pool_t::next_node(detail::get_pointer(prev)) = 0;      
-
       //Deallocate all new linked list at once
-      node_pool->deallocate_nodes(detail::get_pointer(head));
+      node_pool->deallocate_nodes(m_cached_nodes, n);
    }   
 
    /*!Initialization function, creates an executes atomically the 
@@ -342,7 +321,7 @@
    struct destroy_if_last_link_func
    {
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type,sizeof(T), NumAlloc>   node_pool_t;
+               <SegmentManager, mutex_type,sizeof(T), NodesPerChunk>   
node_pool_t;
 
       /*!Decrements reference count and destroys the object if there is no 
          more attached allocators. Never throws*/
@@ -369,7 +348,7 @@
    void priv_destroy_if_last_link()
    {
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type,sizeof(T), NumAlloc>   node_pool_t;
+               <SegmentManager, mutex_type,sizeof(T), NodesPerChunk>   
node_pool_t;
       //Get segment manager
       segment_manager *segment_mngr = this->get_segment_manager();
       //Get pool pointer
@@ -380,10 +359,10 @@
       segment_mngr->atomic_func(func);
    }
 
- private:
+   private:
    // We can't instantiate a pointer like this:
    // detail::shared_node_pool<SegmentManager, mutex_type, 
-   //                             sizeof(T), NumAlloc> *mp_node_pool;
+   //                             sizeof(T), NodesPerChunk> *mp_node_pool;
    // since it can provoke an early instantiation of T, that could be 
    // incomplete at that moment (for example, a node of a node-based container)
    // This provokes errors on some node based container implementations using
@@ -392,35 +371,36 @@
    // Because of this, we will use a void offset pointer and we'll do some 
    //(ugly )casts when needed.
    void_pointer   mp_node_pool;
-   char_pointer   mp_cached;       //Ptr to the first cached node
-   std::size_t    m_cached_nodes;
+   cached_list_t  m_cached_nodes;
    std::size_t    m_max_cached_nodes;
+   /// @endcond
 };
 
 /*!Equality test for same type of cached_node_allocator*/
-template<class T, class A> inline
-bool operator==(const cached_node_allocator<T, A> &alloc1, 
-                const cached_node_allocator<T, A> &alloc2)
+template<class T, class S, std::size_t NodesPerChunk> inline
+bool operator==(const cached_node_allocator<T, S, NodesPerChunk> &alloc1, 
+                const cached_node_allocator<T, S, NodesPerChunk> &alloc2)
    {  return alloc1.get_node_pool() == alloc2.get_node_pool(); }
 
 /*!Inequality test for same type of cached_node_allocator*/
-template<class T, class A> inline
-bool operator!=(const cached_node_allocator<T, A> &alloc1, 
-                const cached_node_allocator<T, A> &alloc2)
+template<class T, class S, std::size_t NodesPerChunk> inline
+bool operator!=(const cached_node_allocator<T, S, NodesPerChunk> &alloc1, 
+                const cached_node_allocator<T, S, NodesPerChunk> &alloc2)
    {  return alloc1.get_node_pool() != alloc2.get_node_pool(); }
 
+/// @cond
 /*!This specialization indicates that the construct function allows
    convertible types to construct the value type. This allows
    storing less allocator instances in containers.*/
-template<class T, class SegmentManager>
+template<class T, class SegmentManager, std::size_t NodesPerChunk>
 struct has_convertible_construct
-   <boost::interprocess::cached_node_allocator<T, SegmentManager> >
+   <boost::interprocess::cached_node_allocator<T, SegmentManager, 
NodesPerChunk> >
 {
    enum {   value = true };
 };
+/// @endcond
 
 }  //namespace interprocess {
-
 }  //namespace boost {
 
 #include <boost/interprocess/detail/config_end.hpp>

Index: node_allocator.hpp
===================================================================
RCS file: 
/cvsroot/boost/boost/boost/interprocess/allocators/node_allocator.hpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- node_allocator.hpp  15 Oct 2006 13:11:05 -0000      1.3
+++ node_allocator.hpp  4 May 2007 20:53:07 -0000       1.4
@@ -1,6 +1,6 @@
 //////////////////////////////////////////////////////////////////////////////
 //
-// (C) Copyright Ion Gaztañaga 2005-2006. Distributed under the Boost
+// (C) Copyright Ion Gaztañaga 2005-2007. 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)
 //
@@ -46,22 +46,20 @@
    placing the allocator in shared memory, memory mapped-files, etc...
    This node allocator shares a segregated storage between all instances 
    of node_allocator with equal sizeof(T) placed in the same segment 
-   group. N is the number of nodes allocated at once when the allocator
+   group. NodesPerChunk is the number of nodes allocated at once when the 
allocator
    needs runs out of nodes*/
-template<class T, std::size_t N, class SegmentManager>
+template<class T, class SegmentManager, std::size_t NodesPerChunk>
 class node_allocator
 {
- public:
+   public:
    typedef typename SegmentManager::void_pointer         void_pointer;
    typedef typename detail::
       pointer_to_other<void_pointer, const void>::type   cvoid_pointer;
    typedef SegmentManager                                segment_manager;
-   typedef typename detail::
-      pointer_to_other<void_pointer, char>::type         char_pointer;
    typedef typename SegmentManager::
-      mutex_family::mutex_type                              mutex_type;
+      mutex_family::mutex_type                           mutex_type;
    typedef node_allocator
-      <T, N, SegmentManager>                             self_t;
+      <T, SegmentManager, NodesPerChunk>                 self_t;
 
    public:
    //-------
@@ -81,20 +79,21 @@
    template<class T2>
    struct rebind
    {  
-      typedef node_allocator<T2, N, SegmentManager>   other;
+      typedef node_allocator<T2, SegmentManager, NodesPerChunk>   other;
    };
 
- private:
-
+   /// @cond
+   private:
    /*!Not assignable from related node_allocator*/
-   template<class T2, std::size_t N2, class AllocAlgo2>
+   template<class T2, class SegmentManager2, std::size_t N2>
    node_allocator& operator=
-      (const node_allocator<T2, N2, AllocAlgo2>&);
+      (const node_allocator<T2, SegmentManager2, N2>&);
 
    /*!Not assignable from other node_allocator*/
    node_allocator& operator=(const node_allocator&);
+   /// @endcond
 
- public:
+   public:
 
    /*!Constructor from a segment manager. If not present, constructs a node
       pool. Increments the reference count of the associated node pool.
@@ -108,7 +107,7 @@
       : mp_node_pool(other.get_node_pool()) 
    {  
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), N>   node_pool_t;
+               <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   
node_pool_t;
       node_pool_t *node_pool  = 
static_cast<node_pool_t*>(other.get_node_pool());
       node_pool->inc_ref_count();   
    }
@@ -118,7 +117,7 @@
       Can throw boost::interprocess::bad_alloc*/
    template<class T2>
    node_allocator
-      (const node_allocator<T2, N, SegmentManager> &other)
+      (const node_allocator<T2, SegmentManager, NodesPerChunk> &other)
       : mp_node_pool(priv_get_or_create(other.get_segment_manager())) { }
 
    /*!Destructor, removes node_pool_t from memory
@@ -134,7 +133,7 @@
    segment_manager* get_segment_manager()const
    {  
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), N>   node_pool_t;
+               <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   
node_pool_t;
       node_pool_t *node_pool  = static_cast<node_pool_t*>
          (detail::get_pointer(mp_node_pool));
       return node_pool->get_segment_manager();
@@ -160,14 +159,16 @@
 
    /*!Returns the number of elements that could be allocated. Never throws*/
    size_type max_size() const
-      {  return this->get_segment_manager()->get_size();  }
+      {  return this->get_segment_manager()->get_size()/sizeof(value_type);  }
 
    /*!Allocate memory for an array of count elements. 
       Throws boost::interprocess::bad_alloc if there is no enough memory*/
    pointer allocate(size_type count, cvoid_pointer = 0)
    {  
+      if(count > ((size_type)-1)/sizeof(value_type))
+         throw bad_alloc();
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), N>   node_pool_t;
+               <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   
node_pool_t;
       node_pool_t *node_pool  = static_cast<node_pool_t*>
          (detail::get_pointer(mp_node_pool));
       return pointer(static_cast<T*>(node_pool->allocate(count)));
@@ -177,7 +178,7 @@
    void deallocate(const pointer &ptr, size_type count)
    {
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), N>   node_pool_t;
+               <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   
node_pool_t;
       node_pool_t *node_pool  = static_cast<node_pool_t*>
          (detail::get_pointer(mp_node_pool));
       node_pool->deallocate(detail::get_pointer(ptr), count);
@@ -186,18 +187,16 @@
    /*!Swaps allocators. Does not throw. If each allocator is placed in a
       different memory segment, the result is undefined.*/
    friend void swap(self_t &alloc1, self_t &alloc2)
-   {
-      using namespace std;
-      swap(alloc1.mp_node_pool, alloc2.mp_node_pool);
-   }
+   {  detail::do_swap(alloc1.mp_node_pool, alloc2.mp_node_pool);  }
 
- private:
+   /// @cond
+   private:
    /*!Object function that creates the node allocator if it is not created and
       increments reference count if it is already created*/
    struct get_or_create_func
    {
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type, sizeof(T), N>   node_pool_t;
+               <SegmentManager, mutex_type, sizeof(T), NodesPerChunk>   
node_pool_t;
 
       /*!This connects or constructs the unique instance of node_pool_t
          Can throw boost::interprocess::bad_alloc*/
@@ -233,7 +232,7 @@
    struct destroy_if_last_link_func
    {
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type,sizeof(T), N>   node_pool_t;
+               <SegmentManager, mutex_type,sizeof(T), NodesPerChunk>   
node_pool_t;
 
       /*!Decrements reference count and destroys the object if there is no 
          more attached allocators. Never throws*/
@@ -260,7 +259,7 @@
    void priv_destroy_if_last_link()
    {
       typedef detail::shared_node_pool
-               <SegmentManager, mutex_type,sizeof(T), N>   node_pool_t;
+               <SegmentManager, mutex_type,sizeof(T), NodesPerChunk>   
node_pool_t;
       //Get segment manager
       segment_manager *named_segment_mngr = this->get_segment_manager();
       //Get node pool pointer
@@ -275,7 +274,7 @@
  private:
    // We can't instantiate a pointer like this:
    // detail::shared_node_pool<SegmentManager, mutex_type, 
-   //                             sizeof(T), N> *mp_node_pool;
+   //                             sizeof(T), NodesPerChunk> *mp_node_pool;
    // since it can provoke an early instantiation of T, that could be 
    // incomplete at that moment (for example, a node of a node-based container)
    // This provokes errors on some node based container implementations using
@@ -284,36 +283,37 @@
    // Because of this, we will use a void offset pointer and we'll do some 
    //(ugly )casts when needed.
    void_pointer   mp_node_pool;
+   /// @endcond
 };
 
 /*!Equality test for same type of node_allocator*/
-template<class T, std::size_t N, class A> inline
-bool operator==(const node_allocator<T, N, A> &alloc1, 
-                const node_allocator<T, N, A> &alloc2)
+template<class T, class S, std::size_t NodesPerChunk> inline
+bool operator==(const node_allocator<T, S, NodesPerChunk> &alloc1, 
+                const node_allocator<T, S, NodesPerChunk> &alloc2)
    {  return alloc1.get_node_pool() == alloc2.get_node_pool(); }
 
 /*!Inequality test for same type of node_allocator*/
-template<class T, std::size_t N, class A> inline
-bool operator!=(const node_allocator<T, N, A> &alloc1, 
-                const node_allocator<T, N, A> &alloc2)
+template<class T, class S, std::size_t NodesPerChunk> inline
+bool operator!=(const node_allocator<T, S, NodesPerChunk> &alloc1, 
+                const node_allocator<T, S, NodesPerChunk> &alloc2)
    {  return alloc1.get_node_pool() != alloc2.get_node_pool(); }
 
 
+/// @cond
 /*!This specialization indicates that the construct function allows
    convertible types to construct the value type. This allows
    storing less allocator instances in containers.*/
-template<class T, std::size_t N, class A>
+template<class T, class S, std::size_t NodesPerChunk>
 struct has_convertible_construct
-   <boost::interprocess::node_allocator<T, N, A> >
+   <boost::interprocess::node_allocator<T, S, NodesPerChunk> >
 {
    enum {   value = true };
 };
+/// @endcond
 
 }  //namespace interprocess {
-
 }  //namespace boost {
 
 #include <boost/interprocess/detail/config_end.hpp>
 
 #endif   //#ifndef BOOST_INTERPROCESS_POOLED_NODE_ALLOCATOR_HPP
-

Index: private_node_allocator.hpp
===================================================================
RCS file: 
/cvsroot/boost/boost/boost/interprocess/allocators/private_node_allocator.hpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- private_node_allocator.hpp  7 Aug 2006 13:58:38 -0000       1.2
+++ private_node_allocator.hpp  4 May 2007 20:53:07 -0000       1.3
@@ -1,6 +1,6 @@
 //////////////////////////////////////////////////////////////////////////////
 //
-// (C) Copyright Ion Gaztañaga 2005-2006. Distributed under the Boost
+// (C) Copyright Ion Gaztañaga 2005-2007. 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)
 //
@@ -32,23 +32,22 @@
 #include <stdio.h>
 #include <cstddef>
 
-/*!\file
-   Describes private_node_allocator pooled shared memory STL compatible 
allocator 
-*/
+//!\file
+//!Describes private_node_allocator pooled shared memory STL compatible 
allocator 
 
 namespace boost {
-
 namespace interprocess {
 
-/*!An STL node allocator that uses a segment manager as memory 
-   source. The internal pointer type will of the same type (raw, smart) as
-   "typename SegmentManager::void_pointer" type. This allows
-   placing the allocator in shared memory, memory mapped-files, etc...
-   This allocator has its own node pool. N is the number of nodes allocated 
-   at once when the allocator needs runs out of nodes*/
-template<class T, std::size_t N, class SegmentManager>
+//!An STL node allocator that uses a segment manager as memory 
+//!source. The internal pointer type will of the same type (raw, smart) as
+//!"typename SegmentManager::void_pointer" type. This allows
+//!placing the allocator in shared memory, memory mapped-files, etc...
+//!This allocator has its own node pool. NodesPerChunk is the number of nodes 
allocated 
+//!at once when the allocator needs runs out of nodes
+template<class T, class SegmentManager, std::size_t NodesPerChunk>
 class private_node_allocator
 {
+   /// @cond
    private:
    typedef typename SegmentManager::void_pointer         void_pointer;
    typedef typename detail::
@@ -59,9 +58,10 @@
    typedef typename detail::pointer_to_other
       <void_pointer, segment_manager>::type              segment_mngr_ptr_t;
    typedef typename SegmentManager::
-      mutex_family::mutex_type                              mutex_type;
+      mutex_family::mutex_type                           mutex_type;
    typedef private_node_allocator
-      <T, N, SegmentManager>                             self_t;
+      <T, SegmentManager, NodesPerChunk>                 self_t;
+   /// @endcond
 
    public:
    //-------
@@ -77,25 +77,27 @@
    typedef std::size_t                                   size_type;
    typedef std::ptrdiff_t                                difference_type;
 
-   /*!Obtains node_allocator from other node_allocator*/
+   //!Obtains node_allocator from other node_allocator
    template<class T2>
    struct rebind
    {  
-      typedef private_node_allocator<T2, N, SegmentManager>   other;
+      typedef private_node_allocator<T2, SegmentManager, NodesPerChunk>   
other;
    };
 
-   /*!Not assignable from related private_node_allocator*/
-   template<class T2, std::size_t N2, class MemoryAlgorithm2>
+   /// @cond
+   private:
+   //!Not assignable from related private_node_allocator
+   template<class T2, class MemoryAlgorithm2, std::size_t N2>
    private_node_allocator& operator=
-      (const private_node_allocator<T2, N2, MemoryAlgorithm2>&);
+      (const private_node_allocator<T2, MemoryAlgorithm2, N2>&);
 
-   /*!Not assignable from other private_node_allocator*/
+   //!Not assignable from other private_node_allocator
    private_node_allocator& operator=(const private_node_allocator&);
 
    void priv_initialize()
    {
       typedef detail::private_node_pool
-               <SegmentManager, sizeof(T), N>   priv_node_pool_t;
+               <SegmentManager, sizeof(T), NodesPerChunk>   priv_node_pool_t;
       void * ptr = mp_segment_mngr->allocate(sizeof(priv_node_pool_t));
       //This does not throw
       new(ptr)priv_node_pool_t(detail::get_pointer(mp_segment_mngr));
@@ -107,7 +109,7 @@
    {
       //-------------------------------------------------------------
       typedef detail::private_node_pool
-                  <SegmentManager, sizeof(T), N>   priv_node_pool_t;
+                  <SegmentManager, sizeof(T), NodesPerChunk>   
priv_node_pool_t;
       //-------------------------------------------------------------
       priv_node_pool_t *pnode_pool     = static_cast<priv_node_pool_t*>
                                           (detail::get_pointer(mp_node_pool));
@@ -116,61 +118,63 @@
       pnode_pool->~priv_node_pool_t();
       segment_mngr.deallocate(pnode_pool);
    }
+   /// @endcond
 
- public:
+   public:
 
-   /*!Constructor from a segment manager.*/
+   //!Constructor from a segment manager
    private_node_allocator(segment_manager *segment_mngr)
       : mp_segment_mngr(segment_mngr), mp_node_pool(0){}
 
-   /*!Copy constructor from other private_node_allocator. Never throws*/
+   //!Copy constructor from other private_node_allocator. Never throws
    private_node_allocator(const private_node_allocator &other)
       : mp_segment_mngr(other.get_segment_manager()), mp_node_pool(0){}
 
-   /*!Copy constructor from related private_node_allocator. Never throws.*/
+   //!Copy constructor from related private_node_allocator. Never throws.
    template<class T2>
    private_node_allocator
-      (const private_node_allocator<T2, N, SegmentManager> &other)
+      (const private_node_allocator<T2, SegmentManager, NodesPerChunk> &other)
       : mp_segment_mngr(other.get_segment_manager()), mp_node_pool(0){}
 
-   /*!Destructor, frees all used memory. Never throws*/
+   //!Destructor, frees all used memory. Never throws
    ~private_node_allocator() 
       {  if(mp_node_pool)  priv_free();  }
 
-   /*!Returns the segment manager. Never throws*/
+   //!Returns the segment manager. Never throws
    segment_manager* get_segment_manager()const
       {  return detail::get_pointer(mp_segment_mngr);  }
 
-   /*!Return address of mutable value. Never throws*/
+   //!Return address of mutable value. Never throws
    pointer address(reference value) const
       {  return pointer(boost::addressof(value));  }
 
-   /*!Return address of non mutable value*. Never throws*/
+   //!Return address of non mutable value. Never throws
    const_pointer address(const_reference value) const
       {  return const_pointer(boost::addressof(value));  }
 
-   /*!Construct object, calling constructor. 
-   Throws if T(const Convertible &) throws*/
+   //!Construct object, calling constructor. 
+   //!Throws if T(const Convertible &) throws
    template<class Convertible>
    void construct(const pointer &ptr, const Convertible &value)
       {  new(detail::get_pointer(ptr)) value_type(value);  }
 
-   /*!Destroys object. Throws if object's destructor throws*/
+   //!Destroys object. Throws if object's destructor throws
    void destroy(const pointer &ptr)
       {  BOOST_ASSERT(ptr != 0); (*ptr).~value_type();  }
 
-
-   /*!Returns the number of elements that could be allocated. Never throws*/
+   //!Returns the number of elements that could be allocated. Never throws
    size_type max_size() const
-      {  return mp_segment_mngr->get_size();  }
+      {  return mp_segment_mngr->get_size()/sizeof(value_type);  }
 
-   /*!Allocate memory for an array of count elements. 
-      Throws boost::interprocess::bad_alloc if there is no enough memory*/
+   //!Allocate memory for an array of count elements. 
+   //!Throws boost::interprocess::bad_alloc if there is no enough memory
    pointer allocate(size_type count, cvoid_pointer hint = 0)
    {  
+      if(count > ((size_type)-1)/sizeof(value_type))
+         throw bad_alloc();
       //----------------------------------------------------------
       typedef detail::private_node_pool
-                  <SegmentManager, sizeof(T), N>   priv_node_pool_t;
+                  <SegmentManager, sizeof(T), NodesPerChunk>   
priv_node_pool_t;
       //----------------------------------------------------------
       if(!mp_node_pool)   priv_initialize();
       priv_node_pool_t *node_pool  = static_cast<priv_node_pool_t*>
@@ -178,12 +182,12 @@
       return pointer(static_cast<value_type*>(node_pool->allocate(count)));
    }
 
-   /*!Deallocate allocated memory. Never throws*/
+   //!Deallocate allocated memory. Never throws
    void deallocate(const pointer &ptr, size_type count)
    {
       //----------------------------------------------------------
       typedef detail::private_node_pool
-                  <SegmentManager, sizeof(T), N>   priv_node_pool_t;
+                  <SegmentManager, sizeof(T), NodesPerChunk>   
priv_node_pool_t;
       //----------------------------------------------------------
       if(!mp_node_pool)   priv_initialize();
       priv_node_pool_t *node_pool = static_cast<priv_node_pool_t*>(
@@ -191,8 +195,8 @@
       node_pool->deallocate(detail::get_pointer(ptr), count);
    }
 
-   /*!Swaps allocators. Does not throw. If each allocator is placed in a
-      different shared memory segments, the result is undefined.*/
+   //!Swaps allocators. Does not throw. If each allocator is placed in a
+   //!different shared memory segments, the result is undefined.*/
    friend void swap(self_t &alloc1,self_t &alloc2)
    {
       using namespace std;
@@ -200,10 +204,11 @@
       swap (alloc1.mp_node_pool,    alloc2.mp_node_pool);
    }
 
- private:
+   /// @cond
+   private:
    // We can't instantiate a pointer like this:
    // detail::private_node_pool<SegmentManager, 
-   //                             sizeof(T),  N> *mp_node_pool;
+   //                             sizeof(T),  NodesPerChunk> *mp_node_pool;
    // since it can provoke an early instantiation of T, that is not 
    // complete at the moment (for example, a node of a node-based pointer)
    // This provokes errors on some node based container implementations using
@@ -213,34 +218,36 @@
    // when needed.
    segment_mngr_ptr_t      mp_segment_mngr;
    void_pointer            mp_node_pool;
+   /// @endcond
 };
 
-/*!Equality test for same type of private_node_allocator*/
-template<class T, std::size_t N, class A> inline
-bool operator==(const private_node_allocator<T, N, A> &alloc1, 
-                const private_node_allocator<T, N, A> &alloc2)
+//!Equality test for same type of private_node_allocator
+template<class T, class S, std::size_t NodesPerChunk> inline
+bool operator==(const private_node_allocator<T, S, NodesPerChunk> &alloc1, 
+                const private_node_allocator<T, S, NodesPerChunk> &alloc2)
 {  return &alloc1 == &alloc2; }
 
-/*!Inequality test for same type of private_node_allocator*/
-template<class T, std::size_t N, class A> inline
-bool operator!=(const private_node_allocator<T, N, A> &alloc1, 
-                const private_node_allocator<T, N, A> &alloc2)
+//!Inequality test for same type of private_node_allocator
+template<class T, class S, std::size_t NodesPerChunk> inline
+bool operator!=(const private_node_allocator<T, S, NodesPerChunk> &alloc1, 
+                const private_node_allocator<T, S, NodesPerChunk> &alloc2)
 {  
    return &alloc1 != &alloc2;
 }
 
-/*!This specialization indicates that the construct function allows
-   convertible types to construct the value type. This allows
-   storing less allocator instances in containers.*/
-template<class T, std::size_t N, class A>
+/// @cond
+//!This specialization indicates that the construct function allows
+//!convertible types to construct the value type. This allows
+//!storing less allocator instances in containers.
+template<class T, class S, std::size_t NodesPerChunk>
 struct has_convertible_construct
-   <boost::interprocess::private_node_allocator<T, N, A> >
+   <boost::interprocess::private_node_allocator<T, S, NodesPerChunk> >
 {
    enum {   value = true };
 };
+/// @endcond
 
 }  //namespace interprocess {
-
 }  //namespace boost {
 
 #include <boost/interprocess/detail/config_end.hpp>


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Boost-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-cvs

Reply via email to