<div dir="ltr">Hi,<div><br></div><div><span style="font-size:12.8px">I'm pleased to finally announce (again but now officially ;) ) the additional record </span><span class="gmail-m_8743638140598548299gmail-m_8356926166533102833gmail-il" style="font-size:12.8px">operators</span><span style="font-size:12.8px">: Initialize, Finalize, AddRef and Copy. Available in latest FPC trunk (r35485):</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">1. operator Initialize - is called </span><span style="color:rgb(0,0,0);white-space:pre-wrap">after</span><span style="font-size:12.8px"> memory allocation for record (</span><span style="color:rgb(0,0,0);white-space:pre-wrap">called *after* FPC internal call recordrtti(data,typeinfo,@int_initialize);)</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">2. operator Finalize -  is called when record goes out of scope (called *before* </span><span style="color:rgb(0,0,0);white-space:pre-wrap">FPC internal call </span><span style="color:rgb(0,0,0);white-space:pre-wrap">recordrtti(data,typeinfo,@int_finalize);)</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">3. operator AddRef - is </span><span style="font-size:12.8px">called after the contents of a </span><span style="font-size:12.8px">record has been duplicated </span><span style="font-size:12.8px">by copying the contents byte by byte (</span><span style="color:rgb(0,0,0);white-space:pre-wrap">called *after* FPC internal call</span><span style="font-size:12.8px"> recordrtti(data,typeinfo,@int_addref);  )</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">4. operator Copy - Copy operator (if exists) is called *instead of* default copy behavior. Operator is responsible for </span><span style="font-size:12.8px">copying everything that's needed from the source to the target.</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">AddRef and Copy might be at beginning a little hard for understanding but we have good explanation provided by Thorsten Engler in topic "Management operators : Copy and Clone confusion..." :</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">=== quote begin ===</span></div><div><span style="font-size:12.8px">the reason for both to exist is that there are cases (e.g.</span><br style="font-size:12.8px"><span style="font-size:12.8px">passing an interface parameter) where the callee is responsible for any</span><br style="font-size:12.8px"><span style="font-size:12.8px">lifetime management implications (and the caller might not even be</span><br style="font-size:12.8px"><span style="font-size:12.8px">implemented using fpc). The caller just passes the interface pointer on the</span><br style="font-size:12.8px"><span style="font-size:12.8px">stack (or in a register), which, while it creates a copy of the bytes, does</span><br style="font-size:12.8px"><span style="font-size:12.8px">not actually invoke the copy operator. In cases where reference counting is</span><br style="font-size:12.8px"><span style="font-size:12.8px">required (parameter not marked as const), the callee may decide to simply</span><br style="font-size:12.8px"><span style="font-size:12.8px">use the value that was passed on the stack as the backing for the parameter,</span><br style="font-size:12.8px"><span style="font-size:12.8px">so it calls AddRef on that, without performing another copy.</span><br style="font-size:12.8px"><br style="font-size:12.8px"><span style="font-size:12.8px">Given this context, I find the terms AddRef and Copy to be perfectly</span><br style="font-size:12.8px"><span style="font-size:12.8px">adequate, even when applied to types that aren't strictly speaking</span><br style="font-size:12.8px"><span style="font-size:12.8px">performing reference counting; e.g. IIRC, AddRef for a BSTR (ole string type</span><br style="font-size:12.8px"><span style="font-size:12.8px">for windows which does NOT have a reference count) actually involves making</span><br style="font-size:12.8px"><span style="font-size:12.8px">a copy of the string contents and replacing the BSTR pointer.</span><br style="font-size:12.8px"><br style="font-size:12.8px"><span style="font-size:12.8px">AddRef here means "this is now an *additional* *reference* to whatever these</span><br style="font-size:12.8px"><span style="font-size:12.8px">bytes might refer to".</span><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">=== quote end ===</span></div><div><span style="font-size:12.8px"><br></span></div><div>my 2 cents for above: AddRef exist to speed up things.</div><div><br></div><div><span style="font-size:12.8px">New set of operators is unique and is called "management operators". That is because:</span><br></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">A. each of record (even non managed or even empty) with management operator becomes managed type.</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">B. is possible to implement new custom types (also thanks to other operators) with own </span><span style="font-size:12.8px">management</span><span style="font-size:12.8px"> of memory (new string types, fast TValue implementations without hacks on RTL etc.).</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">C.</span><span style="font-size:12.8px"> </span><span style="font-size:12.8px">"management operators" have no result.</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">D. For management operators is generated simple VMT (thanks to this is possible to work with management operators together with all RTL functions like InitializeArray/FinalizeArray).</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">=== example declaration begin ===</span><br></div><div><div><span style="font-size:12.8px">  PFoo = ^TFoo;</span></div><div><span style="font-size:12.8px">  TFoo = record</span></div><div><span style="font-size:12.8px">  private</span></div><div><span style="font-size:12.8px">    class operator Initialize(var a: TFoo);</span></div><div><span style="font-size:12.8px">    class operator Finalize(var a: TFoo);</span></div><div><span style="font-size:12.8px">    class operator AddRef(var a: TFoo);</span></div><div><span style="font-size:12.8px">    class operator Copy(constref aSrc: TFoo; var aDst: TFoo);</span></div></div><div><span style="font-size:12.8px">  end;</span></div><div><span style="font-size:12.8px">=== example declaration end ===</span><div><br></div><div>Management Operators feature can be used for many things:</div><div><br></div><div>* support for value types</div><div>* nullable types</div><div>* some custom ARC variations</div><div>* speed up existing types</div><div>* very fast RTTI.TValue implementation</div><div>* as replacement for manually called Init/Done record methods like in mORMot for many types (for example SynCommons.TSynLocker).</div><div>* auto init/finit for pointers/classes/simple types or whatever we have in Pascal</div><div><br></div><div><div style="font-size:12.8px">It works correctly in all possible ways with RTL: </div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">* New (Initialize)</div><div style="font-size:12.8px">* Dispose (Finalize)</div><div style="font-size:12.8px">* Initialize (Initialize)</div><div style="font-size:12.8px">* Finalize (Finalize)</div><div style="font-size:12.8px">* InitializeArray (Initialize)</div><div style="font-size:12.8px">* FinalizeArray (Finalize)</div><div style="font-size:12.8px">* SetLength (Initialize/Finalize)</div><div style="font-size:12.8px">* Copy (AddRef)</div><div style="font-size:12.8px">* RTTI.IsManaged</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">Managements operators are often called implicitly in many cases. Few examples:</div><div style="font-size:12.8px"><br></div><div style="font-size:12.8px">* global variables<span style="font-size:12.8px"> </span><span style="font-size:12.8px">(Initialize/Finalize<wbr>)</span></div><div style="font-size:12.8px">* local variables<span style="font-size:12.8px"> </span><span style="font-size:12.8px">(Initialize/Finalize<wbr>)</span></div><div style="font-size:12.8px">* for fields inside: records, objects, classes<span style="font-size:12.8px"> </span><span style="font-size:12.8px">(Initialize/Finalize)</span></div></div><div>* variable assignment (Copy)</div><div>* for parameters for routines (AddRef/Finalize/none - depends on modifiers like var/constref/cons)</div><div><br></div><div>Own experiments recommended! :)<br></div><div><br></div><div>Complex example and test:</div><div><a href="http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/tests/test/tmoperator8.pp?view=co&content-type=text%2Fplain" target="_blank">http://svn.freepascal.org/cgi-<wbr>bin/viewvc.cgi/trunk/tests/tes<wbr>t/tmoperator8.pp?view=co&conte<wbr>nt-type=text%2Fplain</a></div><div><br></div><div><span style="font-size:12.8px">Note: Lazarus </span><span style="font-size:12.8px">(trunk version)</span><span style="font-size:12.8px"> has support for all new operators syntax (thanks for Mattias Gaertner).</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">Future directions and opened doors (where management operators can be used but not directly):</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">+ "default" field for better handling smart pointers / nullable types (maybe will be introduced new type called proxy record for handling "default" modifier) (eg. <a href="https://github.com/maciej-izak/PascalSmartPointers">https://github.com/maciej-izak/PascalSmartPointers</a> compilable with NewPascal)</span></div><div><span style="font-size:12.8px">+ New VMT entry "vmtManagedInit" for "Initialize operator" for record fields inside classes (optimization)</span></div><div><span style="font-size:12.8px">+ Base for Nullable types syntax sugar</span></div><div><span style="font-size:12.8px">+ Probably base in some way for ARC classes (DELPHINEXTGEN compiler mode)</span></div><div><span style="font-size:12.8px">+ More Oxygene compatibility</span></div><div><span style="font-size:12.8px">+ Aspects</span></div><div><span style="font-size:12.8px"><br></span></div><div><span style="font-size:12.8px">Note for myself: </span><span style="font-size:12.8px">document the feature on the wiki in New Features Trunk and the changes to the Rtti in User Changes Trunk :)</span></div><div><span style="font-size:12.8px"><br></span></div>-- <br><div class="gmail-m_8743638140598548299gmail-m_8356926166533102833gmail_signature"><div dir="ltr"><div>Best regards,<br>Maciej Izak</div></div></div>
</div></div>