Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

379 lines
9.7 KiB

/*==========================================================================
*
* Copyright (C) 1995 - 2000 Microsoft Corporation. All Rights Reserved.
*
* File: FPM.cpp
* Content: fixed size pool manager
*
* History:
* Date By Reason
* ====== == ======
* 12-18-97 aarono Original
* 11-06-98 ejs Add custom handler for Release function
* 04-12-99 jtk Trimmed unused functions and parameters, added size assert
* 11-22-99 jtk Converted to .CPP
* 01-31-2000 jtk Changed to use DNCriticalSections. Added code to check
* for items already being in the pool on Release().
* 04-11-2000 ejs Put ASSERTs back into service. They had been MACRO'd away to nothing
* 11-16/2000 rmt Bug #40587 - DPVOICE: Mixing server needs to use multi-processors
***************************************************************************/
#include "dncmni.h"
#include "fpm.h"
#define DPMEM_ALLOC DNMalloc
#define DPMEM_FREE DNFree
#define ASSERT(X) DNASSERT(X)
//#define CHECK_FOR_DUPLICATE_FPM_RELEASE
//**********************************************************************
// ------------------------------
// FN_BOOL_DUMMY - place-holder function to return a Boolean
//
// Entry: Pointer
//
// Exit: Boolean
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "FN_BOOL_DUMMY"
BOOL FN_BOOL_DUMMY(void *pvItem)
{
return TRUE;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// FN_VOID_DUMMY - place-holder function
//
// Entry: Pointer
//
// Exit: Boolean
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "FN_VOID_DUMMY"
VOID FN_VOID_DUMMY(void *pvItem)
{
return;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// FPM_Get - get an item from the pool
//
// Entry: Pointer to pool
//
// Exit: Pointer to item
// NULL = out of memory
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "FPM_Get"
void * FPM_Get( FPOOL *pPool )
{
void * pvItem;
DNEnterCriticalSection(&pPool->cs);
DNASSERT(pPool->pPoolElements == 0 || !IsBadReadPtr(pPool->pPoolElements, sizeof(PVOID)));
if(!pPool->pPoolElements){
DNLeaveCriticalSection(&pPool->cs);
pvItem = DPMEM_ALLOC(pPool->cbItemSize);
if((pvItem) && !(*pPool->fnBlockInitAlloc)(pvItem) ){
DPMEM_FREE(pvItem);
pvItem=NULL;
}
DNEnterCriticalSection(&pPool->cs);
if(pvItem){
pPool->nAllocated++;
if( pPool->pdwTotalItems )
(*pPool->pdwTotalItems)++;
}
} else {
pvItem=pPool->pPoolElements;
pPool->pPoolElements=*((void **)pvItem);
DNASSERT(pPool->pPoolElements == 0 || !IsBadReadPtr(pPool->pPoolElements, sizeof(PVOID)));
}
if(pvItem){
pPool->nInUse++;
if( pPool->pdwOutstandingItems )
(*pPool->pdwOutstandingItems)++;
DNLeaveCriticalSection(&pPool->cs);
(*pPool->fnBlockInit)(pvItem);
}
else {
DNLeaveCriticalSection(&pPool->cs);
}
return pvItem;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// FPM_Release - return element to pool
//
// Entry: Pointer to pool
// Pointer to element
//
// Exit: Nothing
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "FPM_Release"
void FPM_Release( FPOOL *pPool, void *pvItem)
{
(*pPool->fnBlockRelease)(pvItem);
DNEnterCriticalSection(&pPool->cs);
#if defined(CHECK_FOR_DUPLICATE_FPM_RELEASE) && defined(DEBUG)
{
void *pTemp;
pTemp = pPool->pPoolElements;
while ( pTemp != NULL )
{
DNASSERT( pTemp != pvItem );
pTemp = *((void**)pTemp);
}
}
#endif // CHECK_FOR_DUPLICATE_FPM_RELEASE
pPool->nInUse--;
if( pPool->pdwOutstandingItems )
(*pPool->pdwOutstandingItems)--;
#ifdef NO_POOLS
(*pPool->fnBlockFini)(pvItem);
DPMEM_FREE(pvItem);
pPool->nAllocated--;
#else
*((void**)pvItem)=pPool->pPoolElements;
pPool->pPoolElements=pvItem;
#endif
DNASSERT(pPool->pPoolElements == 0 || !IsBadReadPtr(pPool->pPoolElements, sizeof(PVOID)));
DNLeaveCriticalSection(&pPool->cs);
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// FPM_Fini - destroy pool
//
// Entry: Pointer to pool
//
// Exit: Nothing
//
// Note: This function frees the pool memory, the pointer passed in is
// then invalid!
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "FPM_Fini"
VOID FPM_Fini( FPOOL *pPool, BOOL fAssertOnLeak )
{
FPM_Deinitialize( pPool, fAssertOnLeak );
DPMEM_FREE( pPool );
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// FPM_Deinitialize - deinitialize pool
//
// Entry: Pointer to pool
// Boolean to control if it should assert on a leak
//
// Exit: Nothing
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "FPM_Deinitialize"
VOID FPM_Deinitialize( FPOOL *pPool, BOOL fAssertOnLeak )
{
void *pvItem;
while(pPool->pPoolElements){
pvItem = pPool->pPoolElements;
pPool->pPoolElements=*((void **)pvItem);
DNASSERT(pPool->pPoolElements == 0 || !IsBadReadPtr(pPool->pPoolElements, sizeof(PVOID)));
(*pPool->fnBlockFini)(pvItem);
DPMEM_FREE(pvItem);
pPool->nAllocated--;
if( pPool->pdwOutstandingItems )
(*pPool->pdwOutstandingItems)--;
}
if( fAssertOnLeak )
{
if(pPool->nAllocated){
ASSERT(0);
}
}
DNDeleteCriticalSection(&pPool->cs);
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// FPM_Create - Allocate a new pool
//
// Entry: Size of pool element
// Pointer to function for initializing element on alloc
// Pointer to function for initializing element on get
// Pointer to function for deinitializing element on release
// Pointer to function for deinitializing element on free
//
// Exit: Pointer to new pool
// NULL = out of memory
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "FPM_Create"
FPOOL *FPM_Create( unsigned int size,
FN_BLOCKINITALLOC fnBlockInitAlloc,
FN_BLOCKINIT fnBlockInit,
FN_BLOCKRELEASE fnBlockRelease,
FN_BLOCKFINI fnBlockFini,
DWORD *pdwOutstandingItems,
DWORD *pdwTotalItems
)
{
LPFPOOL pPool;
pPool=static_cast<FPOOL*>( DPMEM_ALLOC( sizeof( *pPool ) ) );
if ( pPool == NULL )
{
return NULL;
}
if ( FPM_Initialize( pPool, // pointer to fixed pool
size, // size of pool element
fnBlockInitAlloc, // pointer to function for initializing element on alloc
fnBlockInit, // pointer to function for initializing element on get
fnBlockRelease, // pointer to function for deinitializing element on release
fnBlockFini, // pointer to function for deinitializing element on free
pdwOutstandingItems,
pdwTotalItems
) == FALSE )
{
DPMEM_FREE( pPool );
pPool = NULL;
}
return pPool;
}
//**********************************************************************
//**********************************************************************
// ------------------------------
// FPM_Initialize - initialize an instance of a pool
//
// Entry: Pointer to pool
// Size of pool element
// Pointer to function for initializing element on alloc
// Pointer to function for initializing element on get
// Pointer to function for deinitializing element on release
// Pointer to function for deinitializing element on free
//
// Exit: Boolean indicating success
// TRUE = success
// FALSE = failure
// ------------------------------
#undef DPF_MODNAME
#define DPF_MODNAME "FPM_Initialize"
BOOL FPM_Initialize( LPFPOOL pPool, // pointer to pool to initialize
DWORD dwElementSize, // size of blocks in pool
FN_BLOCKINITALLOC fnBlockInitAlloc, // fn called for each new alloc
FN_BLOCKINIT fnBlockInit, // fn called each time block used
FN_BLOCKRELEASE fnBlockRelease, // fn called each time block released
FN_BLOCKFINI fnBlockFini, // fn called before releasing mem
DWORD *pdwOutstandingItems,
DWORD *pdwTotalItems
)
{
BOOL fReturn;
fReturn = TRUE;
if ( DNInitializeCriticalSection(&pPool->cs) == FALSE )
{
fReturn = FALSE;
goto Exit;
}
DebugSetCriticalSectionRecursionCount( &pPool->cs, 0 );
pPool->pPoolElements = NULL;
pPool->nAllocated = 0;
pPool->nInUse = 0;
pPool->pdwOutstandingItems = pdwOutstandingItems;
pPool->pdwTotalItems = pdwTotalItems;
if( pPool->pdwOutstandingItems )
*(pPool->pdwOutstandingItems) = 0;
if( pPool->pdwTotalItems )
*(pPool->pdwTotalItems) = 0;
if(fnBlockInitAlloc){
pPool->fnBlockInitAlloc = fnBlockInitAlloc;
} else {
pPool->fnBlockInitAlloc = FN_BOOL_DUMMY;
}
if(fnBlockInit){
pPool->fnBlockInit = fnBlockInit;
} else {
pPool->fnBlockInit = FN_VOID_DUMMY;
}
if(fnBlockRelease){
pPool->fnBlockRelease = fnBlockRelease;
} else {
pPool->fnBlockRelease = FN_VOID_DUMMY;
}
if(fnBlockFini){
pPool->fnBlockFini = fnBlockFini;
} else {
pPool->fnBlockFini = FN_VOID_DUMMY;
}
pPool->Get = FPM_Get;
pPool->Release= FPM_Release;
pPool->Fini = FPM_Fini;
// FPM reuses the item memory as a linked list when not in use,
// make sure the items are large enough
ASSERT( dwElementSize >= sizeof( void* ) );
pPool->cbItemSize = dwElementSize;
Exit:
return fReturn;
}
//**********************************************************************