xflminterface IF_Pool : public XF_RefCount
This class represents a pool memory allocator. Applications will get an object of this type by calling the createMemoryPool method on the IF_DbSystem interface. The purpose of a memory pool is to allow for more efficient allocations of memory - as well as freeing of memory. The idea is that within a memory pool object, larger blocks will be allocated from the operating system, and sub-allocations will be done within those blocks. Sub-allocating within a block is made very, very fast, because there is deliberately no mechanism for keeping track of and freeing individual sub-allocations. There is no reclaiming of free space for individual sub-allocations, nor is the allocation algorithm going to search for "best fits". The allocation routines always allocate simply by moving an offset pointer in the most recently allocated block. They never look for available space within a block. Memory pools also provide a minimal (very minimal) ability to "mark" (poolMark) and "free to a mark" (poolReset). The poolMark method remembers the pointer to the current block being used for sub-allocations as well as the offset within that block. The poolReset method frees all blocks that were allocated after that block, and also resets the offset pointer to the "mark" within that block. The effect is to "free" all allocations that occurred after the mark.
Method Summary |
|
void |
poolInit - Initialize the memory pool's block allocation size. |
RCODE |
poolAlloc - Allocate memory from blocks in the memory pool. |
RCODE |
poolCalloc - Allocate memory from blocks in the memory pool. Initialize the allocated memory to zeroes. |
void |
poolFree - Free all allocated memory blocks. |
void |
poolReset - Free all memory allocated after a particular mark. |
void * |
poolMark - Obtain a marker in the pool that can later be used to free back to (see poolReset) |
FLMUINT |
getBlockSize - Return the block allocation size for the pool. |
FLMUINT |
getBytesAllocated - Return the total number of bytes currently allocated in the memory pool. |
Method Detail |
RCODE poolInit(
FLMUINT uiBlockSize);
This is a method sets a memory pool's block allocation size. NOTE: This method does NOT actually allocate any memory. Memory is not allocated until a call to poolAlloc or poolCalloc is made.
Parameters In:
FLMUINT uiBlockSize The minimum size of each allocated block allocated in the pool. Sub-allocations are done within allocated blocks. Note that an application may request memory allocations larger than this block size. This is simply the minimum block size that will be allocated.
Parameters Out: none
Example Code:
RCODE rc;
IF_Pool * pPool = NULL;
char * pszString;
void * pvBinary1;
void * pvBinary2;
void * pvMark;
if (RC_BAD( rc = pDbSystem->createMemoryPool( &pPool)))
{
printf( "Error %08X calling createMemoryPool\n", (unsigned)rc);
goto Exit;
}
// Set minimum block allocation size in pool to 512 bytes.
pPool->poolInit( 512);
// Allocate space for a string buffer.
if (RC_BAD( rc = pPool->poolAlloc( 50, (void **)&pszString)))
{
printf( "Error %08X calling poolAlloc\n", (unsigned)rc);
goto Exit;
}
// Obtain a mark from the pool so we can free everything allocated after this point.
pvMark = pPool->pvMark();
// Allocate space for two binary buffers - initialize them to zeroes.
if (RC_BAD( rc = pPool->poolCalloc( 50, (void **)&pvBinary1)))
{
printf( "Error %08X calling poolCalloc\n", (unsigned)rc);
goto Exit;
}
if (RC_BAD( rc = pPool->poolCalloc( 50, (void **)&pvBinary2)))
{
printf( "Error %08X calling poolCalloc\n", (unsigned)rc);
goto Exit;
}
// Do something with the binary buffers
.
.
// Free back to the mark obtained above. This will essentially free all of the memory allocated since the mark.
// In this case, that means pvBinary1 and pvBinary2. pszString would still be allocated.
pPool->poolReset( pvMark, FALSE);
// Do other stuff with pool
.
.
Exit:
// Note that there is no need to free the individual allocations. When poolFree is called, all allocations made from the
// pool will be freed.
if (pPool)
{
// NOTE: Technically, poolFree does not have to be called here because the Release() method will do it if necessary - if
// there are no other variables referencing the pPool object (which there are not in this example). However, we show it
// by way of example code. The main difference between the Release() and poolFree() methods are that poolFree() only
// frees the memory allocated within the pool. Release() will only do that if this is the last reference to the object. Furthermore,
// Release() will also free the object itself if this is the last reference to it.
pPool->poolFree();
pPool->Release();
}
return( rc);
RCODE poolAlloc(
FLMUINT uiBytesToAllocate,
void ** ppvAllocatedBuffer);
This method allocates memory from a memory pool. The memory is allocated by first allocating blocks from the operating system, and then doing sub-allocations within those blocks.
Parameters In:
FLMUINT uiBytesToAllocate The number of bytes to be allocated.
Parameters Out:
void ** ppvAllocatedBuffer A pointer to the allocated memory is returned here.
Example Code: see poolInit
RCODE poolCalloc(
FLMUINT uiBytesToAllocate,
void ** ppvAllocatedBuffer);
This method allocates memory from a memory pool and initializes it to zeroes. The memory is allocated by first allocating blocks from the operating system, and then doing sub-allocations within those blocks.
Parameters In:
FLMUINT uiBytesToAllocate The number of bytes to be allocated.
Parameters Out:
void ** ppvAllocatedBuffer A pointer to the allocated memory is returned here.
Example Code: see poolInit
void poolFree( void);
This is a method frees all memory blocks that have been allocated within a memory pool.
Parameters In: none
Parameters Out: none
Example Code: see poolInit
void poolReset(
void * pvMark);
This method frees all memory that was allocated in the pool since the mark (pvMark) was obtained. The mark would have been obtained by calling poolMark.
Parameters In:
void * pvMark The marker that indicates the location in the pool where allocations made after it are to be freed.
Parameters Out: none
Example Code: see poolInit.
void * poolMark( void);
This method returns a mark that indicates a location in the pool. This location may be passed into poolReset to free all allocations that occurred since the mark was obtained.
Parameters In: none
Parameters Out: none
Example Code: see poolInit.
FLMUINT getBlockSize( void);
This method returns the minimum block allocation size for the memory pool. It will be whatever value was passed into poolInit.
Parameters In: none
Parameters Out: none
Example Code:
RCODE rc;
IF_Pool * pPool = NULL;
char * pszString;
FLMUINT uiBlockSize;
FLMUINT uiBytesAllocated;
if (RC_BAD( rc = pDbSystem->createMemoryPool( &pPool)))
{
printf( "Error %08X calling createMemoryPool\n", (unsigned)rc);
goto Exit;
}
// Set minimum block allocation size in pool to 512 bytes.
pPool->poolInit( 512);
// Allocate space for a string buffer.
if (RC_BAD( rc = pPool->poolAlloc( 50, (void **)&pszString)))
{
printf( "Error %08X calling poolAlloc\n", (unsigned)rc);
goto Exit;
}
// getBlockSize() should return 512.
uiBlockSize = pPool->getBlockSize();
// getBytesAllocated() should return something >= 50. This is because allocations are rounded up to the next alignment
// boundary. If the alignment boundary is 8 bytes, the call to getBytesAllocated would return 56. If it were 4 bytes,
// it would return 52.
uiBytesAllocated = pPool->getBytesAllocated();
Exit:
if (pPool)
{
// Note that there is no need to explicitly call poolFree - the call to Release() will do it if necessary.
pPool->Release();
}
return( rc);
FLMUINT getBytesAllocated( void);
This method returns the number of bytes allocated within the pool. NOTE: This is NOT the total bytes allocated in blocks in the pool. Rather, it is roughly the number of bytes that have been sub-allocated within blocks by calls to poolAlloc or poolCalloc. We say "roughly" because the allocation sizes requested are always rounded up to the nearest alignment boundary. For example, if the alignment boundary is 8 bytes, and an application asks for 50 bytes, the actual allocation will be 56 bytes. The total number of bytes allocated would be incremented by 56, not 50. Note also that calls to poolReset and poolFree will NOT cause the total number of bytes to be reduced. Hence, the number returned by getBytesAllocated should really be viewed as the total number of bytes ever allocated over the life of the memory pool object.
Parameters In: none
Parameters Out: none
Example Code: see getBlockSize.