一个队列类的实现 转

一个队列类的实现(比delphi自带的速度快70倍)

测试结果

实现的代码

unit sfContnrs;

interface

{$DEFINE MULTI_THREAD_QUEUE} //线程安全版本,如果不需要线程安全,请注释掉此行代码

{$IFDEF MULTI_THREAD_QUEUE}
uses
    Windows;
{$ENDIF}

type
  TsfQueue=class
  private
    FCapacity:Integer;
    FTmpBuff:Pointer;
    FBuff:Pointer;
    FPosition:Integer;
  {$IFDEF MULTI_THREAD_QUEUE}
    FCS:TRTLCriticalSection;
  {$ENDIF}
    //\\
    FPushIndex:Integer;
    FPopIndex:Integer;

procedure Lock();
    procedure UnLock();
    procedure Inernal_SetCapacity(const Value:Integer);
    //\\
    procedure setCapacity(const Value: Integer);
    function getCapacity: Integer;
  public
    constructor Create(InitCapacity: Integer=1024);
    destructor  Destroy();override;
    //\\
    function Push(AItem: Pointer): Pointer;
    function Pop(): Pointer;
  public
    property Capacity:Integer read getCapacity write setCapacity;
  end;

implementation

{ TsfQueue }

constructor TsfQueue.Create(InitCapacity:Integer);
begin
  {$IFDEF MULTI_THREAD_QUEUE}
     InitializeCriticalSection(FCS);
  {$ENDIF}

if InitCapacity < 1024 then InitCapacity := 1024;

Inernal_SetCapacity(InitCapacity);

end;

destructor TsfQueue.Destroy;
begin
  FreeMem(FBuff);
  if FTmpBuff <> nil then
    FreeMem(FTmpBuff);
  //\\
  {$IFDEF MULTI_THREAD_QUEUE}
     DeleteCriticalSection(FCS);
  {$ENDIF}

inherited;
end;

procedure TsfQueue.Lock;
begin
  {$IFDEF MULTI_THREAD_QUEUE}
     EnterCriticalSection(FCS);
  {$ENDIF}
end;

procedure TsfQueue.UnLock;
begin
  {$IFDEF MULTI_THREAD_QUEUE}
      LeaveCriticalSection(FCS);
  {$ENDIF}
end;

procedure TsfQueue.Inernal_SetCapacity(const Value: Integer);
var
  PageCount,ASize:Integer;
begin
    if Value > FCapacity then
    begin
      if FTmpBuff <> nil then
        FreeMem(FTmpBuff);

//扩容
      ASize := Value * 4;//计算出所需要的字节数量
      Pagecount := ASize div 4096;
      if (ASize mod 4096) > 0 then Inc(PageCount);

