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.

Member Summary

Member Functions: allocated, available, blockSize, get, release

Types

Bucket

typedef Block * Bucket;

BucketVec

typedef std::vector < Bucket > BucketVec;

MutexType

typedef M MutexType;

ScopedLock

typedef typename M::ScopedLock ScopedLock;

Constructors

FastMemoryPool inline

FastMemoryPool(
    std::size_t blocksPerBucket = 1000,
    std::size_t bucketPreAlloc = 10,
    std::size_t maxAlloc = 0
);

Creates the FastMemoryPool.

The size of a block is inferred from the type size. Number of blocks per bucket, pre-allocated bucket pointer storage and maximum allowed total size of the pool can be customized by overriding default parameter value:

  • blocksPerBucket specifies how many blocks each bucket contains defaults to POCO_FAST_MEMORY_POOL_PREALLOC

  • bucketPreAlloc specifies how much space for bucket pointers (buckets themselves are not pre-allocated) will be pre-alocated.

  • maxAlloc specifies maximum allowed total pool size in bytes.

Destructor

~FastMemoryPool inline

~FastMemoryPool();

Destroys the FastMemoryPool and releases all memory. Any memory taken from, but not returned to, the pool becomes invalid.

Member Functions

allocated inline

std::size_t allocated() const;

Returns the total amount of memory allocated, in bytes.

available inline

std::size_t available() const;

Returns currently available amount of memory in bytes.

blockSize inline

std::size_t blockSize() const;

Returns the block size in bytes.

get inline

void * get();

Returns pointer to the next available memory block. If the pool is exhausted, it will be resized by allocating a new bucket.

release inline

template < typename P > void release(
    P * ptr
);

Recycles the released memory by initializing it for internal use and setting it as next available block; previously next block becomes this block's next. Releasing of null pointers is silently ignored. Destructor is called for the returned pointer.