145 lines
3 KiB
C++
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;
|
||
|
}
|
||
|
}
|
||
|
|