Poco

template < typename T, typename M = FastMutex >

class FastMemoryPool

Library: Foundation
Package: Core
Header: Poco/MemoryPool.h

Description

FastMemoryPool is a class for pooling fixed-size blocks of memory.

The main purpose of this class is to speed-up memory allocations, as well as to reduce memory fragmentation in situations where the same blocks are allocated all over again, such as in server applications. It differs from the MemoryPool in the way the block size is determined - it is inferred form the held type size and applied statically. It is also, as its name implies, faster than Poco::MemoryPool. It is likely to be significantly faster than the runtime platform generic memory allocation functionality as well, but it has certain limitations (aside from only giving blocks of fixed size) - see more below.

An object using memory from the pool should be created using in-place new operator; once released back to the pool, its destructor will be called by the pool. The returned pointer must be a valid pointer to the type for which it was obtained.

Example use:

using std::vector;
using std:string;
using std::to_string;
using Poco::FastMemoryPool;

int blocks = 10;
FastMemoryPool<int> fastIntPool(blocks);
FastMemoryPool<string> fastStringPool(blocks);

vector<int*> intVec(blocks, 0);
vector<string*> strVec(blocks);

for (int i = 0; i < blocks; ++i)
{
  intVec[i] = new (fastIntPool.get()) int(i);
  strVec[i] = new (fastStringPool.get()) string(to_string(i));
}

for (int i = 0; i < blocks; ++i)
{
  fastIntPool.release(intVec[i]);
  fastStringPool.release(strVec[i]);
}

Pool keeps memory blocks in "buckets". A bucket is an array of blocks; it is always allocated with a single new[], and its blocks are initialized at creation time. Whenever the current capacity of the pool is reached, a new bucket is allocated and its blocks initialized for internal use. If the new bucket allocation would exceed allowed maximum size, std::bad_alloc() exception is thrown, with object itself left intact.

Pool internally keeps track of available blocks through a linked-list and utilizes unused memory blocks for that purpose. This means that, for types smaller than pointer the size of a block will be greater than the size of the type. The implications are following:

  • FastMemoryPool can not be used for arrays of types smaller than pointer

  • if FastMemoryPool is used to store variable-size arrays, it must not have multiple buckets; the way to achieve this is by specifying proper argument values at construction.

Neither of the above are primarily intended or recommended modes of use. It is recommended to use a FastMemoryPool for creation of many objects of the same type. Furthermore, it is perfectly fine to have arrays or STL containers of pointers to objects created in blocks of memory obtained from the FastMemoryPool.

Before a block is given to the user, it is removed from the list; when a block is returned to the pool, it is re-inserted in the list. Pool will return held memory to the system at destruction, and will not leak memory after destruction; this means that after pool destruction, any memory that was taken, but not returned to it becomes invalid.

FastMemoryPool is thread safe; it uses Poco::FastMutex by default, but other mutexes can be specified through the template parameter, if needed. Poco::NullMutex can be specified as template parameter to avoid locking and improve speed in single-threaded scenarios.