文章转载于: https://blog.csdn.net/rocklee/article/details/48803999
本文供给Delphi一个基于原子操纵的无锁队列,简略单纯高效。实用于多线程大吞吐量操纵的队列。可用于Android体系和32,64位Windows体系。
有如下题目:
1.必须实现开辟内存
2.队列大小必须是2的幂
3. 不能压入空指针
InterlockedAPIs.inc
{*******************************************************} { } { CodeGear Delphi Runtime Library } { } { Copyright(c) 1995-2014 Embarcadero Technologies, Inc. } { } {*******************************************************} {$IFDEF CPUX86} function InterlockedAdd(var Addend: Integer; Increment: Integer): Integer; asm MOV ECX,EAX MOV EAX,EDX LOCK XADD [ECX],EAX ADD EAX,EDX end; function InterlockedCompareExchange(var Target: Integer; Exchange: Integer; Comparand: Integer): Integer; asm XCHG EAX,ECX LOCK CMPXCHG [ECX],EDX end; function InterlockedCompareExchangePointer(var Target: Pointer; Exchange: Pointer; Comparand: Pointer): Pointer; asm JMP InterlockedCompareExchange end; function InterlockedDecrement(var Addend: Integer): Integer; asm MOV EDX,-1 JMP InterlockedAdd end; function InterlockedExchange(var Target: Integer; Value: Integer): Integer; asm MOV ECX,EAX MOV EAX,[ECX] @@loop: LOCK CMPXCHG [ECX],EDX JNZ @@loop end; function InterlockedExchangePointer(var Target: Pointer; Value: Pointer): Pointer; asm JMP InterlockedExchange end; function InterlockedIncrement(var Addend: Integer): Integer; asm MOV EDX,1 JMP InterlockedAdd end; {$ENDIF CPUX86} {$IFDEF CPUX64} function InterlockedExchangeAdd(var Addend: Integer; Value: Integer): Integer; asm .NOFRAME MOV EAX,EDX LOCK XADD [RCX].Integer,EAX end; function InterlockedDecrement(var Addend: LongInt): LongInt; asm .NOFRAME MOV EAX,-1 LOCK XADD [RCX].Integer,EAX DEC EAX end; function InterlockedIncrement(var Addend: LongInt): LongInt; asm MOV EAX,1 LOCK XADD [RCX].Integer,EAX INC EAX end; function InterlockedCompareExchange(var Destination: Integer; Exchange: Integer; Comparand: Integer): Integer; asm .NOFRAME MOV EAX,R8d LOCK CMPXCHG [RCX].Integer,EDX end; function InterlockedCompareExchange64(var Destination: Int64; Exchange: Int64; Comparand: Int64): Int64; overload; asm .NOFRAME MOV RAX,R8 LOCK CMPXCHG [RCX],RDX end; function InterlockedCompareExchangePointer(var Destination: Pointer; Exchange: Pointer; Comparand: Pointer): Pointer; asm .NOFRAME MOV RAX,R8 LOCK CMPXCHG [RCX],RDX end; function InterlockedExchangePointer(var Target: Pointer; Value: Pointer): Pointer; asm .NOFRAME LOCK XCHG [RCX],RDX MOV RAX,RDX end; function InterlockedExchange(var Target: Integer; Value: Integer): Integer;// inline; asm .NOFRAME LOCK XCHG [RCX],EDX MOV EAX,EDX end; {$ENDIF CPUX64} {$IFDEF CPUARM} function InterlockedAdd(var Addend: Integer; Increment: Integer): Integer; begin Result := AtomicIncrement(Addend, Increment); end; function InterlockedCompareExchange(var Target: Integer; Exchange: Integer; Comparand: Integer): Integer; begin Result := AtomicCmpExchange(Target, Exchange, Comparand); end; function InterlockedCompareExchangePointer(var Target: Pointer; Exchange: Pointer; Comparand: Pointer): Pointer; begin Result := AtomicCmpExchange(Target, Exchange, Comparand); end; function InterlockedDecrement(var Addend: Integer): Integer; begin Result := AtomicDecrement(Addend); end; function InterlockedExchange(var Target: Integer; Value: Integer): Integer; begin Result := AtomicExchange(Target, Value); end; function InterlockedExchangePointer(var Target: Pointer; Value: Pointer): Pointer; begin Result := AtomicExchange(Target, Value); end; function InterlockedIncrement(var Addend: Integer): Integer; begin Result := AtomicIncrement(Addend); end; {$ENDIF CPUARM}
utAtomFIFO.pas
unit utAtomFIFO; interface Uses SysUtils, SyncObjs; Type TAtomFIFO = Class Protected FWritePtr: Integer; FReadPtr: Integer; FCount:Integer; FHighBound:Integer; FisEmpty:Integer; FData: array of Pointer; function GetSize:Integer; Public procedure Push(Item: Pointer); function Pop: Pointer; Constructor Create(Size: Integer); Virtual; Destructor Destroy; Override; Procedure Empty; property Size: Integer read GetSize; property UsedCount:Integer read FCount; End; Implementation {$I InterlockedAPIs.inc} //创建队列,大小必须是2的幂,须要开辟足够大的队列,防止队列溢出 Constructor TAtomFIFO.Create(Size: Integer); var i:NativeInt; OK:Boolean; Begin Inherited Create; OK:=(Size and (Size-1)=0); if not OK then raise Exception.Create('FIFO长度必须大于便是256并为2的幂'); try SetLength(FData,Size); FHighBound:=Size-1; except Raise Exception.Create('FIFO申请内存失败'); end; End; Destructor TAtomFIFO.Destroy; Begin SetLength(FData,0); Inherited; End; procedure TAtomFIFO.Empty; begin while (InterlockedExchange(FReadPtr, 0)<>0) and (InterlockedExchange(FWritePtr, 0)<>0) and (InterlockedExchange(FCount,0)<>0) do; end; function TAtomFIFO.GetSize: Integer; begin Result:=FHighBound+1; end; procedure TAtomFIFO.Push(Item:Pointer); var N:Integer; begin if Item=nil then Exit; N:=InterlockedIncrement(FWritePtr) and FHighBound; FData[N]:=Item; InterlockedIncrement(FCount); end; Function TAtomFIFO.Pop:Pointer; var N:Integer; begin if InterlockedDecrement(FCount)<0 then begin InterlockedIncrement(FCount); Result:=nil; end else begin N:=InterlockedIncrement(FReadPtr) and FHighBound; while FData[N]=nil do Sleep(1); Result:=FData[N]; FData[N]:=nil; end; end; End.