//Memory pool class
TMemoryPool = class(TObject)
private
FBlkSize: Integer; //Block size
FBlkCnt : Integer; //Memory bock count each time allocate
FMemHead: pMemNode; //Memory list
FreeHead: pMemNode; //Free memory start position
FMemTail: pMemNode; //Tail of current memory
FLock : TRTLCriticalSection;
{******************************************************************************}
{* Function: FreeBuffer *}
{* Purpose: Free memory buffer allocated. *}
{* Paramaters: ABuffer -- Buffer address to free. *}
{* Return: True -- Block is free. *}
{* False -- Free error or the block not found. *}
{******************************************************************************}
function TMemoryPool.FreeBuffer(const ABuffer: Pointer): Boolean;
var
m_pTmp: pMemNode;
begin
Result:= false;
Lock;
try
if (nil = ABuffer) then exit;
m_pTmp:= FMemHead;
while (m_pTmp <> nil) do
begin
if (ABuffer = m_pTmp.FAddr) then
begin
if FreeHead = nil then
FreeHead:= FMemTail
else
FreeHead:= FreeHead.FPrev; //Move free head back
{******************************************************************************}
{* Function: GetBuffer *}
{* Purpose: Get a memroy block buffer. *}
{* Paramaters: None. *}
{* Return: Pointer -- A pointer pointer to buffer. *}
{******************************************************************************}
function TMemoryPool.GetBuffer: Pointer;
begin
Lock;
try
//If there's no free memroy, allocate new memory
if (FreeHead = nil) then
GetResource(FBlkCnt);
//Return free memory head address
Result:= FreeHead.FAddr;
//Mark the block is not free
FreeHead.Free:= false;
//Move free head pointer forward
FreeHead:= FreeHead.FNext;
finally
UnLock;
end;
end;
{******************************************************************************}
{* Procedure: GetResource *}
{* Purpose: Allocate memroy. *}
{* Paramaters: ABlocks -- How many blocks to allocate. *}
{******************************************************************************}
procedure TMemoryPool.GetResource(ABlocks: Integer);
var
m_pNode: pMemNode;
m_iTmp : Integer;
begin
if (ABlocks <= 0) or (FBlkSize <= 0) then exit;
//If the memroy block list is empty, assign head
if FMemHead = nil then
begin
FMemHead:= m_pNode;
FMemTail:= FMemHead;
FreeHead:= FMemHead;
end
else begin
FMemTail.FNext:= m_pNode;
FMemTail:= m_pNode;
end;
if (FreeHead = nil) then
FreeHead:= m_pNode;
for m_iTmp:= 1 to ABlocks - 1 do
begin
new(m_pNode);
m_pNode.Free := true;
m_pNode.FSize:= FBlkSize;
m_pNode.FNext:= nil;
m_pNode.FPrev:= FMemTail;
GetMem(m_pNode.FAddr, FBlkSize);