mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-30 23:43:40 +02:00
134 lines
2.7 KiB
ObjectPascal
134 lines
2.7 KiB
ObjectPascal
unit LazClasses;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
sysutils, Classes, LazMethodList;
|
|
|
|
type
|
|
|
|
{ TFreeNotifyingObject }
|
|
|
|
TFreeNotifyingObject = class
|
|
private
|
|
FFreeNotificationList: TMethodList;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure AddFreeeNotification(ANotification: TNotifyEvent);
|
|
procedure RemoveFreeeNotification(ANotification: TNotifyEvent);
|
|
end;
|
|
|
|
{ TRefCountedObject }
|
|
|
|
TRefCountedObject = class(TFreeNotifyingObject)
|
|
private
|
|
FRefCount: Integer;
|
|
protected
|
|
procedure DoFree; virtual;
|
|
property RefCount: Integer read FRefCount;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure AddReference;
|
|
procedure ReleaseReference;
|
|
end;
|
|
|
|
{ TRefCntObjList }
|
|
|
|
TRefCntObjList = class(TList)
|
|
protected
|
|
procedure Notify(Ptr: Pointer; Action: TListNotification); override;
|
|
end;
|
|
|
|
|
|
procedure ReleaseRefAndNil(var ARefCountedObject);
|
|
|
|
implementation
|
|
|
|
{ TFreeNotifyingObject }
|
|
|
|
constructor TFreeNotifyingObject.Create;
|
|
begin
|
|
FFreeNotificationList := TMethodList.Create;
|
|
inherited Create;
|
|
end;
|
|
|
|
destructor TFreeNotifyingObject.Destroy;
|
|
begin
|
|
FFreeNotificationList.CallNotifyEvents(Self);
|
|
inherited Destroy;
|
|
FreeAndNil(FFreeNotificationList);
|
|
end;
|
|
|
|
procedure TFreeNotifyingObject.AddFreeeNotification(ANotification: TNotifyEvent);
|
|
begin
|
|
FFreeNotificationList.Add(TMethod(ANotification));
|
|
end;
|
|
|
|
procedure TFreeNotifyingObject.RemoveFreeeNotification(ANotification: TNotifyEvent);
|
|
begin
|
|
FFreeNotificationList.Remove(TMethod(ANotification));
|
|
end;
|
|
|
|
{ TRefCountedObject }
|
|
|
|
procedure TRefCountedObject.AddReference;
|
|
begin
|
|
Inc(FRefcount);
|
|
end;
|
|
|
|
procedure TRefCountedObject.DoFree;
|
|
begin
|
|
Self.Free;
|
|
end;
|
|
|
|
constructor TRefCountedObject.Create;
|
|
begin
|
|
FRefCount := 0;
|
|
inherited;
|
|
end;
|
|
|
|
destructor TRefCountedObject.Destroy;
|
|
begin
|
|
Assert(FRefcount = 0, 'Destroying referenced object');
|
|
inherited;
|
|
end;
|
|
|
|
procedure TRefCountedObject.ReleaseReference;
|
|
begin
|
|
Assert(FRefCount > 0, 'TRefCountedObject.ReleaseReference RefCount > 0');
|
|
Dec(FRefCount);
|
|
if FRefCount = 0 then DoFree;
|
|
end;
|
|
|
|
{ TRefCntObjList }
|
|
|
|
procedure TRefCntObjList.Notify(Ptr: Pointer; Action: TListNotification);
|
|
begin
|
|
case Action of
|
|
lnAdded: TRefCountedObject(Ptr).AddReference;
|
|
lnExtracted,
|
|
lnDeleted: TRefCountedObject(Ptr).ReleaseReference;
|
|
end;
|
|
end;
|
|
|
|
procedure ReleaseRefAndNil(var ARefCountedObject);
|
|
begin
|
|
Assert( (Pointer(ARefCountedObject) = nil) or
|
|
(TObject(ARefCountedObject) is TRefCountedObject),
|
|
'ReleaseRefAndNil requires TRefCountedObject');
|
|
|
|
if Pointer(ARefCountedObject) = nil then
|
|
exit;
|
|
|
|
if (TObject(ARefCountedObject) is TRefCountedObject) then
|
|
TRefCountedObject(ARefCountedObject).ReleaseReference;
|
|
Pointer(ARefCountedObject) := nil;
|
|
end;
|
|
|
|
end.
|
|
|