Difference between revisions of "management operators"

From Lazarus wiki
Jump to navigationJump to search
Line 6: Line 6:
 
* It is now possible to implement new custom types with their own memory management, e.g: new string types, fast TValue implementations without hacks on RTL etc.<br>
 
* It is now possible to implement new custom types with their own memory management, e.g: new string types, fast TValue implementations without hacks on RTL etc.<br>
 
* Management operators have no result type as opposed to normal operators.<br>
 
* Management operators have no result type as opposed to normal operators.<br>
* A simple virtual method table is generated for the management oprators. Thanks to this is possible to work with management operators together with all RTL functions like InitializeArray and FinalizeArray.
+
* A simple virtual method table is generated for the management oprators. Thanks to this is possible to work with management operators together with all RTL functions like InitializeArray and FinalizeArray.<br><br>
 +
Management Operators features can be used for many things:
 +
 
 +
* support for value types
 +
* nullable types
 +
* some custom ARC variations
 +
* speed up existing types
 +
* very fast RTTI.TValue implementation
 +
* as replacement for manually called Init/Done record methods like in mORMot for many types (for example SynCommons.TSynLocker).
 +
* auto init/finit for pointers/classes/simple types or whatever we have in Pascal
 +
 
 +
It works correctly in all possible ways with RTL:
 +
 
 +
* New (Initialize)
 +
* Dispose (Finalize)
 +
* Initialize (Initialize)
 +
* Finalize (Finalize)
 +
* InitializeArray (Initialize)
 +
* FinalizeArray (Finalize)
 +
* SetLength (Initialize/Finalize)
 +
* Copy (AddRef)
 +
* RTTI.IsManaged
 +
 
 +
Managements operators are often called implicitly, for example:
 +
* Global variables (Initialize/Finalize)
 +
* Local variables (Initialize/Finalize)
 +
* For fields inside records, objects or classes (Initialize/Finalize)
 +
* Variable assignment (Copy)
 +
* For parameters for routines - AddRef/Finalize/none - this depends on modifiers like var/constref/const.
 +
 
  
 
=== Initialize ===
 
=== Initialize ===

Revision as of 12:04, 1 January 2018

Management Operators

From Free Pascal version 3.1.1 there is a new language feature called management operators for advanced records. The new operators are: Initialize, Finalize, AddRef and Copy. The new operators are a unique feature and are called "management operators". That is because:

  • each of record (even non managed or even empty) with management operator becomes a managed type.
  • It is now possible to implement new custom types with their own memory management, e.g: new string types, fast TValue implementations without hacks on RTL etc.
  • Management operators have no result type as opposed to normal operators.
  • A simple virtual method table is generated for the management oprators. Thanks to this is possible to work with management operators together with all RTL functions like InitializeArray and FinalizeArray.

Management Operators features can be used for many things:

  • support for value types
  • nullable types
  • some custom ARC variations
  • speed up existing types
  • very fast RTTI.TValue implementation
  • as replacement for manually called Init/Done record methods like in mORMot for many types (for example SynCommons.TSynLocker).
  • auto init/finit for pointers/classes/simple types or whatever we have in Pascal

It works correctly in all possible ways with RTL:

  • New (Initialize)
  • Dispose (Finalize)
  • Initialize (Initialize)
  • Finalize (Finalize)
  • InitializeArray (Initialize)
  • FinalizeArray (Finalize)
  • SetLength (Initialize/Finalize)
  • Copy (AddRef)
  • RTTI.IsManaged

Managements operators are often called implicitly, for example:

  • Global variables (Initialize/Finalize)
  • Local variables (Initialize/Finalize)
  • For fields inside records, objects or classes (Initialize/Finalize)
  • Variable assignment (Copy)
  • For parameters for routines - AddRef/Finalize/none - this depends on modifiers like var/constref/const.


Initialize

The initialize operator is called after memory allocation for a record and called after the internal compiler call to recordrtti(data,typeinfo,@int_initialize); It allows automatic initialization for a record. A simple example is:

{$if FPC_FULLVERSION < 30101}{$ERROR this demo needs version 3.1.1}{$endif}
{$mode delphi}{$macro on}
program TestInitialize;

type
    PRec = ^TRec;
    TRec = record
      I : Integer;
      class operator initialize(var aRec:TRec);
    end;

    class operator TRec.initialize(var aRec:TRec);
    begin
      aRec :=Default(TRec);
    end;

    procedure printTRec(r : PRec);
    begin
        WriteLn('Initialized TRec field i: ', r^.I = 0);
    end; 
var
 a,b:PRec; 
begin
    New(a);New(b);
    PrintTRec(a);
    PrintTRec(b);
    Dispose(a);Dispose(b);
end.

Finalize

Finalize is called when a record goes out of scope and called before the internal call to recordrtti(data,typeinfo,@int_finalize);
It is useful for automatic custom finalization code. A simple example looks like:
{$if FPC_FULLVERSION < 30101}{$ERROR this demo needs version 3.1.1}{$endif}
{$mode delphi}{$macro on}
program testfinalize;

type
    PRec = ^TRec;
    TRec = record
      I : Integer;
      class operator finalize(var aRec:TRec);
    end;

    class operator TRec.finalize(var aRec:TRec);
    begin
      writeln('Just to let you know: I am finalizing..');
    end;
var
 a,b:PRec; 
begin
    New(a);New(b);
    Dispose(a);Dispose(b);
end.

AddRef

AddRef is called after the contents of a record has been duplicated by copying the contents byte by byte and is called *after* FPC internal call recordrtti(data,typeinfo,@int_addref); By itself it does not any lifetime management, but you can use it to implement it. See also Copy.

Copy

The Copy operator, if implemented, is called instead of the default copy behavior. This operator is responsible for copying everything that's needed from the source to the target.