{----------------------------------------------------------------------------- The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/MPL-1.1.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is: JvFinalize.pas, released on 2004-02-27. The Initial Developers of the Original Code is: Andreas Hausladen Copyright (c) 2004 Andreas Hausladen All Rights Reserved. You may retrieve the latest version of this file at the Project JEDI's JVCL home page, located at http://jvcl.sourceforge.net The purpose of this unit is to reduce code inclusion for functions that are not used by the program and which are only included because they are used in the finalization section. Known Issues: -----------------------------------------------------------------------------} // $Id: JvFinalize.pas,v 1.1 2004/12/10 13:38:16 ahuser Exp $ unit JvFinalize; {$I jvcl.inc} interface type TFinalizeProc = procedure; /// /// AddFinalizeProc adds a TFinalizeProc to the finalize section. /// The procedure is called on finalization. /// procedure AddFinalizeProc(const UnitName: string; FinalizeProc: TFinalizeProc); /// /// AddFinalizeObject adds an TObject derived class to the finalize section. /// The object is destroyed on finalization. /// function AddFinalizeObject(const UnitName: string; Instance: TObject): TObject; /// /// AddFinalizeObjectNil adds an TObject derived class to the finalize section. /// The object is destroyed and the reference is set to nil on finalization. /// The object is freed by "Obj.Free; Obj := nil;" /// /// /// Only global variables are allowed to be specified. /// function AddFinalizeObjectNil(const UnitName: string; var Reference{: TObject}): TObject; /// /// AddFinalizeFreeAndNil adds an TObject derived class to the finalize section. /// The reference is set to nil before the object is destroyed on finalization. /// /// /// Only global variables are allowed to be specified. /// function AddFinalizeFreeAndNil(const UnitName: string; var Reference{: TObject}): TObject; /// /// AddFinalizeMemory adds an memory allocation to the finalize section. /// The memory is released on finalization. /// function AddFinalizeMemory(const UnitName: string; Ptr: Pointer): Pointer; /// /// AddFinalizeMemory adds an memory allocation to the finalize section. /// The memory is released and the Ptr is set to nil on finalization. /// /// /// Only global variables are allowed to be specified. /// function AddFinalizeMemoryNil(const UnitName: string; var Ptr{: Pointer}): Pointer; /// /// FinalizeUnit finalizes all items from the unit UnitName. The UnitName is /// case sensitive. If you add any finalization item you must call this function /// to free the items. Otherwise the items will be destroyed when the package /// that contains the JvFinalize unit is unloaded. /// procedure FinalizeUnit(const UnitName: string); implementation type TFinalizeItem = class(TObject) public Next: TFinalizeItem; constructor Create(const AUnitName: string); end; TFinalizeUnitItem = class(TObject) public UnitName: string; Items: TFinalizeItem; Next: TFinalizeUnitItem; constructor Create(AUnitName: string; ANext: TFinalizeUnitItem); destructor Destroy; override; end; var FinalizeUnitList: TFinalizeUnitItem = nil; //=== { TFinalizeItem } ====================================================== constructor TFinalizeItem.Create(const AUnitName: string); var P: TFinalizeUnitItem; begin inherited Create; P := FinalizeUnitList; while P <> nil do begin if P.UnitName = AUnitName then Break; P := P.Next; end; if P = nil then begin FinalizeUnitList := TFinalizeUnitItem.Create(AUnitName, FinalizeUnitList); P := FinalizeUnitList; end; Next := P.Items; P.Items := Self; end; //=== { TFinalizeUnitItem } ================================================== constructor TFinalizeUnitItem.Create(AUnitName: string; ANext: TFinalizeUnitItem); begin inherited Create; UnitName := AUnitName; Next := ANext; end; destructor TFinalizeUnitItem.Destroy; var P: TFinalizeItem; begin while Items <> nil do begin P := Items; Items := P.Next; P.Free; end; inherited Destroy; end; /// /// FinalizeUnits destroys all remaining finalization items. /// procedure FinalizeUnits; var P: TFinalizeUnitItem; begin // Normally FinalizeUnitList should be nil because the units should call // FinalizeUnit() in their finalization section. while FinalizeUnitList <> nil do try while FinalizeUnitList <> nil do begin P := FinalizeUnitList; FinalizeUnitList := P.Next; P.Free; end; except // ignore, we are in the finalization section end; end; procedure FinalizeUnit(const UnitName: string); var N, P: TFinalizeUnitItem; begin N := nil; P := FinalizeUnitList; if P = nil then Exit; while P <> nil do begin if P.UnitName = UnitName then begin if N = nil then FinalizeUnitList := P.Next else N.Next := P.Next; P.Free; Break; end; N := P; P := P.Next; end; end; //============================================================================ type PObject = ^TObject; PPointer = ^Pointer; TFinalizeProcItem = class(TFinalizeItem) private FFinalizeProc: TFinalizeProc; public constructor Create(const AUnitName: string; AFinalizeProc: TFinalizeProc); destructor Destroy; override; end; TFinalizeObjectItem = class(TFinalizeItem) private FInstance: TObject; public constructor Create(const AUnitName: string; AInstance: TObject); destructor Destroy; override; end; TFinalizeObjectNilItem = class(TFinalizeItem) private FReference: PObject; public constructor Create(const AUnitName: string; var AReference: TObject); destructor Destroy; override; end; TFinalizeFreeAndNilItem = class(TFinalizeItem) private FReference: PObject; public constructor Create(const AUnitName: string; var AReference: TObject); destructor Destroy; override; end; TFinalizeMemoryItem = class(TFinalizeItem) private FPtr: Pointer; public constructor Create(const AUnitName: string; APtr: Pointer); destructor Destroy; override; end; TFinalizeMemoryNilItem = class(TFinalizeItem) private FPtr: PPointer; public constructor Create(const AUnitName: string; var APtr: Pointer); destructor Destroy; override; end; //=== { TFinalizeProcItem } ================================================== constructor TFinalizeProcItem.Create(const AUnitName: string; AFinalizeProc: TFinalizeProc); begin inherited Create(AUnitName); FFinalizeProc := AFinalizeProc; end; destructor TFinalizeProcItem.Destroy; begin FFinalizeProc; inherited Destroy; end; //=== { TFinalizeObjectItem } ================================================ constructor TFinalizeObjectItem.Create(const AUnitName: string; AInstance: TObject); begin inherited Create(AUnitName); FInstance := AInstance; end; destructor TFinalizeObjectItem.Destroy; begin FInstance.Free; inherited Destroy; end; //=== { TFinalizeObjectNilItem } ============================================= constructor TFinalizeObjectNilItem.Create(const AUnitName: string; var AReference: TObject); begin inherited Create(AUnitName); FReference := @AReference; end; destructor TFinalizeObjectNilItem.Destroy; begin FReference^.Free; FReference^ := nil; inherited Destroy; end; //=== { TFinalizeFreeAndNilItem } ============================================ constructor TFinalizeFreeAndNilItem.Create(const AUnitName: string; var AReference: TObject); begin inherited Create(AUnitName); FReference := @AReference; end; destructor TFinalizeFreeAndNilItem.Destroy; var Obj: TObject; begin Obj := FReference^; FReference^ := nil; Obj.Free; inherited Destroy; end; //=== { TFinalizeMemoryItem } ================================================ constructor TFinalizeMemoryItem.Create(const AUnitName: string; APtr: Pointer); begin inherited Create(AUnitName); FPtr := APtr; end; destructor TFinalizeMemoryItem.Destroy; begin if FPtr <> nil then FreeMem(FPtr); inherited Destroy; end; //=== { TFinalizeMemoryNilItem } ============================================= constructor TFinalizeMemoryNilItem.Create(const AUnitName: string; var APtr: Pointer); begin inherited Create(AUnitName); FPtr := @APtr; end; destructor TFinalizeMemoryNilItem.Destroy; begin if FPtr^ <> nil then begin FreeMem(FPtr^); FPtr^ := nil; end; inherited Destroy; end; //============================================================================ procedure AddFinalizeProc(const UnitName: string; FinalizeProc: TFinalizeProc); begin TFinalizeProcItem.Create(UnitName, FinalizeProc); end; function AddFinalizeObject(const UnitName: string; Instance: TObject): TObject; begin TFinalizeObjectItem.Create(UnitName, Instance); Result := Instance; end; function AddFinalizeObjectNil(const UnitName: string; var Reference{: TObject}): TObject; begin TFinalizeObjectNilItem.Create(UnitName, TObject(Reference)); Result := TObject(Reference); end; function AddFinalizeFreeAndNil(const UnitName: string; var Reference{: TObject}): TObject; begin TFinalizeFreeAndNilItem.Create(UnitName, TObject(Reference)); Result := TObject(Reference); end; function AddFinalizeMemory(const UnitName: string; Ptr: Pointer): Pointer; begin TFinalizeMemoryItem.Create(UnitName, Ptr); Result := Ptr; end; function AddFinalizeMemoryNil(const UnitName: string; var Ptr{: Pointer}): Pointer; begin TFinalizeMemoryNilItem.Create(UnitName, Pointer(Ptr)); Result := Pointer(Ptr); end; {$IFDEF MSWINDOWS} initialization finalization // asn: causes exceptions on linux FinalizeUnits; {$ENDIF MSWINDOWS} end.