POOLMEM.C


#include "poolmem.h"



// Tree Memory Allocation structure.


typedef struct _POOLMEMORYBLOCK POOLMEMORYBLOCK, *PPOOLMEMORYBLOCK;

struct _POOLMEMORYBLOCK {
DWORD Index;
DWORD Size;
PPOOLMEMORYBLOCK NextBlock;
PPOOLMEMORYBLOCK PrevBlock;
PBYTE RawMemory;
};

typedef struct _POOLHEADER {
PPOOLMEMORYBLOCK PoolHead;
HANDLE Heap;
} POOLHEADER, *PPOOLHEADER;


BOOL
PoolMemAddMemory (
IN POOLHANDLE Handle,
IN DWORD Size
)
{
PBYTE allocedMemory;
PPOOLMEMORYBLOCK newBlock;
PPOOLHEADER poolHeader = (PPOOLHEADER) Handle;
DWORD sizeNeeded;

assert(poolHeader != NULL);

//
// Determine size needed and attempt to allocate memory.
//
if (Size + sizeof(POOLMEMORYBLOCK) > POOLMEMORYBLOCKSIZE) {
sizeNeeded = Size + sizeof(POOLMEMORYBLOCK);
}
else {
sizeNeeded = POOLMEMORYBLOCKSIZE;
}

allocedMemory = HeapAlloc(poolHeader -> Heap,0,sizeNeeded);

if (allocedMemory) {

//
// Use the beginning of the alloc'ed block as the poolblock structure.
//
newBlock = (PPOOLMEMORYBLOCK) allocedMemory;
newBlock -> Size = sizeNeeded - sizeof(POOLMEMORYBLOCK);
newBlock -> RawMemory = allocedMemory + sizeof(POOLMEMORYBLOCK);
newBlock -> Index = 0;

//
// Link the block into the list.
//
if (poolHeader -> PoolHead) {
poolHeader -> PoolHead -> PrevBlock = newBlock;
}
newBlock -> NextBlock = poolHeader -> PoolHead;
newBlock -> PrevBlock = NULL;
poolHeader -> PoolHead = newBlock;


}
//
// Assuming allocedMemory is non-NULL, we have succeeded.
//
return allocedMemory != NULL;
}


POOLHANDLE
WINAPI
PoolMemInitPool (
)
{
BOOL ableToAddMemory;
PPOOLHEADER header = NULL;
HANDLE procHeap;


procHeap = GetProcessHeap();
//
// Allocate the header of this pool.
//
header = HeapAlloc(procHeap,0,sizeof(POOLHEADER));

if (header) {

//
// Allocation was successful. Now, initialize the pool.
//
header -> PoolHead = NULL;
header -> Heap = procHeap;

//
// Actually add some memory to the pool.
//
ableToAddMemory = PoolMemAddMemory(header,0);

if (!ableToAddMemory) {
//
// Unable to add memory to the pool.
//
HeapFree(header -> Heap,0,header);
header = NULL;
}

}
return (POOLHANDLE) header;
}


VOID
WINAPI
PoolMemDestroyPool (
POOLHANDLE Handle
)
{
PPOOLMEMORYBLOCK nextBlock;
PPOOLMEMORYBLOCK blockToFree;
PPOOLHEADER poolHeader;

assert(Handle != NULL);

poolHeader = (PPOOLHEADER) Handle;

//
// Walk the list, freeing as we go.
//
blockToFree = poolHeader -> PoolHead;

while (blockToFree != NULL) {

nextBlock = blockToFree->NextBlock;
HeapFree(poolHeader -> Heap,0,blockToFree);
blockToFree = nextBlock;
}

//
// Also, deallocate the poolheader itself.
//
HeapFree(poolHeader -> Heap,0,poolHeader);

}

PVOID
WINAPI
PoolMemGetAlignedMemory (
IN POOLHANDLE Handle,
IN DWORD Size,
IN DWORD AlignSize
)

{
BOOL haveEnoughMemory = TRUE;
PVOID rMemory = NULL;
PPOOLHEADER poolHeader = (PPOOLHEADER) Handle;
PPOOLMEMORYBLOCK currentBlock;
DWORD sizeNeeded;
DWORD padLength;

assert(poolHeader != NULL);

currentBlock = poolHeader -> PoolHead;

// Determine if more memory is needed, attempt to add if needed.
sizeNeeded = Size;

if (currentBlock -> Size - currentBlock -> Index < sizeNeeded + AlignSize) {

haveEnoughMemory = PoolMemAddMemory(poolHeader,sizeNeeded + AlignSize);
currentBlock = poolHeader -> PoolHead;
}

// If there is enough memory available, return it.
if (haveEnoughMemory) {
if (AlignSize) {

padLength = (DWORD) currentBlock + sizeof(POOLMEMORYBLOCK)
+ currentBlock -> Index;
currentBlock -> Index += (AlignSize - (padLength % AlignSize)) % AlignSize;

}


//Now, get the address of the memory to return.
rMemory = (PVOID)
&(currentBlock->RawMemory[currentBlock -> Index]);

currentBlock->Index += sizeNeeded;
}

return rMemory;
}