一个简易 无锁池
1.所有读写无等待,不需要判断条件直接读写(除自动扩充容量时),效率是一般带锁或带条件判断池的两倍以上。
2.预先开辟2的幂大小容量,可自增,每次翻倍
3.仅提供思路,工程应用可靠性还不确定。
// 无锁池 // hezihang @cnblogs.com// 20160228 增加代引用计数器内存块的池,增加编译指令POOLGROW功能,可打开关闭池的自动翻倍增长功能 // 20160225 修正Grow中FWritePtr没有增长Bug // 20140609 增加Grow临界区,减少等待时间 // 20140608 修正可能存在同时Grow的Bugunit Iocp.AtomPool;interface{ .$DEFINE POOLGROW }UsesSystem.SysUtils,System.SyncObjs;TypeInt32 = Integer;UInt32 = Cardinal;TAtomPoolAbstract = classprivateFWritePtr: Int32;FReadPtr: Int32;FHighBound: UInt32;FData: array of Pointer; {$IFDEF POOLGROW}FCs: TCriticalSection;FLock: Int32;procedure CheckGrow; inline;procedure Grow; inline; {$ENDIF}Protectedfunction AllocItemResource: Pointer; virtual; abstract;procedure FreeItemResource(Item: Pointer); virtual; abstract;function GetCapacity: UInt32;procedure FreeResources;Publicprocedure 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 = classprivateFMemory: PByteArray;FWritePtr: Int32;FReadPtr: Int32;FHighBound: UInt32;FMemSize: UInt32;FData: array of Pointer;FDataRef: array of Int32;Protectedfunction GetCapacity: UInt32;procedure AllocResources;procedure FreeResources;Publicfunction 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;ImplementationconstMAXTHREADCOUNT = 1000; // 从池中申请资源最大线程数// 创建池,大小必须是2的幂,并且必须大于MAXTHREADCOUNT Constructor TAtomPoolAbstract.Create(Capacity: UInt32); varOK: Boolean; BeginInherited Create;OK := (Capacity and (Capacity - 1) = 0);OK := OK and (Capacity > MAXTHREADCOUNT);if not OK thenraise Exception.Create(Format('池长度必须大于%d并为2的幂', [MAXTHREADCOUNT])); {$IFDEF POOLGROW}FCs := TCriticalSection.Create; {$ENDIF}FHighBound := Capacity - 1;FReadPtr := 0; End;Destructor TAtomPoolAbstract.Destroy; BeginFreeResources;SetLength(FData, 0); {$IFDEF POOLGROW}FCs.Free; {$ENDIF}Inherited; End;procedure TAtomPoolAbstract.AllocResources; vari: UInt32; begintrySetLength(FData, Capacity);for i := 0 to FHighBound doFData[i] := AllocItemResource;exceptRaise Exception.Create('池申请内存失败');end; end;procedure TAtomPoolAbstract.FreeResources; vari: UInt32; beginfor i := FHighBound downto 0 doSelf.FreeItemResource(FData[i]); end;procedure TAtomPoolAbstract.Put(Item: Pointer); varN: 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)) thenbeginGrowend; {$ENDIF}N := TInterlocked.Increment(FReadPtr);Result := FData[N and FHighBound]; end;function TAtomPoolAbstract.GetCapacity: UInt32; beginResult := FHighBound + 1; end;{$IFDEF POOLGROW}procedure TAtomPoolAbstract.CheckGrow; beginif TInterlocked.Add(FLock, 0) > 0 thenbeginwhile FLock = 1 doSleep(0);FCs.Enter;FCs.Leave;end; end;procedure TAtomPoolAbstract.Grow; vari, N: Integer; beginif TInterlocked.CompareExchange(FLock, 1, 0) = 0 then // 加锁beginFCs.Enter;TInterlocked.Increment(FLock);N := Length(FData);SetLength(FData, N + N);for i := N to High(FData) doFData[i] := AllocItemResource;TInterlocked.Increment(FLock);FHighBound := High(FData);FWritePtr := FHighBound;FCs.Leave;TInterlocked.Exchange(FLock, 0);endelseCheckGrow; end; {$ENDIF} { TAtomPoolMem4K }function TAtomPoolMem4K.AllocItemResource: Pointer; beginGetMem(Result, 4096); end;procedure TAtomPoolMem4K.FreeItemResource(Item: Pointer); beginFreeMem(Item, 4096); end;Constructor TAtomMemoryPoolRef.Create(Capacity: UInt32; MemSize: UInt32); varOK: Boolean; BeginInherited Create;OK := (Capacity and (Capacity - 1) = 0);OK := OK and (Capacity > MAXTHREADCOUNT);if not OK thenraise Exception.Create(Format('池长度必须大于%d并为2的幂', [MAXTHREADCOUNT]));if FMemSize and $10 <> 0 thenraise Exception.Create('内存块大小必须是16的倍数');FMemSize := MemSize;tryAllocResources;FHighBound := Capacity - 1;FWritePtr := FHighBound;FReadPtr := 0;exceptRaise Exception.Create('池申请内存失败');end; End;function TAtomMemoryPoolRef.DecRef(var Item: Pointer): Int32; varN: Integer; beginN := (NativeUInt(Item) - NativeUInt(FMemory)) div FMemSize;if (N>=0) and (N<=FHighBound) thenbeginResult := TInterlocked.Decrement(FDataRef[N]);if Result = 0 thenbeginPut(Item);Item := nil;end;endelse Result:=-1; end;Destructor TAtomMemoryPoolRef.Destroy; BeginFreeResources;Inherited; End;procedure TAtomMemoryPoolRef.AllocResources; vari: UInt32;P: PByteArray; beginSetLength(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 dobeginFData[i] := P;Inc(P, FMemSize);end; end;procedure TAtomMemoryPoolRef.FreeResources; beginFreeMem(FMemory, Length(FData) * FMemSize);SetLength(FData, 0);SetLength(FDataRef, 0); end;procedure TAtomMemoryPoolRef.Put(Item: Pointer); varN: UInt32; beginN := TInterlocked.Increment(FWritePtr);FData[N and FHighBound] := Item; end;Function TAtomMemoryPoolRef.Get: Pointer; varN: UInt32; beginN := TInterlocked.Increment(FReadPtr);Result := FData[N and FHighBound]; end;function TAtomMemoryPoolRef.GetCapacity: UInt32; beginResult := FHighBound + 1; end;function TAtomMemoryPoolRef.IncRef(Item: Pointer): Int32; varN: Integer; beginN := (NativeInt(Item) - NativeInt(FMemory)) div FMemSize;if (N>=0) and (N<=FHighBound) thenResult := TInterlocked.Increment(FDataRef[N])elseResult:=-1; end;End.