Skip to content

Commit baf9709

Browse files
committed
optimization for changed event
1 parent a17ae80 commit baf9709

File tree

1 file changed

+47
-41
lines changed

1 file changed

+47
-41
lines changed

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

Lines changed: 47 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ interface
3333
SysUtils,
3434
TypInfo,
3535
Spring,
36+
Spring.Events.Base,
3637
Spring.Collections,
3738
Spring.Collections.Events,
3839
Spring.Collections.HashTable;
@@ -374,8 +375,7 @@ TCollectionBase<T> = class abstract(TEnumerableBase<T>)
374375
private
375376
fOnChanged: TCollectionChangedEventImpl<T>;
376377
fNotify: TNotify;
377-
procedure InitializeEvent;
378-
procedure UpdateNotify(Sender: TObject);
378+
procedure EventChanged(Sender: TObject);
379379
protected
380380
{$REGION 'Property Accessors'}
381381
function GetIsReadOnly: Boolean;
@@ -645,6 +645,8 @@ TArrayHelper = record
645645
EmptyBucket = -1; // must be negative, note choice of BucketSentinelFlag
646646
UsedBucket = -2; // likewise
647647

648+
procedure UpdateNotify(actualClass, baseClass: TClass; const event: TEventBase; var code);
649+
648650
implementation
649651

650652
uses
@@ -657,9 +659,24 @@ implementation
657659
Posix.Pthread,
658660
{$ENDIF}
659661
Spring.Collections.Lists,
660-
Spring.Events.Base,
661662
Spring.ResourceStrings;
662663

664+
procedure UpdateNotify(actualClass, baseClass: TClass; const event: TEventBase; var code);
665+
const
666+
ChangedVirtualIndex = 1;
667+
var
668+
baseAddress, actualAddress: Pointer;
669+
begin
670+
{$POINTERMATH ON}
671+
baseAddress := PPointer(baseClass)[ChangedVirtualIndex];
672+
actualAddress := PPointer(actualClass)[ChangedVirtualIndex];
673+
{$POINTERMATH OFF}
674+
if (Assigned(event) and event.CanInvoke) or (actualAddress <> baseAddress) then
675+
Pointer(code) := actualAddress
676+
else
677+
Pointer(code) := nil;
678+
end;
679+
663680

664681
{$REGION 'TArrayHelper'}
665682

@@ -1782,7 +1799,7 @@ function TSourceIterator<T>.GetElementType: PTypeInfo;
17821799
constructor TCollectionBase<T>.Create;
17831800
begin
17841801
inherited Create;
1785-
UpdateNotify(Self);
1802+
UpdateNotify(ClassType, TCollectionBase<T>, fOnChanged, fNotify);
17861803
end;
17871804

17881805
destructor TCollectionBase<T>.Destroy;
@@ -1791,24 +1808,9 @@ destructor TCollectionBase<T>.Destroy;
17911808
inherited Destroy;
17921809
end;
17931810

1794-
procedure TCollectionBase<T>.InitializeEvent;
1795-
var
1796-
onChanged: TCollectionChangedEventImpl<T>;
1811+
procedure TCollectionBase<T>.EventChanged(Sender: TObject);
17971812
begin
1798-
if not Assigned(fOnChanged) then
1799-
begin
1800-
onChanged := TCollectionChangedEventImpl<T>.Create;
1801-
onChanged.OnChanged := UpdateNotify;
1802-
if AtomicCmpExchange(Pointer(fOnChanged), Pointer(onChanged), nil) <> nil then
1803-
onChanged.Free
1804-
else
1805-
begin
1806-
{$IFDEF AUTOREFCOUNT}
1807-
onChanged.__ObjAddRef;
1808-
{$ENDIF AUTOREFCOUNT}
1809-
UpdateNotify(Self);
1810-
end;
1811-
end;
1813+
UpdateNotify(ClassType, TCollectionBase<T>, fOnChanged, fNotify);
18121814
end;
18131815