//转移数据
      GetMem(FTmpBuff,PageCount * 4096);
      FillChar(FTmpBuff^,PageCount * 4096,#0);

if FBuff <> nil then
      begin
        Move(FBuff^,FTmpBuff^,FCapacity * 4);
        FreeMem(FBuff);
      end;

FBuff := FTmpBuff;

//计算新的容量
      FCapacity := (PageCount * 4096) div 4;

if FCapacity >= 2048 then
      begin
         //FTmpBuff 分配用于Pop时候,移动内存用
         GetMem(FTmpBuff,PageCount * 4096);
      end
      else
        FTmpBuff := nil;
    end;
end;

function TsfQueue.Pop: Pointer;
  procedure AdjuestMem();
  var
    pSrc:PInteger;
    pTmp:Pointer;
  begin
    FillChar(FTmpBuff^,FCapacity * 4,#0);
    pSrc := PInteger(FBuff);
    Inc(pSrc,FPopIndex);
    Move(pSrc^,FTmpBuff^,(FCapacity - FPopIndex) * 4);
    //\\
    //交换指针
    pTmp    := FBuff;
    FBuff   := FTmpBuff;
    FTmpBuff := pTmp;
    //\\
  end;

const
    _MoveRange_ = 2048;

var
  P:PInteger;
begin
  Lock();
  try
    Result := nil;
    if (FPopIndex = FPushIndex) then
      Exit;
    P := PInteger(FBuff);
    Inc(P,FPopIndex);
    Result := Pointer(P^);
    Inc(FPopIndex);
    //队列底部空余内存达到 8192 整体搬迁
    if FPopIndex = _MoveRange_ then
    begin
      AdjuestMem();
      FPopIndex := 0;
      Dec(FPushIndex,_MoveRange_);
    end;
  finally
    UnLock();
  end;
end;

function TsfQueue.Push(AItem: Pointer): Pointer;
var
  P:PInteger;
begin
  Lock();
  try
    P := PInteger(FBuff);
    Inc(P,FPushIndex);
    P^ := Integer(AItem);
    Inc(FPushIndex);
    if FPushIndex >= FCapacity then
    begin
      //扩容加 1024 个位置
      Inernal_SetCapacity(FCapacity + 1024);
    end;
  finally
    UnLock();
  end;
end;

procedure TsfQueue.setCapacity(const Value: Integer);
begin
  Lock();
  try
    Inernal_SetCapacity(Value);
  finally
    UnLock();
  end;
end;

function TsfQueue.getCapacity: Integer;
begin
  Lock();
  try
    Result := Self.FCapacity;
  finally
    UnLock();
  end;
end;

end.

//测试函数

procedure TfrmMain.btnQueueClick(Sender: TObject);
var
  A:TsfQueue; //优化后的高速队类实现(线程安全)
  B:TQueue;
  Index:Integer;
begin
  A := TsfQueue.Create();
  B := TQueue.Create();
  SW.Start();
  for Index := 1 to 10000 * 2 do
  begin
    b.Push(0);
  end;
  for Index := 1 to 10000 * 2 do
  begin
    b.Pop();
  end;

SW.Stop();

showMessage(IntToStr(SW.ElapsedMiliseconds));

end;

原文地址:https://www.cnblogs.com/maweiwei/p/12208178.html

时间: 2024-08-04 18:56:01

一个队列类的实现 转的相关文章

实现一个队列类,该类用两个栈来实现

1 /* 2 * 实现一个队列类,该类用两个栈来实现 3 * 队列和栈的主要区别是,队列是先进先出,就像我们在食堂[派对打饭一样,先到先打 4 * 栈是先进后出,就像枪里面的子弹,最先进去的把压到了最低 5 * 因此我们只要修改一下peek()和pop(),以相反顺序执行操作,我们可以利用第二个栈来反转元素的次序 6 * 这种做法是可行的,但是却不是效率最高的,元素的移来移去,重复移动,毫无必要. 7 * 所以在这里我们可以延迟元素的移动,就让元素一直留在第二个栈中,只有必须反转元素次序时才移动

一个队列类的实现(比delphi自带的速度快70倍)(线程安全版本)

unit sfContnrs; interface {$DEFINE MULTI_THREAD_QUEUE} //线程安全版本,如果不需要线程安全,请注释掉此行代码 {$IFDEF MULTI_THREAD_QUEUE}uses    Windows;{$ENDIF} type  TsfQueue=class  private    FCapacity:Integer;    FTmpBuff:Pointer;    FBuff:Pointer;    FPosition:Integer;  {

C++学习笔记50:队列类模板

队列是只能向一端添加元素,从另一端删除元素的线性群体 循环队列 在想象中将数组弯曲成环形,元素出队时,后继元素不移动,每当队尾达到数组最后一个元素时,便再回到数组开头. 队列类模板 //Queue.h #ifndef QUEUE_H #define QUEUE_H #include <cassert> //类模板的定义 template <class T, int SIZE = 50> class Queue { private: int front, rear, count; T

固定尺寸内存块的缓冲队列类及C++实现源代码

-------------------------------------------------------------------------------- 标题: 固定尺寸内存块的缓冲队列类及实现源代码 作者: 叶飞虎 日期: 2014.10.21 -------------------------------------------------------------------------------- 在一般的线性操作应用中(如: 接收缓冲区), 可能须要频繁分配和释放内存块, 频繁

WorldWind源码剖析系列:下载队列类DownloadQueue

下载队列类DownloadQueue代表具有优先级的下载队列,该类的存储下载请求的数组链表专门按一定的优先级来存储下载请求的.该类的类图如下. 下载队列类DownloadQueue各个字段的含义说明如下: public static int MaxQueueLength = 200;//最大队列长度 public static int MaxConcurrentDownloads = 2;//最大当前下载长度 private ArrayList m_requests = new ArrayLis

队列类模板

队列类模板 队列是只能向一端添加元素,从另一端删除元素的线性群体 队列的基本状态 队空 队满 一般状态 队空 队列中没有元素(以数组容纳的队列为例) 队满 队列中元素个数达到上限(以数组容纳的队列为例) 一般状态 队列中有元素,但未达到队满状态(以数组容纳的队列为例) 循环队列 在想象中将数组弯曲成环形,元素出队时,后继元素不移动,每当队尾达到数组最后一个元素时,便再回到数组开头. //Queue.h #ifndef QUEUE_H #define QUEUE_H #include <casse

【数据结构】两个栈实现一个队列

今天面试的时候被问到了,如何用2个栈实现一个队列的功能. 那时候第一时间的想法是: 用2个栈实现,入队列时,可以直接push进其中的一个栈 出队列时,则需要把入队列的那个栈不断的pop到另一个栈中,以实现原先栈的顺序逆序,从而实现队列的先进先出. 可能文字比较拗口,具体的实现可通过下图表示: 注:图片转自http://www.cnblogs.com/wanghui9072229/archive/2011/11/22/2259391.html 很明显,这是一个可行性挺高的方法.但是,出队列的最后一

用两个栈实现一个队列——7

用两个栈实现一个队列,并实现两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能. 栈的特点是"先进后出,后进先出",而队列的特点是"先进先出,后进后出",因此可以想到只用一个栈是无法完成的,所以会需要两个栈,先将输入的数据都依次放入一个栈stack1中,但是先进去的数据会被压在栈底,而栈底的数据是需要最先被取出的,可画图如下: 当要完成在队列头部删除结点这就要用到另外一个栈stack2了,可以将第一个栈stack

固定尺寸内存块的缓冲队列类及C++实现源码

-------------------------------------------------------------------------------- 标题: 固定尺寸内存块的缓冲队列类及实现源码 作者: 叶飞虎 日期: 2014.10.21 -------------------------------------------------------------------------------- 在一般的线性操作应用中(如: 接收缓冲区), 可能需要频繁分配和释放内存块, 频繁操