|
|
/*==========================================================================
* * 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; } //**********************************************************************
|