@@ -512,18 +512,19 @@ TCircularArrayBuffer<T> = class(TEnumerableBase<T>)
512512 private
513513 { $REGION 'Nested Types'}
514514 type
515- TEnumerator = class (TRefCountedObject, IEnumerator<T>)
516- private
515+ PEnumerator = ^TEnumerator;
516+ TEnumerator = record
517+ Vtable: Pointer;
518+ RefCount: Integer;
519+ TypeInfo: PTypeInfo;
517520 { $IFDEF AUTOREFCOUNT} [Unsafe]{ $ENDIF}
518521 fSource: TCircularArrayBuffer<T>;
519- fIndex: Integer;
522+ fIndex, fCount : Integer;
520523 fVersion: Integer;
521524 fCurrent: T;
522525 function GetCurrent : T;
523- public
524- constructor Create(const source: TCircularArrayBuffer<T>);
525- destructor Destroy; override;
526526 function MoveNext : Boolean;
527+ class var Enumerator_Vtable: TEnumeratorVtable;
527528 end ;
528529 ItemType = TTypeInfo<T>;
529530 PT = ^T;
@@ -536,7 +537,7 @@ TEnumerator = class(TRefCountedObject, IEnumerator<T>)
536537 fVersion: Integer;
537538 fHead: Integer;
538539 fTail: Integer;
539- function GetTail : PT ; inline;
540+ function GetTail : Integer ; inline;
540541 protected
541542 { $REGION 'Property Accessors'}
542543 function GetCapacity : Integer; inline;
@@ -553,12 +554,11 @@ TEnumerator = class(TRefCountedObject, IEnumerator<T>)
553554 procedure DeleteFromHead (action: TCollectionChangedAction); inline;
554555 procedure DeleteFromTail (action: TCollectionChangedAction); inline;
555556
556- procedure DoNotify (const item: T; action: TCollectionChangedAction); inline;
557557 property Capacity: Integer read GetCapacity;
558558 property Count: Integer read GetCount;
559559 property Items: TArray<T> read fItems;
560560 property Head: Integer read fHead;
561- property Tail: PT read GetTail;
561+ property Tail: Integer read GetTail;
562562 property OwnsObjects: Boolean read GetOwnsObjects;
563563 public
564564 constructor Create(capacity: Integer = 0 ; ownsObjects: Boolean = False);
@@ -2108,13 +2108,6 @@ procedure TCircularArrayBuffer<T>.Clear;
21082108 DeleteFromHead(caRemoved);
21092109end ;
21102110
2111- procedure TCircularArrayBuffer <T>.DoNotify(const item: T;
2112- action: TCollectionChangedAction);
2113- begin
2114- if Assigned(fOnChanged) and fOnChanged.CanInvoke then
2115- fOnChanged.Invoke(Self, item, action);
2116- end ;
2117-
21182111function TCircularArrayBuffer <T>.GetCapacity: Integer;
21192112begin
21202113 Result := fCapacity;
@@ -2127,7 +2120,14 @@ function TCircularArrayBuffer<T>.GetCount: Integer;
21272120
21282121function TCircularArrayBuffer <T>.GetEnumerator: IEnumerator<T>;
21292122begin
2130- Result := TEnumerator.Create(Self);
2123+ _AddRef;
2124+ with PEnumerator(TEnumeratorBlock.Create(@Result, @TEnumerator.Enumerator_Vtable,
2125+ TypeInfo(TEnumerator), @TEnumerator.GetCurrent, @TEnumerator.MoveNext))^ do
2126+ begin
2127+ fSource := Self;
2128+ fCount := Self.Count;
2129+ fVersion := Self.fVersion;
2130+ end ;
21312131end ;
21322132
21332133function TCircularArrayBuffer <T>.GetIsEmpty: Boolean;
@@ -2145,15 +2145,14 @@ function TCircularArrayBuffer<T>.GetOwnsObjects: Boolean;
21452145 Result := { $IFDEF DELPHIXE7_UP} (GetTypeKind(T) = tkClass) and { $ENDIF} (fCount < 0 );
21462146end ;
21472147
2148- function TCircularArrayBuffer <T>.GetTail: PT ;
2148+ function TCircularArrayBuffer <T>.GetTail: Integer ;
21492149var
21502150 index: Integer;
21512151begin
21522152 index := fTail;
2153- if index > 0 then
2154- Result := @fItems[index - 1 ]
2155- else
2156- Result := @fItems[fCapacity - 1 ];
2153+ if index = 0 then
2154+ index := fCapacity;
2155+ Result := index - 1 ;
21572156end ;
21582157
21592158procedure TCircularArrayBuffer <T>.AddToHead(const item: T);
@@ -2172,7 +2171,8 @@ procedure TCircularArrayBuffer<T>.AddToHead(const item: T);
21722171 fItems[index] := item;
21732172 fHead := index;
21742173
2175- DoNotify(item, caAdded);
2174+ if Assigned(fOnChanged) and fOnChanged.CanInvoke then
2175+ fOnChanged.Invoke(Self, item, caAdded);
21762176end ;
21772177
21782178procedure TCircularArrayBuffer <T>.AddToTail(const item: T);
@@ -2190,7 +2190,9 @@ procedure TCircularArrayBuffer<T>.AddToTail(const item: T);
21902190 if index = fCapacity then
21912191 index := 0 ;
21922192 fTail := index;
2193- DoNotify(item, caAdded);
2193+
2194+ if Assigned(fOnChanged) and fOnChanged.CanInvoke then
2195+ fOnChanged.Invoke(Self, item, caAdded);
21942196end ;
21952197
21962198procedure TCircularArrayBuffer <T>.DeleteFromHead(action: TCollectionChangedAction);
@@ -2210,7 +2212,8 @@ procedure TCircularArrayBuffer<T>.DeleteFromHead(action: TCollectionChangedActio
22102212 index := 0 ;
22112213 fHead := index;
22122214
2213- DoNotify(item^, action);
2215+ if Assigned(fOnChanged) and fOnChanged.CanInvoke then
2216+ fOnChanged.Invoke(Self, item^, action);
22142217 if OwnsObjects and (action = caRemoved) then
22152218 FreeObject(item^);
22162219 item^ := Default(T);
@@ -2233,7 +2236,8 @@ procedure TCircularArrayBuffer<T>.DeleteFromTail(action: TCollectionChangedActio
22332236 item := @fItems[index];
22342237 fTail := index;
22352238
2236- DoNotify(item^, action);
2239+ if Assigned(fOnChanged) and fOnChanged.CanInvoke then
2240+ fOnChanged.Invoke(Self, item^, action);
22372241 if OwnsObjects and (action = caRemoved) then
22382242 FreeObject(item^);
22392243 item^ := Default(T);
@@ -2282,20 +2286,24 @@ procedure TCircularArrayBuffer<T>.TrimExcess;
22822286
22832287function TCircularArrayBuffer <T>.TryGetFirst(var value : T): Boolean;
22842288begin
2285- Result := Count > 0 ;
2286- if Result then
2287- value := fItems[fHead]
2288- else
2289- value := Default(T);
2289+ if Count > 0 then
2290+ begin
2291+ value := fItems[fHead];
2292+ Exit(True);
2293+ end ;
2294+ value := Default(T);
2295+ Result := False;
22902296end ;
22912297
22922298function TCircularArrayBuffer <T>.TryGetLast(var value : T): Boolean;
22932299begin
2294- Result := Count > 0 ;
2295- if Result then
2296- value := Tail^
2297- else
2298- value := Default(T);
2300+ if Count > 0 then
2301+ begin
2302+ value := fItems[Tail];
2303+ Exit(True);
2304+ end ;
2305+ value := Default(T);
2306+ Result := False;
22992307end ;
23002308
23012309procedure TCircularArrayBuffer <T>.SetCapacity(value : Integer);
@@ -2377,39 +2385,33 @@ procedure TCircularArrayBuffer<T>.SetOwnsObjects(value: Boolean);
23772385
23782386{ $REGION 'TCircularArrayBuffer<T>.TEnumerator'}
23792387
2380- constructor TCircularArrayBuffer<T>.TEnumerator.Create(
2381- const source: TCircularArrayBuffer<T>);
2382- begin
2383- fSource := source;
2384- fSource._AddRef;
2385- fVersion := fSource.fVersion;
2386- end ;
2387-
2388- destructor TCircularArrayBuffer<T>.TEnumerator.Destroy;
2389- begin
2390- fSource._Release;
2391- end ;
2392-
23932388function TCircularArrayBuffer <T>.TEnumerator.GetCurrent: T;
23942389begin
23952390 Result := fCurrent;
23962391end ;
23972392
23982393function TCircularArrayBuffer <T>.TEnumerator.MoveNext: Boolean;
2394+ var
2395+ source: TCircularArrayBuffer<T>;
2396+ index: Integer;
23992397begin
2400- if fVersion = fSource.fVersion then
2398+ source := fSource;
2399+ if fVersion = source.fVersion then
24012400 begin
2402- Result := fIndex < fSource.Count ;
2403- if Result then
2401+ index := fIndex;
2402+ if index < fCount then
24042403 begin
2405- fCurrent := fSource.fItems[(fSource.fHead + fIndex) mod fSource.fCapacity];
2404+ Inc(index, source.fHead);
2405+ if index >= source.fCapacity then
2406+ Dec(index, source.fCapacity);
2407+ fCurrent := source.fItems[index];
24062408 Inc(fIndex);
2407- end
2408- else
2409- fCurrent := Default(T);
2410- end
2411- else
2412- Result := RaiseHelper.EnumFailedVersion;
2409+ Exit(True);
2410+ end ;
2411+ fCurrent := Default(T);
2412+ Exit(False);
2413+ end ;
2414+ Result := RaiseHelper.EnumFailedVersion;
24132415end ;
24142416
24152417{ $ENDREGION}
0 commit comments