• 线程安全的队列


    线程安全的队列

    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.

  • 相关阅读:
    ORA-01157:无法标识/锁定数据文件,ORA-01110:表空间丢失错误
    Oracle ORA-01033: ORACLE initialization or shutdown in progress
    mysql delete语句不能用别名
    内存溢出
    中间件-RocketMQ-启动
    rz上传文件乱码
    字节码解读(转~谨用作记录)
    java字节码指令列表(转)
    idea打jar包,提示 jar包中没有主清单属性
    MYSQL 查看最大连接数和修改最大连接数
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/8092564.html
Copyright © 2020-2023  润新知