Multi-threaded Pooled Allocators
- by Darren Engwirda
I'm having some issues using pooled memory allocators for std::list objects in a multi-threaded application.
The part of the code I'm concerned with runs each thread function in isolation (i.e. there is no communication or synchronization between threads) and therefore I'd like to setup separate memory pools for each thread, where each pool is not thread-safe (and hence fast).
I've tried using a shared thread-safe singleton memory pool and found the performance to be poor, as expected.
This is a heavily simplified version of the type of thing I'm trying to do. A lot has been included in a pseudo-code kind of way, sorry if it's confusing.
/* The thread functor - one instance of MAKE_QUADTREE created for each thread
*/
class make_quadtree
{
private:
/* A non-thread-safe memory pool for int linked list items, let's say that it's
* something along the lines of BOOST::OBJECT_POOL
*/
pooled_allocator<int> item_pool;
/* The problem! - a local class that would be constructed within each std::list as the
* allocator but really just delegates to ITEM_POOL
*/
class local_alloc
{
public :
//!! I understand that I can't access ITEM_POOL from within a nested class like
//!! this, that's really my question - can I get something along these lines to
//!! work??
pointer allocate (size_t n) { return ( item_pool.allocate(n) ); }
};
public :
make_quadtree (): item_pool() // only construct 1 instance of ITEM_POOL per
// MAKE_QUADTREE object
{
/* The kind of data structures - vectors of linked lists
* The idea is that all of the linked lists should share a local pooled allocator
*/
std::vector<std::list<int, local_alloc>> lists;
/* The actual operations - too complicated to show, but in general:
*
* - The vector LISTS is grown as a quadtree is built, it's size is the number of
* quadtree "boxes"
*
* - Each element of LISTS (each linked list) represents the ID's of items
* contained within each quadtree box (say they're xy points), as the quadtree
* is grown a lot of ID pop/push-ing between lists occurs, hence the memory pool
* is important for performance
*/
}
};
So really my problem is that I'd like to have one memory pool instance per thread functor instance, but within each thread functor share the pool between multiple std::list objects.