ㄓㄤㄑㄧㄤ

简易高效的Delphi原子队列

本文提供Delphi一个基于原子操作的无锁队列,简易高效。适用于多线程大吞吐量操作的队列。

可用于Android系统和32,64位Windows系统。

 

感谢歼10和qsl提供了修改建议!

有如下问题:

1.必须实现开辟内存

2.队列大小必须是2的幂

3.不能压入空指针

4.本程序还未经过工程应用考验

 1 unit utAtomFIFO;
 2  
 3 interface
 4  
 5 Uses
 6   SysUtils,
 7   SyncObjs;
 8  
 9 Type
10   TAtomFIFO = Class
11   Protected
12     FWritePtr: Integer;
13     FReadPtr: Integer;
14     FCount:Integer;
15     FHighBound:Integer;
16     FisEmpty:Integer;
17     FData: array of Pointer;
18     function GetSize:Integer;
19   Public
20     procedure Push(Item: Pointer);
21     function Pop: Pointer;
22     Constructor Create(Size: Integer); Virtual;
23     Destructor Destroy; Override;
24     Procedure Empty;
25     property Size: Integer read GetSize;
26     property UsedCount:Integer read FCount;
27   End;
28  
29 Implementation
30  
31 {$I InterlockedAPIs.inc}
32 //创建队列,大小必须是2的幂,需要开辟足够大的队列,防止队列溢出
33  
34 Constructor TAtomFIFO.Create(Size: Integer);
35 var
36   i:NativeInt;
37   OK:Boolean;
38 Begin
39   Inherited Create;
40   OK:=(Size and (Size-1)=0);
41  
42   if not OK then raise Exception.Create('FIFO长度必须大于等于256并为2的幂');
43  
44   try
45     SetLength(FData, Size);
46     FHighBound:=Size-1;
47   except
48     Raise Exception.Create('FIFO申请内存失败');
49   end;
50 End;
51  
52 Destructor TAtomFIFO.Destroy;
53 Begin
54   SetLength(FData, 0);
55   Inherited;
56 End;
57  
58 procedure TAtomFIFO.Empty;
59 begin
60   while (InterlockedExchange(FReadPtr, 0)<>0) and (InterlockedExchange(FWritePtr, 0)<>0) and (InterlockedExchange(FCount, 0)<>0) do;
61 end;
62  
63 function TAtomFIFO.GetSize: Integer;
64 begin
65   Result:=FHighBound+1;
66 end;
67  
68 procedure TAtomFIFO.Push(Item:Pointer);
69 var
70   N:Integer;
71 begin
72   if Item=nil then Exit;
73  
74   N:=InterlockedIncrement(FWritePtr) and FHighBound;
75   FData[N]:=Item;
76   InterlockedIncrement(FCount);
77 end;
78  
79 Function TAtomFIFO.Pop:Pointer;
80 var
81   N:Integer;
82 begin
83   if InterlockedDecrement(FCount)<0 then
84   begin
85     InterlockedIncrement(FCount);
86     Result:=nil;
87   end
88   else
89   begin
90     N:=InterlockedIncrement(FReadPtr) and FHighBound;
91     while FData[N]=nil do Sleep(1);
92     Result:=FData[N];
93  
94     FData[N]:=nil;
95   end;
96 end;
97  
98 End.
View Code

