@@ -1923,7 +1923,7 @@ TLazyInitializer = record
19231923
19241924 { $REGION 'Shared smart pointer'}
19251925
1926- { $IFDEF DELPHIXE6_UP}{ $RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS(DefaultFieldRttiVisibility )}{ $ENDIF}
1926+ { $IFDEF DELPHIXE6_UP}{ $RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([] )}{ $ENDIF}
19271927
19281928 IShared<T> = reference to function: T;
19291929
@@ -2014,37 +2014,17 @@ THandleFinalizer<T> = class(TInterfacedObject, IShared<T>)
20142014
20152015 { $REGION 'Weak smart pointer'}
20162016
2017- { $IFDEF DELPHIXE6_UP}{ $RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS(DefaultFieldRttiVisibility)}{ $ENDIF}
2018-
2019- TWeakReference = class abstract (TRefCountedObject)
2020- private
2021- fTarget: Pointer;
2022- class procedure RegisterWeakRef (address: Pointer; instance: Pointer); static;
2023- class procedure UnregisterWeakRef (address: Pointer; instance: Pointer); static;
2024- end ;
2017+ { $IFDEF DELPHIXE6_UP}{ $RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])}{ $ENDIF}
20252018
20262019 Weak<T> = record
2027- strict private type
2028- IWeakReference = interface
2029- procedure SetTarget (const value : T);
2030- end ;
2031-
2032- TWeakReference = class (TWeakReference, IWeakReference)
2033- private
2034- procedure SetTarget (const value : T);
2035- constructor Create(const target: T; var ref: PPointer);
2036- public
2037- destructor Destroy; override;
2038- end ;
20392020 strict private
2021+ fReference: IInterface;
20402022 fTarget: PPointer;
2041- fReference: IWeakReference;
2042- function GetIsAlive : Boolean;
2023+ function GetIsAlive : Boolean; inline;
20432024 function GetTarget : T;
2044- procedure SetTarget (const value : T);
20452025 type PT = ^T;
20462026 public
2047- constructor Create(const target : T);
2027+ constructor Create(const value : T);
20482028
20492029 class operator Implicit(const value : Shared<T>): Weak<T>;
20502030 class operator Implicit(const value : T): Weak<T>;
@@ -2054,10 +2034,49 @@ TWeakReference = class(TWeakReference, IWeakReference)
20542034 class operator NotEqual(const left: Weak<T>; const right: T): Boolean; inline;
20552035
20562036 function TryGetTarget (out target: T): Boolean;
2057- property Target: T read GetTarget write SetTarget ;
2037+ property Target: T read GetTarget;
20582038 property IsAlive: Boolean read GetIsAlive;
20592039 end ;
20602040
2041+ Weak = record
2042+ private type
2043+ PReference = ^TReference;
2044+ TReference = record
2045+ private
2046+ Vtable: Pointer;
2047+ RefCount: Integer;
2048+ Target: Pointer;
2049+ function QueryInterface (const IID: TGUID; out Obj): HResult; stdcall;
2050+ function _AddRef : Integer; stdcall;
2051+ function _Release_Obj : Integer; stdcall;
2052+ function _Release_Intf : Integer; stdcall;
2053+ end ;
2054+
2055+ PWeakRec = ^TWeakRec;
2056+ TWeakRec = record
2057+ Ref: PReference;
2058+ Target: PPointer;
2059+ end ;
2060+
2061+ const
2062+ ObjectReferenceVtable: array [0 ..2 ] of Pointer =
2063+ (
2064+ @TReference.QueryInterface,
2065+ @TReference._AddRef,
2066+ @TReference._Release_Obj
2067+ );
2068+
2069+ InterfaceReferenceVtable: array [0 ..2 ] of Pointer =
2070+ (
2071+ @TReference.QueryInterface,
2072+ @TReference._AddRef,
2073+ @TReference._Release_Intf
2074+ );
2075+ private
2076+ class procedure MakeFromObject (const value ; var result); overload; static;
2077+ class procedure MakeFromInterface (const value ; var result); overload; static;
2078+ end ;
2079+
20612080 { $RTTI INHERIT
20622081 METHODS(DefaultMethodRttiVisibility)
20632082 FIELDS(DefaultFieldRttiVisibility)
@@ -3896,16 +3915,6 @@ function NopQueryInterface(inst: Pointer; const IID: TGUID; out Obj): HResult; s
38963915 Result := E_NOINTERFACE;
38973916end ;
38983917
3899- procedure RegisterWeakRef (address: Pointer; const instance: TObject);
3900- begin
3901- TWeakReference.RegisterWeakRef(address, instance);
3902- end ;
3903-
3904- procedure UnregisterWeakRef (address: Pointer; const instance: TObject);
3905- begin
3906- TWeakReference.UnregisterWeakRef(address, instance);
3907- end ;
3908-
39093918{ $ENDREGION}
39103919
39113920
@@ -8169,40 +8178,42 @@ class function Shared<T>.GetMake: IShared<T>;
81698178{ $REGION 'Shared'}
81708179
81718180class procedure Shared.Make (const value : TObject; var result);
8181+ var
8182+ finalizer: PObjectFinalizer absolute result;
81728183begin
8173- if Assigned(Pointer(result))
8174- and (AtomicDecrement(PObjectFinalizer(result).RefCount) = 0 ) then
8175- PObjectFinalizer(result).Value .Free
8184+ if Assigned(finalizer) and (AtomicDecrement(finalizer.RefCount) = 0 ) then
8185+ finalizer.Value .Free
81768186 else
81778187 begin
8178- GetMem(Pointer(result) , SizeOf(TObjectFinalizer));
8179- PObjectFinalizer(result) .Vtable := @Shared.ObjectFinalizerVtable;
8188+ GetMem(finalizer , SizeOf(TObjectFinalizer));
8189+ finalizer .Vtable := @Shared.ObjectFinalizerVtable;
81808190 { $IFDEF AUTOREFCOUNT}
8181- Pointer(PObjectFinalizer(result) .Value ) := nil ;
8191+ Pointer(finalizer .Value ) := nil ;
81828192 { $ENDIF}
81838193 end ;
8184- PObjectFinalizer(result) .RefCount := 1 ;
8185- PObjectFinalizer(result) .Value := value ;
8194+ finalizer .RefCount := 1 ;
8195+ finalizer .Value := value ;
81868196end ;
81878197
81888198class procedure Shared.Make (const value : Pointer; typeInfo: PTypeInfo; var result);
8199+ var
8200+ finalizer: PRecordFinalizer absolute result;
81898201begin
81908202 typeInfo := typeInfo.TypeData.RefType^;
8191- if Assigned(Pointer(result))
8192- and (AtomicDecrement(PRecordFinalizer(result).RefCount) = 0 ) then
8203+ if Assigned(finalizer) and (AtomicDecrement(finalizer.RefCount) = 0 ) then
81938204 begin
8194- FinalizeArray(PRecordFinalizer(result) .Value , typeInfo, 1 );
8195- FillChar(PRecordFinalizer(result) .Value ^, typeInfo.TypeData.RecSize, 0 );
8196- FreeMem(PRecordFinalizer(result) .Value );
8205+ FinalizeArray(finalizer .Value , typeInfo, 1 );
8206+ FillChar(finalizer .Value ^, typeInfo.TypeData.RecSize, 0 );
8207+ FreeMem(finalizer .Value );
81978208 end
81988209 else
81998210 begin
8200- GetMem(Pointer(result) , SizeOf(TRecordFinalizer));
8201- PRecordFinalizer(result) .Vtable := @Shared.RecordFinalizerVtable;
8211+ GetMem(finalizer , SizeOf(TRecordFinalizer));
8212+ finalizer .Vtable := @Shared.RecordFinalizerVtable;
82028213 end ;
8203- PRecordFinalizer(result) .RefCount := 1 ;
8204- PRecordFinalizer(result) .Value := value ;
8205- PRecordFinalizer(result) .TypeInfo := typeInfo;
8214+ finalizer .RefCount := 1 ;
8215+ finalizer .Value := value ;
8216+ finalizer .TypeInfo := typeInfo;
82068217end ;
82078218
82088219class procedure Shared.Make (typeInfo: PTypeInfo; var result);
@@ -8399,11 +8410,6 @@ procedure TWeakReferences.UnregisterWeakRef(address, instance: Pointer);
83998410var
84008411 WeakRefInstances: TWeakReferences;
84018412
8402- { $ENDREGION}
8403-
8404-
8405- { $REGION 'TWeakReference'}
8406-
84078413type
84088414 TVirtualClasses = class (Spring.VirtualClass.TVirtualClasses);
84098415
@@ -8416,14 +8422,14 @@ procedure WeakRefFreeInstance(const Self: TObject);
84168422 freeInstance(Self);
84178423end ;
84188424
8419- class procedure TWeakReference. RegisterWeakRef (address, instance: Pointer );
8425+ procedure RegisterWeakRef (address: Pointer; const instance: TObject );
84208426begin
84218427 TVirtualClasses.Default.Proxify(instance);
84228428 GetClassData(TObject(instance).ClassType).FreeInstance := WeakRefFreeInstance;
84238429 WeakRefInstances.RegisterWeakRef(address, instance);
84248430end ;
84258431
8426- class procedure TWeakReference. UnregisterWeakRef (address, instance: Pointer );
8432+ procedure UnregisterWeakRef (address: Pointer; const instance: TObject );
84278433begin
84288434 WeakRefInstances.UnregisterWeakRef(address, instance);
84298435end ;
@@ -8433,9 +8439,12 @@ class procedure TWeakReference.UnregisterWeakRef(address, instance: Pointer);
84338439
84348440{ $REGION 'Weak<T>'}
84358441
8436- constructor Weak<T>.Create(const target : T);
8442+ constructor Weak<T>.Create(const value : T);
84378443begin
8438- fReference := TWeakReference.Create(target, fTarget);
8444+ case TType.Kind<T> of
8445+ tkClass: Weak.MakeFromObject(value , fReference);
8446+ tkInterface: Weak.MakeFromInterface(value , fReference);
8447+ end ;
84398448end ;
84408449
84418450function Weak <T>.GetIsAlive: Boolean;
@@ -8445,18 +8454,9 @@ function Weak<T>.GetIsAlive: Boolean;
84458454
84468455function Weak <T>.GetTarget: T;
84478456begin
8457+ Result := Default(T);
84488458 if Assigned(fReference) then
8449- Result := PT(fTarget)^
8450- else
8451- Result := Default(T);
8452- end ;
8453-
8454- procedure Weak <T>.SetTarget(const value : T);
8455- begin
8456- if Assigned(fReference) then
8457- fReference.SetTarget(value )
8458- else
8459- fReference := TWeakReference.Create(value , fTarget);
8459+ Result := PT(fTarget)^;
84608460end ;
84618461
84628462function Weak <T>.TryGetTarget(out target: T): Boolean;
@@ -8470,20 +8470,25 @@ function Weak<T>.TryGetTarget(out target: T): Boolean;
84708470
84718471class operator Weak<T>.Implicit(const value : Shared<T>): Weak<T>;
84728472begin
8473- Result.Target := value .Value ;
8473+ case TType.Kind<T> of
8474+ tkClass: Weak.MakeFromObject(value .Value , Result.fReference);
8475+ tkInterface: Weak.MakeFromInterface(value .Value , Result.fReference);
8476+ end ;
84748477end ;
84758478
84768479class operator Weak<T>.Implicit(const value : T): Weak<T>;
84778480begin
8478- Result.Target := value ;
8481+ case TType.Kind<T> of
8482+ tkClass: Weak.MakeFromObject(value , Result.fReference);
8483+ tkInterface: Weak.MakeFromInterface(value , Result.fReference);
8484+ end ;
84798485end ;
84808486
84818487class operator Weak<T>.Implicit(const value : Weak<T>): T;
84828488begin
8489+ Result := Default(T);
84838490 if Assigned(value .fReference) then
84848491 Result := PT(value .fTarget)^
8485- else
8486- Result := Default(T);
84878492end ;
84888493
84898494class operator Weak<T>.Equal(const left: Weak<T>;
@@ -8507,32 +8512,99 @@ function Weak<T>.TryGetTarget(out target: T): Boolean;
85078512{ $ENDREGION}
85088513
85098514
8510- { $REGION 'Weak<T>.TWeakReference '}
8515+ { $REGION 'Weak'}
85118516
8512- constructor Weak<T>.TWeakReference.Create(const target: T; var ref: PPointer);
8517+ class procedure Weak.MakeFromObject (const value ; var result);
8518+ var
8519+ rec: PWeakRec;
85138520begin
8514- SetTarget(target);
8515- ref := @fTarget;
8521+ rec := @result;
8522+ if Assigned(rec.Ref) and (AtomicDecrement(rec.Ref.RefCount) = 0 ) then
8523+ begin
8524+ rec.Ref.RefCount := 1 ;
8525+ if rec.Ref.Target = Pointer(value ) then
8526+ Exit;
8527+ if Assigned(rec.Ref.Target) then
8528+ UnregisterWeakRef(rec.Target, rec.Ref.Target);
8529+ end
8530+ else
8531+ begin
8532+ GetMem(rec.Ref, SizeOf(TReference));
8533+ rec.Ref.Vtable := @Weak.ObjectReferenceVtable;
8534+ rec.Ref.RefCount := 1 ;
8535+ rec.Target := @rec.Ref.Target;
8536+ end ;
8537+
8538+ rec.Ref.Target := Pointer(value );
8539+ if Assigned(rec.Ref.Target) then
8540+ RegisterWeakRef(rec.Target, rec.Ref.Target);
85168541end ;
85178542
8518- destructor Weak<T>.TWeakReference.Destroy;
8543+ class procedure Weak.MakeFromInterface (const value ; var result);
8544+ var
8545+ rec: PWeakRec;
85198546begin
8520- SetTarget(Default(T));
8547+ rec := @result;
8548+ if Assigned(rec.Ref) and (AtomicDecrement(rec.Ref.RefCount) = 0 ) then
8549+ begin
8550+ rec.Ref.RefCount := 1 ;
8551+ if rec.Ref.Target = Pointer(value ) then
8552+ Exit;
8553+ if Assigned(rec.Ref.Target) then
8554+ UnregisterWeakRef(@rec.Ref.Target, IInterface(rec.Ref.Target) as TObject);
8555+ end
8556+ else
8557+ begin
8558+ GetMem(rec.Ref, SizeOf(TReference));
8559+ rec.Ref.Vtable := @Weak.InterfaceReferenceVtable;
8560+ rec.Ref.RefCount := 1 ;
8561+ rec.Target := @rec.Ref.Target;
8562+ end ;
8563+
8564+ rec.Ref.Target := Pointer(value );
8565+ if Assigned(rec.Ref.Target) then
8566+ RegisterWeakRef(@rec.Ref.Target, IInterface(rec.Ref.Target) as TObject);
85218567end ;
85228568
8523- procedure Weak <T>.TWeakReference.SetTarget(const value : T);
8569+
8570+ { $ENDREGION}
8571+
8572+
8573+ { $REGION 'Weak.TReference'}
8574+
8575+ function Weak.TReference .QueryInterface(const IID: TGUID;
8576+ out Obj): HResult;
85248577begin
8525- if Assigned(fTarget) then
8526- case TType.Kind<T> of
8527- tkClass: UnregisterWeakRef(@fTarget, fTarget);
8528- tkInterface: UnregisterWeakRef(@fTarget, IInterface(fTarget) as TObject);
8529- end ;
8530- fTarget := PPointer(@value )^;
8531- if Assigned(fTarget) then
8532- case TType.Kind<T> of
8533- tkClass: RegisterWeakRef(@fTarget, fTarget);
8534- tkInterface: RegisterWeakRef(@fTarget, IInterface(fTarget) as TObject);
8535- end ;
8578+ Result := E_NOINTERFACE;
8579+ end ;
8580+
8581+ function Weak.TReference ._AddRef: Integer;
8582+ begin
8583+ Result := AtomicIncrement(RefCount);
8584+ end ;
8585+
8586+ function Weak.TReference ._Release_Obj: Integer;
8587+ begin
8588+ Result := AtomicDecrement(RefCount);
8589+ if Result = 0 then
8590+ begin
8591+ if Assigned(Target) then
8592+ UnregisterWeakRef(@Target, Target);
8593+ Target := nil ;
8594+ FreeMem(@Self);
8595+ end ;
8596+ end ;
8597+
8598+ function Weak.TReference ._Release_Intf: Integer;
8599+ begin
8600+ Result := AtomicDecrement(RefCount);
8601+ if Result = 0 then
8602+ begin
8603+ if Assigned(Target) then
8604+ UnregisterWeakRef(@Target, IInterface(Target) as TObject);
8605+ Target := nil ;
8606+ FreeMem(@Self);
8607+ end ;
85368608end ;
85378609
85388610{ $ENDREGION}
0 commit comments