windows-nt/Source/XPSP1/NT/sdktools/fsdump/lib/bsfixalloc.cpp
2020-09-26 16:20:57 +08:00

145 lines
3 KiB
C++

/*++
Copyright (c) 2000-2001 Microsoft Corporation
Module Name:
bsfixalloc.cpp
Abstract:
Adapted from MFC 6 SR 1 release of fixalloc.cpp. Removed all MFC stuff.
Author:
Stefan R. Steiner [ssteiner] 4-10-2000
Revision History:
--*/
// fixalloc.cpp - implementation of fixed block allocator
#include "stdafx.h"
#include "bsfixalloc.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
// #define new DEBUG_NEW
#endif
/////////////////////////////////////////////////////////////////////////////
// CBsFixedAlloc
CBsFixedAlloc::CBsFixedAlloc(UINT nAllocSize, UINT nBlockSize)
{
ASSERT(nAllocSize >= sizeof(CNode));
ASSERT(nBlockSize > 1);
//wprintf( L"CBsFixedAlloc called, nAllocSize: %d, nBlockSize: %d\n", nAllocSize, nBlockSize );
m_nAllocSize = nAllocSize;
m_nBlockSize = nBlockSize;
m_pNodeFree = NULL;
m_pBlocks = NULL;
InitializeCriticalSection(&m_protect);
}
CBsFixedAlloc::~CBsFixedAlloc()
{
FreeAll();
DeleteCriticalSection(&m_protect);
}
void CBsFixedAlloc::FreeAll()
{
EnterCriticalSection(&m_protect);
m_pBlocks->FreeDataChain();
m_pBlocks = NULL;
m_pNodeFree = NULL;
LeaveCriticalSection(&m_protect);
}
void* CBsFixedAlloc::Alloc()
{
EnterCriticalSection(&m_protect);
if (m_pNodeFree == NULL)
{
CBsPlex* pNewBlock = NULL;
try
{
// add another block
pNewBlock = CBsPlex::Create(m_pBlocks, m_nBlockSize, m_nAllocSize);
//wprintf( L"Alloc getting more core, nAllocSize: %d\n", m_nAllocSize );
}
catch( ... )
{
LeaveCriticalSection(&m_protect);
throw;
}
// chain them into free list
CNode* pNode = (CNode*)pNewBlock->data();
// free in reverse order to make it easier to debug
(BYTE*&)pNode += (m_nAllocSize * m_nBlockSize) - m_nAllocSize;
for (int i = m_nBlockSize-1; i >= 0; i--, (BYTE*&)pNode -= m_nAllocSize)
{
pNode->pNext = m_pNodeFree;
m_pNodeFree = pNode;
}
}
ASSERT(m_pNodeFree != NULL); // we must have something
// remove the first available node from the free list
void* pNode = m_pNodeFree;
m_pNodeFree = m_pNodeFree->pNext;
LeaveCriticalSection(&m_protect);
return pNode;
}
void CBsFixedAlloc::Free(void* p)
{
if (p != NULL)
{
EnterCriticalSection(&m_protect);
// simply return the node to the free list
CNode* pNode = (CNode*)p;
pNode->pNext = m_pNodeFree;
m_pNodeFree = pNode;
LeaveCriticalSection(&m_protect);
}
}
/////////////////////////////////////////////////////////////////////////////
// CBsPlex
// throws E_OUTOFMEMORY
CBsPlex* PASCAL CBsPlex::Create(CBsPlex*& pHead, UINT nMax, UINT cbElement)
{
ASSERT(nMax > 0 && cbElement > 0);
CBsPlex* p = (CBsPlex*) new BYTE[sizeof(CBsPlex) + nMax * cbElement];
if ( p == NULL ) // prefix #118827
throw E_OUTOFMEMORY;
p->pNext = pHead;
pHead = p; // change head (adds in reverse order for simplicity)
return p;
}
void CBsPlex::FreeDataChain() // free this one and links
{
CBsPlex* p = this;
while (p != NULL)
{
BYTE* bytes = (BYTE*) p;
CBsPlex* pNext = p->pNext;
delete[] bytes;
p = pNext;
}
}