[fpc-devel] Initialize/Finalize management operators and Default intrinsic

Maciej Izak hnb.code at gmail.com
Wed Apr 13 15:24:27 CEST 2016


2016-04-12 17:15 GMT+02:00 Sven Barth <pascaldragon at googlemail.com>:

> > Maybe "run" for my idea is a bad word. We don't need to run any section
> before initialization section from system. What we need is the table/list
> with "fixed" variables which needs to be initialized in system.pp
> initialization (and finalized in finalization). I think that is doable.
>
> It doesn't matter. You need to run the initializer operators and these
> might rely on functionality that is not initialized yet. So the safest
> approach would definitely be to init these after all initialization
> sections and to document this and the reasons behind it. This also
> alleviates the need to use attributes for this (or a keyword or whatever).
>
Running the initializer operators after initialization is IMO bad idea...
Very "pascal incompatible" and confusing even for me ;). I see many
problems for that approach...

I think I have other solution (that also can help to solve old problems).
What is needed is new section like "managementinitialization" and
"managementfinalization" (to complement "initialization"/"finalization"
with a little different logic). managementinitialization should contains
only module related stuff (memory allocation etc.) mostly used/required by
Initialize management operators without dependencies nor complex logic. How
it supposed to work? Below is attached modified example presented by Thorsten
Engler and modified example presented by Sven + my invention ;).

Note: "$" prefix means -> invisible for programmer/created by compiler.

=== unit1 begin ===
unit unit1;

interface

uses
  InterfaceUsedUnit1,
  InterfaceUsedUnit2;

//...

Procedure $AddRef;
Procedure $Release;

type
  PSomeType = ^TSomeType;
  TSomeType = record
    ... with management operators
  end;

function GetSomething: PSomeType;

implementation

uses
  ImplementationUsedUnit;

var
  BufferForTSomeTypeManagementOperators: PByte;

procedure $Init;
begin
  InterfaceUsedUnit1.$AddRef;
  InterfaceUsedUnit2.$AddRef;
  ImplementationUsedUnit.$AddRef;
  //.. code from original initialization section goes here
end;

procedure $Finit;
begin
  //.. code from original finalization section goes here
  ImplementationUsedUnit.$Release;
  InterfaceUsedUnit2.$Release;
  InterfaceUsedUnit1.$Release;
end;

var
  $RefCount: Integer;

var
  gSomething: TSomeType;
  gSomething2: array[0..2] of TSomeType;

function GetSomething: PSomeType;
begin
  if not Assigned(gSomething.inst) then
    gSomething.inst := TObject.Create;
  Result := @gSomething;
end;

procedure $ManagementInit;
begin
  $managementinitialization(); // execute our new section for operators
purpose

  // genereted for all global variables with management operators
  InitializeArray(@gSomething, TypeInfo(TSomeType), 1); // call the
Initialize operator
  InitializeArray(@gSomething2[0], TypeInfo(TSomeType), 3);
end;

procedure $ManagementFinit;
begin
  // genereted for all global variables with management operators
  FinalizeArray(@gSomething, TypeInfo(TSomeType), 1); // call the Finalize
operator
  FinalizeArray(@gSomething2[0], TypeInfo(TSomeType), 3);

  $managementfinalization(); // execute our new section for operators
purpose
end;

procedure $AddRef;
begin
  If LockedInc($RefCount) = 1 then
  begin
    $ManagementInit;
    $Init;
  end;
end;

procedure $Release;
begin
  If LockedDec($RefCount) = 0 then
  begin
    $Finit;
    $ManagementFinit;
  end;
end;

managementinitialization // in the fact it is procedure with symbol
$managementinitialization
  BufferForInitializeOperator := GetMem(100);
initialization
  $AddRef;
finalization
  $Release;
managementfinalization // in the fact it is procedure with symbol
$managementfinalization
  FreeMem(BufferForInitializeOperator);
end.
=== unit1 end ===

simplified than unit1, but behind the scene is the same mechanism

=== unit2 begin ===
unit unit2;

interface

implementation

uses
  unit1;

//
initialization
  Writeln(GetSomething^.inst.ToString); // no memory leak anymore even if
inst is filled inside TSomeType.Initialize operator
end.
=== unit2 end ===

-- 
Best regards,
Maciej Izak
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20160413/045b2426/attachment.html>


More information about the fpc-devel mailing list