博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
高速队类实现(线程安全)
阅读量:7105 次
发布时间:2019-06-28

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

hot3.png

测试结果

实现的代码

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://my.oschina.net/u/582827/blog/228277

你可能感兴趣的文章
continue与break的理解
查看>>
我的友情链接
查看>>
date用法示例_shell脚本
查看>>
Ubuntu命令行中文乱码的解决方法
查看>>
Linux 常用命令
查看>>
KVM启动报错qemu-kvm: cannot set up guest memory 'pc.ra
查看>>
软考中高项学员:2016年3月30日作业
查看>>
汇编语言---机器语言
查看>>
Vmware vSphere 5.0系列教程之六 虚拟机及主机配置文件的创建和模板部署
查看>>
python3-字典的一些常用方法
查看>>
Oracle Linux Public Yum Server
查看>>
Linux服务器中木马(肉鸡)手工清除方法(转)
查看>>
用易语言编写的fireman微型浏览器(个人专属)
查看>>
ELK(elasticsearch+logstash+kibana)+redis实现nginx 日志的分析
查看>>
书店管理系统之分页
查看>>
面试题:接口和抽象类的区别
查看>>
Windows Server 2012显示桌面图标
查看>>
Linux下Socket编程
查看>>
字符型图片验证码识别完整过程及Python实现
查看>>
puppet的hash合并函数
查看>>