• 一个简易无锁池


    一个简易 无锁池

    1.所有读写无等待,不需要判断条件直接读写(除自动扩充容量时),效率是一般带锁或带条件判断池的两倍以上。

    2.预先开辟2的幂大小容量,可自增,每次翻倍

    3.仅提供思路,工程应用可靠性还不确定。

    // 无锁池
    // hezihang @cnblogs.com
    
    // 20160228 增加代引用计数器内存块的池,增加编译指令POOLGROW功能,可打开关闭池的自动翻倍增长功能
    // 20160225 修正Grow中FWritePtr没有增长Bug
    // 20140609 增加Grow临界区,减少等待时间
    // 20140608 修正可能存在同时Grow的Bug
    
    unit Iocp.AtomPool;
    
    interface
    
    { .$DEFINE POOLGROW }
    
    Uses
      System.SysUtils,
      System.SyncObjs;
    
    Type
      Int32 = Integer;
      UInt32 = Cardinal;
    
      TAtomPoolAbstract = class
      private
        FWritePtr: Int32;
        FReadPtr: Int32;
        FHighBound: UInt32;
        FData: array of Pointer;
    {$IFDEF POOLGROW}
        FCs: TCriticalSection;
        FLock: Int32;
        procedure CheckGrow; inline;
        procedure Grow; inline;
    {$ENDIF}
      Protected
        function AllocItemResource: Pointer; virtual; abstract;
        procedure FreeItemResource(Item: Pointer); virtual; abstract;
        function GetCapacity: UInt32;
        procedure FreeResources;
      Public
        procedure AllocResources;
        function Get: Pointer;
        procedure Put(Item: Pointer);
        Constructor Create(Capacity: UInt32); Virtual;
        Destructor Destroy; Override;
        property Capacity: UInt32 read GetCapacity;
      End;
    
      TAtomPoolMem4K = class(TAtomPoolAbstract)
        function AllocItemResource: Pointer; override;
        procedure FreeItemResource(Item: Pointer); override;
      end;
    
      // 内存块带引用计数器的池,池容量恒定不能增长
      TAtomMemoryPoolRef = class
      private
        FMemory: PByteArray;
        FWritePtr: Int32;
        FReadPtr: Int32;
        FHighBound: UInt32;
        FMemSize: UInt32;
        FData: array of Pointer;
        FDataRef: array of Int32;
      Protected
        function GetCapacity: UInt32;
        procedure AllocResources;
        procedure FreeResources;
      Public
        function Get: Pointer;
        procedure Put(Item: Pointer);
        function IncRef(Item: Pointer): Int32;
        function DecRef(var Item: Pointer): Int32;
        Constructor Create(Capacity: UInt32; MemSize: UInt32);
        Destructor Destroy; Override;
        property Capacity: UInt32 read GetCapacity;
        property MemSize:UInt32 read FMemSize;
      End;
    
    Implementation
    
    const
      MAXTHREADCOUNT = 1000; // 从池中申请资源最大线程数
      // 创建池,大小必须是2的幂,并且必须大于MAXTHREADCOUNT
    
    Constructor TAtomPoolAbstract.Create(Capacity: UInt32);
    var
      OK: Boolean;
    Begin
      Inherited Create;
      OK := (Capacity and (Capacity - 1) = 0);
      OK := OK and (Capacity > MAXTHREADCOUNT);
    
      if not OK then
        raise Exception.Create(Format('池长度必须大于%d并为2的幂', [MAXTHREADCOUNT]));
    {$IFDEF POOLGROW}
      FCs := TCriticalSection.Create;
    {$ENDIF}
      FHighBound := Capacity - 1;
      FReadPtr := 0;
    End;
    
    Destructor TAtomPoolAbstract.Destroy;
    Begin
      FreeResources;
      SetLength(FData, 0);
    {$IFDEF POOLGROW}
      FCs.Free;
    {$ENDIF}
      Inherited;
    End;
    
    procedure TAtomPoolAbstract.AllocResources;
    var
      i: UInt32;
    begin
      try
        SetLength(FData, Capacity);
        for i := 0 to FHighBound do
          FData[i] := AllocItemResource;
      except
        Raise Exception.Create('池申请内存失败');
      end;
    end;
    
    procedure TAtomPoolAbstract.FreeResources;
    var
      i: UInt32;
    begin
      for i := FHighBound downto 0 do
        Self.FreeItemResource(FData[i]);
    end;
    
    procedure TAtomPoolAbstract.Put(Item: Pointer);
    var
      N: UInt32;
    begin
    {$IFDEF POOLGROW}
      CheckGrow;
    {$ENDIF}
      N := TInterlocked.Increment(FWritePtr);
      FData[N and FHighBound] := Item;
    end;
    
    Function TAtomPoolAbstract.Get: Pointer;
    var
    {$IFDEF POOLGROW}
      N, M, K: UInt32;
    {$ELSE}
      N: UInt32;
    {$ENDIF}
    begin
    {$IFDEF POOLGROW}
      N := FWritePtr and FHighBound;
      M := FReadPtr and FHighBound;
      K := (M + MAXTHREADCOUNT) and FHighBound;
      if (N > M) and (N < K) then
      // if ((N > M) and (N < K)) or ((N < M) and (N > K)) then
      begin
        Grow
      end;
    {$ENDIF}
      N := TInterlocked.Increment(FReadPtr);
      Result := FData[N and FHighBound];
    end;
    
    function TAtomPoolAbstract.GetCapacity: UInt32;
    begin
      Result := FHighBound + 1;
    end;
    
    {$IFDEF POOLGROW}
    
    procedure TAtomPoolAbstract.CheckGrow;
    begin
      if TInterlocked.Add(FLock, 0) > 0 then
      begin
        while FLock = 1 do
          Sleep(0);
        FCs.Enter;
        FCs.Leave;
      end;
    end;
    
    procedure TAtomPoolAbstract.Grow;
    var
      i, N: Integer;
    begin
      if TInterlocked.CompareExchange(FLock, 1, 0) = 0 then // 加锁
      begin
        FCs.Enter;
        TInterlocked.Increment(FLock);
        N := Length(FData);
        SetLength(FData, N + N);
        for i := N to High(FData) do
          FData[i] := AllocItemResource;
        TInterlocked.Increment(FLock);
        FHighBound := High(FData);
        FWritePtr := FHighBound;
        FCs.Leave;
        TInterlocked.Exchange(FLock, 0);
      end
      else
        CheckGrow;
    end;
    {$ENDIF}
    { TAtomPoolMem4K }
    
    function TAtomPoolMem4K.AllocItemResource: Pointer;
    begin
      GetMem(Result, 4096);
    end;
    
    procedure TAtomPoolMem4K.FreeItemResource(Item: Pointer);
    begin
      FreeMem(Item, 4096);
    end;
    
    Constructor TAtomMemoryPoolRef.Create(Capacity: UInt32; MemSize: UInt32);
    var
      OK: Boolean;
    Begin
      Inherited Create;
      OK := (Capacity and (Capacity - 1) = 0);
      OK := OK and (Capacity > MAXTHREADCOUNT);
    
      if not OK then
        raise Exception.Create(Format('池长度必须大于%d并为2的幂', [MAXTHREADCOUNT]));
      if FMemSize and $10 <> 0 then
        raise Exception.Create('内存块大小必须是16的倍数');
    
      FMemSize := MemSize;
      try
        AllocResources;
        FHighBound := Capacity - 1;
        FWritePtr := FHighBound;
        FReadPtr := 0;
      except
        Raise Exception.Create('池申请内存失败');
      end;
    End;
    
    function TAtomMemoryPoolRef.DecRef(var Item: Pointer): Int32;
    var
      N: Integer;
    begin
      N := (NativeUInt(Item) - NativeUInt(FMemory)) div FMemSize;
      if (N>=0) and (N<=FHighBound) then
      begin
        Result := TInterlocked.Decrement(FDataRef[N]);
        if Result = 0 then
        begin
          Put(Item);
          Item := nil;
        end;
      end
      else Result:=-1;
    end;
    
    Destructor TAtomMemoryPoolRef.Destroy;
    Begin
      FreeResources;
      Inherited;
    End;
    
    procedure TAtomMemoryPoolRef.AllocResources;
    var
      i: UInt32;
      P: PByteArray;
    begin
      SetLength(FData, Capacity);
      SetLength(FDataRef, Capacity);
      FillChar(FDataRef[0], Capacity * Sizeof(FDataRef[0]), 0);
      GetMem(FMemory, Length(FData) * FMemSize); // 一次申请所有内存
      P := FMemory;
      for i := 0 to FHighBound do
      begin
        FData[i] := P;
        Inc(P, FMemSize);
      end;
    end;
    
    procedure TAtomMemoryPoolRef.FreeResources;
    begin
      FreeMem(FMemory, Length(FData) * FMemSize);
      SetLength(FData, 0);
      SetLength(FDataRef, 0);
    end;
    
    procedure TAtomMemoryPoolRef.Put(Item: Pointer);
    var
      N: UInt32;
    begin
      N := TInterlocked.Increment(FWritePtr);
      FData[N and FHighBound] := Item;
    end;
    
    Function TAtomMemoryPoolRef.Get: Pointer;
    var
      N: UInt32;
    begin
      N := TInterlocked.Increment(FReadPtr);
      Result := FData[N and FHighBound];
    end;
    
    function TAtomMemoryPoolRef.GetCapacity: UInt32;
    begin
      Result := FHighBound + 1;
    end;
    
    function TAtomMemoryPoolRef.IncRef(Item: Pointer): Int32;
    var
      N: Integer;
    begin
      N := (NativeInt(Item) - NativeInt(FMemory)) div FMemSize;
      if (N>=0) and (N<=FHighBound) then
        Result := TInterlocked.Increment(FDataRef[N])
      else
        Result:=-1;
    end;
    
    End.
  • 相关阅读:
    2018/2/26 省选模拟赛 0分
    2018/2/25 省选模拟赛 36分
    BZOJ 2428 JZYZOJ1533 : [HAOI2006]均分数据 模拟退火 随机化
    BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演
    BZOJ 3196 Tyvj 1730 二逼平衡树 树套树 线段树 treap
    POJ 2728 JZYZOJ 1636 分数规划 最小生成树 二分 prim
    JZYZOJ1998 [bzoj3223] 文艺平衡树 splay 平衡树
    POJ 3974 Palindrome 字符串 Manacher算法
    BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元
    jQuery cookie使用
  • 原文地址:https://www.cnblogs.com/hezihang/p/3776579.html
Copyright © 2020-2023  润新知