InterlockedAPIs.inc

  1 {*******************************************************}
  2 {                                                       }
  3 {           CodeGear Delphi Runtime Library             }
  4 {                                                       }
  5 { Copyright(c) 1995-2014 Embarcadero Technologies, Inc. }
  6 {                                                       }
  7 {*******************************************************}
  8  
  9 {$IFDEF CPUX86}
 10  
 11 function InterlockedAdd(var Addend: Integer; Increment: Integer): Integer;
 12 asm
 13       MOV   ECX,EAX
 14       MOV   EAX,EDX
 15  LOCK XADD  [ECX],EAX
 16       ADD   EAX,EDX
 17 end;
 18  
 19 function InterlockedCompareExchange(var Target: Integer; Exchange: Integer; Comparand: Integer): Integer;
 20 asm
 21       XCHG    EAX,ECX
 22  LOCK CMPXCHG [ECX],EDX
 23 end;
 24  
 25 function InterlockedCompareExchangePointer(var Target: Pointer; Exchange: Pointer; Comparand: Pointer): Pointer;
 26 asm
 27       JMP InterlockedCompareExchange
 28 end;
 29  
 30 function InterlockedDecrement(var Addend: Integer): Integer;
 31 asm
 32       MOV   EDX,-1
 33       JMP   InterlockedAdd
 34 end;
 35  
 36 function InterlockedExchange(var Target: Integer; Value: Integer): Integer;
 37 asm
 38       MOV     ECX,EAX
 39       MOV     EAX,[ECX]
 40 @@loop:
 41  LOCK CMPXCHG [ECX],EDX
 42       JNZ     @@loop
 43 end;
 44  
 45 function InterlockedExchangePointer(var Target: Pointer; Value: Pointer): Pointer;
 46 asm
 47       JMP InterlockedExchange
 48 end;
 49  
 50 function InterlockedIncrement(var Addend: Integer): Integer;
 51 asm
 52       MOV   EDX,1
 53       JMP   InterlockedAdd
 54 end;
 55  
 56 {$ENDIF CPUX86}
 57  
 58 {$IFDEF CPUX64}
 59  
 60 function InterlockedExchangeAdd(var Addend: Integer; Value: Integer): Integer;
 61 asm
 62       .NOFRAME
 63       MOV   EAX,EDX
 64  LOCK XADD  [RCX].Integer,EAX
 65 end;
 66  
 67 function InterlockedDecrement(var Addend: LongInt): LongInt;
 68 asm
 69       .NOFRAME
 70       MOV   EAX,-1
 71  LOCK XADD  [RCX].Integer,EAX
 72       DEC   EAX
 73 end;
 74  
 75 function InterlockedIncrement(var Addend: LongInt): LongInt;
 76 asm
 77       MOV   EAX,1
 78  LOCK XADD  [RCX].Integer,EAX
 79       INC   EAX
 80 end;
 81  
 82 function InterlockedCompareExchange(var Destination: Integer; Exchange: Integer; Comparand: Integer): Integer;
 83 asm
 84       .NOFRAME
 85       MOV     EAX,R8d
 86  LOCK CMPXCHG [RCX].Integer,EDX
 87 end;
 88  
 89 function InterlockedCompareExchange64(var Destination: Int64; Exchange: Int64; Comparand: Int64): Int64; overload;
 90 asm
 91       .NOFRAME
 92       MOV     RAX,R8
 93  LOCK CMPXCHG [RCX],RDX
 94 end;
 95  
 96 function InterlockedCompareExchangePointer(var Destination: Pointer; Exchange: Pointer; Comparand: Pointer): Pointer;
 97 asm
 98       .NOFRAME
 99       MOV     RAX,R8
100  LOCK CMPXCHG [RCX],RDX
101 end;
102  
103 function InterlockedExchangePointer(var Target: Pointer; Value: Pointer): Pointer;
104 asm
105        .NOFRAME
106   LOCK XCHG [RCX],RDX
107        MOV RAX,RDX
108 end;
109  
110 function InterlockedExchange(var Target: Integer; Value: Integer): Integer;// inline;
111 asm
112        .NOFRAME
113   LOCK XCHG [RCX],EDX
114        MOV EAX,EDX
115 end;
116  
117 {$ENDIF CPUX64}
118  
119 {$IFDEF CPUARM}
120  
121 function InterlockedAdd(var Addend: Integer; Increment: Integer): Integer;
122 begin
123   Result := AtomicIncrement(Addend, Increment);
124 end;
125  
126 function InterlockedCompareExchange(var Target: Integer; Exchange: Integer; Comparand: Integer): Integer;
127 begin
128   Result := AtomicCmpExchange(Target, Exchange, Comparand);
129 end;
130  
131 function InterlockedCompareExchangePointer(var Target: Pointer; Exchange: Pointer; Comparand: Pointer): Pointer;
132 begin
133   Result := AtomicCmpExchange(Target, Exchange, Comparand);
134 end;
135  
136 function InterlockedDecrement(var Addend: Integer): Integer;
137 begin
138   Result := AtomicDecrement(Addend);
139 end;
140  
141 function InterlockedExchange(var Target: Integer; Value: Integer): Integer;
142 begin
143   Result := AtomicExchange(Target, Value);
144 end;
145  
146 function InterlockedExchangePointer(var Target: Pointer; Value: Pointer): Pointer;
147 begin
148   Result := AtomicExchange(Target, Value);
149 end;
150  
151 function InterlockedIncrement(var Addend: Integer): Integer;
152 begin
153   Result := AtomicIncrement(Addend);
154 end;
155  
156 {$ENDIF CPUARM}
View Code

性能测试:

采用天地弦提供的评估程序,进行了一些修改,分别对使用不同的临界区的队列进行对比结果如下:

其中Swith是因队列读空,进行线程上下文切换的次数

1
<em id="__mceDel"> </em>
posted @ 2014-06-18 11:22  ㄓㄤㄑㄧㄤ  阅读(463)  评论(0)    收藏  举报
哈哈,页脚部分。