Skip to content

Commit cfa6fb0

Browse files
committed
optimized iterator enumerator
1 parent b5c371c commit cfa6fb0

File tree

1 file changed

+59
-27
lines changed

1 file changed

+59
-27
lines changed

Source/Base/Collections/Spring.Collections.Base.pas

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -285,27 +285,39 @@ TIteratorRec<T> = record
285285
class function Add(const collection: IInterface; const value: Spring.TValue): Boolean; static;
286286
end;
287287

288-
TIterator = class abstract(TRefCountedObject)
288+
PIterator = ^TIterator;
289+
TIterator = record
289290
private type
290291
TEnumeratorState = (Initial, Started, Finished);
291292
private
292-
fSource: TRefCountedObject;
293-
fIterator: PIteratorRec;
294-
fState: TEnumeratorState;
293+
Vtable: Pointer;
294+
RefCount: Integer;
295+
Parent: TRefCountedObject;
296+
Iterator: PIteratorRec;
297+
State: TEnumeratorState;
295298
procedure Start;
296299
public
297-
constructor Create(source: TRefCountedObject; iterator: PIteratorRec);
298-
destructor Destroy; override;
300+
class function Create(enumerator: PPointer; vtable: PEnumeratorVtable;
301+
parent: TRefCountedObject; iterator: PIteratorRec; getCurrent: Pointer): Pointer; static;
302+
function _Release: Integer; stdcall;
299303
function MoveNext: Boolean;
300304
end;
301305

302306
TIteratorBase<T> = class abstract(TEnumerableBase<T>)
303307
private type
304308
TIteratorRecT = TIteratorRec<T>;
305309
PIteratorRecT = ^TIteratorRecT;
306-
TEnumerator = class(TIterator, IEnumerator<T>)
307-
private
310+
311+
TEnumerator = record
312+
Vtable: Pointer;
313+
RefCount: Integer;
314+
315+
fSource: TRefCountedObject;
316+
fIterator: PIteratorRecT;
317+
fState: TIterator.TEnumeratorState;
308318
function GetCurrent: T;
319+
320+
class var Enumerator_Vtable: TEnumeratorVtable;
309321
end;
310322
protected
311323
fIterator: TIteratorRec<T>;
@@ -2555,7 +2567,7 @@ function TIteratorBase<T>.GetElementType: PTypeInfo;
25552567

25562568
function TIteratorBase<T>.GetEnumerator: IEnumerator<T>;
25572569
begin
2558-
Result := TEnumerator.Create(Self, @fIterator);
2570+
TIterator.Create(@Result, @TEnumerator.Enumerator_Vtable, Self, @fIterator, @TEnumerator.GetCurrent);
25592571
end;
25602572

25612573
function TIteratorBase<T>.ToArray: TArray<T>;
@@ -2682,48 +2694,68 @@ function TArrayIterator<T>.ToArray: TArray<T>;
26822694

26832695
{$REGION 'TIterator'}
26842696

2685-
constructor TIterator.Create(source: TRefCountedObject; iterator: PIteratorRec);
2697+
class function TIterator.Create(enumerator: PPointer; vtable: PEnumeratorVtable;
2698+
parent: TRefCountedObject; iterator: PIteratorRec; getCurrent: Pointer): Pointer;
26862699
begin
2687-
fSource := source;
2688-
fSource._AddRef;
2689-
fIterator := iterator.Clone;
2700+
IInterface(enumerator^) := nil;
2701+
parent._AddRef;
2702+
Result := AllocMem(SizeOf(TIterator));
2703+
PIterator(Result).Vtable := vtable;
2704+
PIterator(Result).RefCount := 1;
2705+
PIterator(Result).Parent := parent;
2706+
PIterator(Result).Iterator := iterator.Clone;
2707+
enumerator^ := Result;
2708+
2709+
if not Assigned(vtable[0]) then
2710+
begin
2711+
vtable[0] := @NopQueryInterface;
2712+
vtable[1] := @RecAddRef;
2713+
vtable[2] := @TIterator._Release;
2714+
vtable[3] := getCurrent;
2715+
vtable[4] := @TIterator.MoveNext;
2716+
end;
26902717
end;
26912718

2692-
destructor TIterator.Destroy;
2719+
function TIterator._Release: Integer;
26932720
begin
2694-
fIterator.Finalize;
2695-
FreeMem(fIterator);
2696-
fSource._Release;
2721+
Result := AtomicDecrement(RefCount);
2722+
if Result = 0 then
2723+
begin
2724+
Iterator.Finalize;
2725+
FreeMem(Iterator);
2726+
Parent._Release;
2727+
FreeMem(@Self);
2728+
end;
26972729
end;
26982730

26992731
function TIterator.MoveNext: Boolean;
27002732
begin
27012733
repeat
2702-
if fState = Started then
2734+
if State = Started then
27032735
begin
2704-
if fIterator.MoveNext(fIterator) then
2736+
if Iterator.MoveNext(Iterator) then
27052737
Exit(True);
2706-
fState := Finished;
2738+
State := Finished;
27072739
end;
2708-
if fState = Initial then
2740+
if State = Initial then
27092741
begin
2710-
fState := Started;
2742+
State := Started;
27112743
Start;
27122744
end;
2713-
until fState = Finished;
2745+
until State = Finished;
27142746

2715-
fIterator.Finalize;
2747+
Iterator.Finalize;
27162748
Result := False;
27172749
end;
27182750

27192751
procedure TIterator.Start;
27202752
var
27212753
startProc: TStartFunc;
27222754
begin
2723-
startProc := fIterator.Start;
2755+
startProc := Iterator.Start;
27242756
if Assigned(startProc) then
2725-
if not startProc(fIterator) then
2726-
fState := Finished;
2757+
if not startProc(Iterator) then
2758+
State := Finished;
27272759
end;
27282760

27292761
{$ENDREGION}

0 commit comments

Comments
 (0)