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