18141816
procedure TCollectionBase<T>.DoNotify(const item: T;
@@ -1902,8 +1904,24 @@ function TCollectionBase<T>.GetIsReadOnly: Boolean;
19021904
end;
19031905

19041906
function TCollectionBase<T>.GetOnChanged: ICollectionChangedEvent<T>;
1907+
var
1908+
onChanged: TCollectionChangedEventImpl<T>;
19051909
begin
1906-
InitializeEvent;
1910+
if not Assigned(fOnChanged) then
1911+
begin
1912+
onChanged := TCollectionChangedEventImpl<T>.Create;
1913+
if AtomicCmpExchange(Pointer(fOnChanged), Pointer(onChanged), nil) <> nil then
1914+
onChanged.Free
1915+
else
1916+
begin
1917+
{$IFDEF AUTOREFCOUNT}
1918+
onChanged.__ObjAddRef;
1919+
{$ENDIF AUTOREFCOUNT}
1920+
fOnChanged.OnChanged := EventChanged;
1921+
EventChanged(fOnChanged);
1922+
end;
1923+
end;
1924+
19071925
Result := fOnChanged;
19081926
end;
19091927

@@ -1943,18 +1961,6 @@ function TCollectionBase<T>.QueryInterface(const IID: TGUID; out obj): HResult;
19431961
Result := inherited QueryInterface(IID, obj);
19441962
end;
19451963

1946-
procedure TCollectionBase<T>.UpdateNotify(Sender: TObject);
1947-
var
1948-
event: procedure(const item: T; action: TCollectionChangedAction) of object;
1949-
begin
1950-
event := Changed;
1951-
if (Assigned(fOnChanged) and fOnChanged.CanInvoke)
1952-
or (TMethod(event).Code <> @TCollectionBase<T>.Changed) then
1953-
fNotify := TMethod(event).Code
1954-
else
1955-
fNotify := nil;
1956-
end;
1957-
19581964
function TCollectionBase<T>.RemoveAll(const match: Predicate<T>): Integer;
19591965
begin
19601966
Result := RemoveRange(IEnumerable<T>(this).Where(match).ToArray);
@@ -2622,7 +2628,7 @@ function TListBase<T>.IndexOf(const item: T): Integer;
26222628
var
26232629
count: Integer;
26242630
begin
2625-
count := IEnumerable<T>(this).Count;
2631+
count := IList<T>(this).Count;
26262632
if count > 0 then
26272633
Result := IList<T>(this).IndexOf(item, 0, count)
26282634
else
@@ -2633,7 +2639,7 @@ function TListBase<T>.IndexOf(const item: T; index: Integer): Integer;
26332639
var
26342640
count: Integer;
26352641
begin
2636-
count := IEnumerable<T>(this).Count;
2642+
count := IList<T>(this).Count;
26372643
if count > 0 then
26382644
Result := IList<T>(this).IndexOf(item, index, count - index)
26392645
else
@@ -2644,7 +2650,7 @@ function TListBase<T>.LastIndexOf(const item: T): Integer;
26442650
var
26452651
count: Integer;
26462652
begin
2647-
count := IEnumerable<T>(this).Count;
2653+
count := IList<T>(this).Count;
26482654
if count > 0 then
26492655
Result := IList<T>(this).LastIndexOf(item, count - 1, count)
26502656
else
@@ -2655,7 +2661,7 @@ function TListBase<T>.LastIndexOf(const item: T; index: Integer): Integer;
26552661
var
26562662
count: Integer;
26572663
begin
2658-
count := IEnumerable<T>(this).Count;
2664+
count := IList<T>(this).Count;
26592665
if count > 0 then
26602666
Result := IList<T>(this).LastIndexOf(item, index, index + 1)
26612667
else
@@ -2679,17 +2685,17 @@ procedure TListBase<T>.Reverse;
26792685

26802686
procedure TListBase<T>.Sort;
26812687
begin
2682-
IList<T>(this).Sort(fComparer, 0, IEnumerable<T>(this).Count);
2688+
IList<T>(this).Sort(fComparer, 0, IList<T>(this).Count);
26832689
end;
26842690

26852691
procedure TListBase<T>.Sort(const comparer: IComparer<T>);
26862692
begin
2687-
IList<T>(this).Sort(comparer, 0, IEnumerable<T>(this).Count);
2693+
IList<T>(this).Sort(comparer, 0, IList<T>(this).Count);
26882694
end;
26892695

26902696
procedure TListBase<T>.Sort(const comparer: TComparison<T>);
26912697
begin
2692-
IList<T>(this).Sort(IComparer<T>(PPointer(@comparer)^), 0, IEnumerable<T>(this).Count);
2698+
IList<T>(this).Sort(IComparer<T>(PPointer(@comparer)^), 0, IList<T>(this).Count);
26932699
end;
26942700

26952701
procedure TListBase<T>.Sort(const comparer: TComparison<T>; index, count: Integer);

0 commit comments

Comments
 (0)