NT4/private/windows/spooler/spllib/memblock.cxx
2020-09-30 17:12:29 +02:00

197 lines
3.0 KiB
C++

/*++
Copyright (c) 1994 Microsoft Corporation
All rights reserved.
Module Name:
memblock.cxx
Abstract:
Memory allocater for chunks of read only memory.
Author:
Albert Ting (AlbertT) 30-Aug-1994
Revision History:
--*/
#include "spllibp.hxx"
#pragma hdrstop
TMemBlock::
TMemBlock(
UINT uGranularity,
DWORD fdwFlags) :
_uGranularity(uGranularity),
_pIterBlock(NULL),
_pIterData(NULL),
_dwCount(0),
_fdwFlags(fdwFlags)
{
DWORD dwSize = dwBlockHeaderSize() + _uGranularity;
if( _fdwFlags & kFlagGlobalNew ){
_pLast = (PBLOCK) new BYTE[dwSize];
} else {
_pLast = (PBLOCK)AllocMem( dwSize );
}
_pFirst = _pLast;
if (_pFirst) {
_pFirst->pNext = NULL;
_dwNextFree = dwBlockHeaderSize();
}
}
TMemBlock::
~TMemBlock()
{
PBLOCK pBlock;
PBLOCK pBlockNext;
for (pBlock = _pFirst; pBlock; pBlock = pBlockNext) {
pBlockNext = pBlock;
if( _fdwFlags & kFlagGlobalNew ){
delete [] (PBYTE)pBlock;
} else {
//
// Our Delete must mirror the New.
//
FreeMem(pBlock);
}
}
}
PVOID
TMemBlock::
pvAlloc(
DWORD dwSize
)
{
PDATA pData;
//
// If out of memory, fail.
//
if (!_pFirst) {
goto FailOOM;
}
dwSize = Align(dwSize + dwDataHeaderSize());
SPLASSERT(dwSize <= _uGranularity);
if (dwSize + _dwNextFree > _uGranularity) {
DWORD dwSize = dwBlockHeaderSize() + _uGranularity;
//
// Must allocate a new block
//
if( _fdwFlags & kFlagGlobalNew ){
_pLast->pNext = (PBLOCK) new BYTE[dwSize];
} else {
_pLast->pNext = (PBLOCK)AllocMem( dwSize );
}
if (!_pLast->pNext) {
goto FailOOM;
}
_pLast = _pLast->pNext;
_pLast->pNext = NULL;
_dwNextFree = dwBlockHeaderSize();
}
//
// We have enough space in this link now;
// update everything.
//
pData = (PDATA)((PBYTE)_pLast + _dwNextFree);
pData->dwSize = dwSize;
_dwNextFree += dwSize;
_pLast->pDataLast = pData;
_dwCount++;
return pvDataToUser(pData);
FailOOM:
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
PVOID
TMemBlock::
pvFirst(
VOID
)
{
if (!_dwCount) {
return NULL;
}
_pIterBlock = _pFirst;
_pIterData = pBlockToData(_pIterBlock);
_dwIterCount = 0;
return pvDataToUser(_pIterData);
}
PVOID
TMemBlock::
pvIter(
VOID
)
{
_dwIterCount++;
if (_dwIterCount == _dwCount)
return NULL;
//
// Go to next block. If we're at the last pData, go to next block.
//
if (_pIterData == _pIterBlock->pDataLast) {
_pIterBlock = _pIterBlock->pNext;
_pIterData = pBlockToData(_pIterBlock);
} else {
_pIterData = pDataNext(_pIterData);
}
return pvDataToUser(_pIterData);
}
UINT
TMemBlock::
uSize(
PVOID pvUser
) const
{
return pvUserToData(pvUser)->dwSize;
}