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