博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
内存池
阅读量:5834 次
发布时间:2019-06-18

本文共 5530 字,大约阅读时间需要 18 分钟。

unit untMemoryPool;

interface

{$WARNINGS OFF}
uses
  System.Classes, System.SysUtils, Winapi.Windows;

type

  //Node for block memory
  pMemNode = ^TMemNode;
  TMemNode = record
    Free : Boolean;                 //Is free?
    FSize: Integer;                 //Block Size
    FAddr: Pointer;                 //Address pointer to memory allocated

    FNext: pMemNode;                //Next block pointer

    FPrev: pMemNode;                //Block befor
  end;

  //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;

    procedure InitLock;

    procedure Lock;
    procedure UnLock;
    procedure UnInitLock;

    procedure GetResource(ABlocks: Integer);

    procedure FreeResource;

  public

    constructor Create(const ABlocks: Integer = 10; const ABlockSize: Integer = 1024);
    destructor Destroy; override;

    //Get a free buffer

    function  GetBuffer: Pointer;
    //After use the buffer
    function FreeBuffer(const ABuffer: Pointer): Boolean;

  published

    property BlockSize: Integer read FBlkSize;

  end;

implementation

{ TMemoryPool }

{******************************************************************************}
{*     Procedure: Create                                                      *}
{*       Purpose: constructor of TMemoryPool.                                 *}
{*    Paramaters: ABlocks    --  Block to allocate when create.               *}
{*                ABlockSize --  Each block size.                             *}
{******************************************************************************}
constructor TMemoryPool.Create(const ABlocks, ABlockSize: Integer);
begin
  InitLock;

  FBlkCnt := ABlocks;

  FBlkSize:= ABlockSize;

  FMemHead:= nil;

  FMemTail:= nil;
  FreeHead:= nil;

  GetResource(ABlocks);

end;

{******************************************************************************}

{*     Procedure: Destroy                                                     *}
{*       Purpose: Destrucotr of TMemoryPool.                                  *}
{*    Paramaters: None.                                                       *}
{******************************************************************************}
destructor TMemoryPool.Destroy;
begin
  FreeResource;
  UnInitLock;

  inherited;

end;

{******************************************************************************}

{*      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

        //Swap two blocks's content

        m_pTmp.Free := false;
        m_pTmp.FAddr:= FreeHead.FAddr;
        FreeHead.Free := true;
        FreeHead.FAddr:= ABuffer;

        Result:= true;

        exit;
      end;
      m_pTmp:= m_pTmp.FNext;

      // Not find the block, exit

      if (m_pTmp = FreeHead) then break;
    end;
  finally
    UnLock;
  end;
end;

{******************************************************************************}

{*     Procedure: FreeResource                                                *}
{*       Purpose: Free all memory allocated.                                  *}
{*    Paramaters: None.                                                       *}
{******************************************************************************}
procedure TMemoryPool.FreeResource;
var
  m_pNode: pMemNode;
  m_pTmp : pMemNode;
begin
  m_pNode:= FMemHead;

  try

    while (m_pNode <> nil) do
    begin
      m_pTmp:= m_pNode;
      m_pNode:= m_pNode.FNext;

      FreeMem(m_pTmp.FAddr);

      Dispose(m_pTmp);
    end;
  except
  end;

  FMemHead:= nil;

end;

{******************************************************************************}

{*      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;

  //Get new memory block

  new(m_pNode);
  m_pNode.Free := true;
  m_pNode.FSize:= FBlkSize;
  m_pNode.FPrev:= FMemTail;
  GetMem(m_pNode.FAddr, FBlkSize);
  m_pNode.FNext:= nil;

  //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);

    FMemTail.FNext:= m_pNode;

    FMemTail:= m_pNode;
  end;
end;

procedure TMemoryPool.InitLock;

begin
  InitializeCriticalSection(FLock);
end;

procedure TMemoryPool.Lock;

begin
  EnterCriticalSection(FLock);
end;

procedure TMemoryPool.UnInitLock;

begin
  DeleteCriticalSection(FLock);
end;

procedure TMemoryPool.UnLock;

begin
  LeaveCriticalSection(FLock);
end;

end.

转载地址:http://ptucx.baihongyu.com/

你可能感兴趣的文章
颤抖吧,Css3
查看>>
西门子_TDC_数据耦合小经验
查看>>
接口测试与postman
查看>>
【转载】Nginx + Tomcat 实现反向代理
查看>>
Mac下,如何把Github上的仓库删除掉
查看>>
9.18考试 第一题count题解
查看>>
mac zsh选择到行首的快捷键
查看>>
LINQ To XML的一些方法
查看>>
[LeetCode] Copy List with Random Pointer
查看>>
openstack部署之nova
查看>>
JS组件系列——表格组件神器:bootstrap table
查看>>
存储过程Oracle(一)
查看>>
log4j日志归档
查看>>
Java笔记01——IO流
查看>>
mysql遇见error,1049
查看>>
uva 10034(最小生成树)
查看>>
NYOJ311 完全背包
查看>>
shp格式数据发布服务:postGIS + postgresql + geoserver
查看>>
101. Symmetric Tree - Easy
查看>>
codevs——2822 爱在心中
查看>>