当前位置: 首页 > news >正文

线程安全的队列

线程安全的队列

unit MyQueue;

interface


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

 

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

type
TsfQueue = class
private
FCapacity: Integer;
FTmpBuff: Pointer;
FBuff: pointer;
FPosition: Integer;
{$IFDEF MULTI_THREAD_QUEUE}
FCS: TCriticalSection; //TRTLCriticalSection;
{$ENDIF}
//\\
FPushIndex: Integer;
FPopIndex: Integer;
procedure Lock();
procedure UnLock();
procedure Inernal_SetCapacity(const Value: Integer);
//\\
procedure setCapacity(const Value: Integer);
function getCapacity: Integer;
function getCurCount: 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;
property Count: Integer read getCurCount;
end;

implementation


{ TsfQueue }

constructor TsfQueue.Create(InitCapacity: Integer);
begin
{$IFDEF MULTI_THREAD_QUEUE}
FCS := TCriticalSection.Create;
// 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}
FCS.Free;
FCS := nil;
//DeleteCriticalSection(FCS);
{$ENDIF}


inherited;
end;

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

procedure TsfQueue.UnLock;
begin
{$IFDEF MULTI_THREAD_QUEUE}
FCS.Leave;
// 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;

function TsfQueue.getCurCount: Integer;
begin
Result := FPushIndex - FPopIndex;
end;

end.

相关文章:

  • 用string存取二进制数据
  • struct{0}二
  • fastText、TextCNN、TextRNN……这里有一套NLP文本分类深度学习方法库供你选择
  • DNGuard V1.0 for Win98, WinMe 的运行库发布
  • [Quest ActiveRoles Management Shell for Active Directory] QADProxyAddress命令相关的bug。
  • cursor:hand 与 cursor:pointer 的区别
  • win7中USB音箱没有声音解决的方法
  • 绘制思维导图的注意事项有哪些?
  • Sql去重语句
  • js算法-归并排序(merge_sort)
  • sessionStorage和localStorage
  • 昼猫笔记 JavaScript -- 面向对象(I)
  • 在Activity中为什么要用managedQuery()
  • uoj#352. 新年的五维几何(概率期望+爆搜)
  • 自己编写的一个Javascript正则表达式对象
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • 【从零开始安装kubernetes-1.7.3】2.flannel、docker以及Harbor的配置以及作用
  • Android单元测试 - 几个重要问题
  • Android组件 - 收藏集 - 掘金
  • AWS实战 - 利用IAM对S3做访问控制
  • FineReport中如何实现自动滚屏效果
  • Java面向对象及其三大特征
  • js写一个简单的选项卡
  • Kibana配置logstash,报表一体化
  • Lsb图片隐写
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 基于HAProxy的高性能缓存服务器nuster
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 数组的操作
  • 体验javascript之美-第五课 匿名函数自执行和闭包是一回事儿吗?
  • 移动端 h5开发相关内容总结(三)
  • 栈实现走出迷宫(C++)
  • [Shell 脚本] 备份网站文件至OSS服务(纯shell脚本无sdk) ...
  • mysql面试题分组并合并列
  • 从如何停掉 Promise 链说起
  • 树莓派用上kodexplorer也能玩成私有网盘
  • 数据库巡检项
  • 组复制官方翻译九、Group Replication Technical Details
  • ​你们这样子,耽误我的工作进度怎么办?
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • (1)STL算法之遍历容器
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (强烈推荐)移动端音视频从零到上手(上)
  • (原創) 未来三学期想要修的课 (日記)
  • (转载)hibernate缓存
  • **Java有哪些悲观锁的实现_乐观锁、悲观锁、Redis分布式锁和Zookeeper分布式锁的实现以及流程原理...
  • .net refrector
  • .net 怎么循环得到数组里的值_关于js数组
  • :=
  • ??如何把JavaScript脚本中的参数传到java代码段中
  • @javax.ws.rs Webservice注解
  • @JsonFormat与@DateTimeFormat注解的使用
  • @RequestMapping用法详解