Skip to content

Commit a974af9

Browse files
committed
refactored hashtable
1 parent a11f6dd commit a974af9

13 files changed

+964
-817
lines changed

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

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,6 @@ TPairComparer<TKey, TValue> = record
8989
class function Default: IComparer<TPair<TKey, TValue>>; static;
9090
end;
9191

92-
TEqualsMethod<T> = function(const left, right: T): Boolean of object;
93-
TGetHashCodeMethod<T> = function(const value: T): Integer of object;
9492
TComparerThunks<T> = record
9593
class function Equals(instance: Pointer; const left, right): Boolean; static;
9694
class function GetHashCode(instance: Pointer; const value): Integer; static;
@@ -519,6 +517,7 @@ TInnerCollection<T> = class sealed(TEnumerableBase<T>,
519517
private type
520518
{$REGION 'Nested Types'}
521519
PT = ^T;
520+
522521
PEnumerator = ^TEnumerator;
523522
TEnumerator = record
524523
Vtable: Pointer;
@@ -671,13 +670,6 @@ TMapBase<TKey, TValue> = class abstract(TCollectionBase<TPair<TKey, TValue>>)
671670
OwnsObjectsMask = 1 shl OwnsObjectsBitIndex;
672671
CountMask = not OwnsObjectsMask;
673672

674-
// use the MSB of the HashCode to note removed items
675-
RemovedFlag = Integer($80000000);
676-
MinCapacity = 6; // 75% load factor leads to min bucket count of 8
677-
BucketSentinelFlag = RemovedFlag; // note: the same as RemovedFlag
678-
EmptyBucket = -1; // must be negative, note choice of BucketSentinelFlag
679-
UsedBucket = -2; // likewise
680-
681673
procedure AssignComparer(var comparer; const source: IInterface);
682674
procedure EnsureEventInstance(var event: TEventBase; var result;
683675
eventClass: TEventBaseClass; eventChanged: TNotifyEvent);
@@ -696,6 +688,7 @@ implementation
696688
Posix.Pthread,
697689
{$ENDIF}
698690
Spring.Collections.Lists,
691+
Spring.Comparers,
699692
Spring.ResourceStrings;
700693

701694
procedure AssignComparer(var comparer; const source: IInterface);
@@ -875,12 +868,14 @@ class function TPairComparer<TKey, TValue>.Default: IComparer<TPair<TKey, TValue
875868

876869
class function TComparerThunks<T>.Equals(instance: Pointer; const left, right): Boolean;
877870
begin
878-
Result := TEqualsMethod<T>(instance^)(T(left), T(right));
871+
Result := IEqualityComparer<T>(instance).Equals(T(left), T(right));
872+
// Result := TEqualsMethod<T>(instance^)(T(left), T(right));
879873
end;
880874

881875
class function TComparerThunks<T>.GetHashCode(instance: Pointer; const value): Integer;
882876
begin
883-
Result := TGetHashCodeMethod<T>(instance^)(T(value));
877+
Result := IEqualityComparer<T>(instance).GetHashCode(T(value));
878+
// Result := TGetHashCodeMethod<T>(instance^)(T(value));
884879
end;
885880

886881
{$ENDREGION}
@@ -2373,16 +2368,40 @@ class function TInnerCollection<T>.Create(const source: TRefCountedObject;
23732368
Result.fHashTable := hashTable;
23742369
Result.fElementType := elementType;
23752370
Result.fComparer := comparer;
2376-
Result.fOffset := THashTable.KeyOffset + offset;
2371+
Result.fOffset := KeyOffset + offset;
23772372
Result.AfterConstruction;
23782373
end;
23792374

23802375
function TInnerCollection<T>.Contains(const value: T): Boolean;
2376+
var
2377+
hashTable: PHashTable;
2378+
item: PByte;
2379+
itemCount, itemSize, targetIndex, offset: Integer;
2380+
comparer: Pointer;
23812381
begin
2382-
if fOffset = THashTable.KeyOffset then // means this is for the key
2383-
Result := fHashTable.Find(value) <> nil
2382+
if fOffset = KeyOffset then // means this is for the key
2383+
begin
2384+
item := IHashTable<T>(fHashTable).Find(value);
2385+
Result := Assigned(item);
2386+
end
23842387
else
2385-
Result := inherited Contains(value, fComparer);
2388+
begin
2389+
offset := fOffset;
2390+
hashTable := fHashTable;
2391+
item := hashTable.Items;
2392+
itemCount := hashTable.ItemCount;
2393+
itemSize := hashTable.ItemSize;
2394+
comparer := Pointer(fComparer);
2395+
while itemCount > 0 do
2396+
begin
2397+
if PInteger(item)^ >= 0 then
2398+
if IEqualityComparer<T>(comparer).Equals(PT(item + offset)^, value) then
2399+
Exit(True);
2400+
Inc(item, itemSize);
2401+
Dec(itemCount);
2402+
end;
2403+
Result := False;
2404+
end;
23862405
end;
23872406

23882407
function TInnerCollection<T>.GetCount: Integer;

0 commit comments

Comments
 (0)