[fpc-devel] Management operators AddRef and Copy vs Copy

Florian Klämpfl florian at freepascal.org
Tue Apr 12 21:41:58 CEST 2016


Am 10.04.2016 um 18:53 schrieb Maciej Izak:
> 2016-04-10 14:45 GMT+02:00 Florian Klämpfl <florian at freepascal.org <mailto:florian at freepascal.org>>:
> 
>     I think this is the wrong way:
>     - AddRef means only to increase the ref. count of the passed data structure
>     - Copy is no deep copy, it means only: copy the current data structure, if it references managed
>     types, their ref. count is increased but they are not copied
> 
>     Example with dyn. arrays:
>     - AddRef increases the ref. count of the passed array, not its members
>     - Copy creates a copy of the array, if the members of the array are managed, their ref. count is
>     increased
> 
>     So I would call the operator Copy, in case of custom implemented ref. counted records, this would be
>     an AddRef operation. For a real copy, a procedure like Clone should be declared.
> 
> 
> Proposed implementation is compatible with internal rtti.inc usage (FPC_ADDREF and FPC_COPY). In my
> example I mean dyn array of records and related usage of operators only in context of items of those
> array.
> 
> Important note:
> operator Initialize is called after system int_initialize for required record fields
> operator Finalize is called before system int_finalize for required record fields
> operator AddRef is called after int_addref for required fields
> operator Copy is called after fpc_Copy_internal for required fields
> 
> note for note:
> in current FPC implementation int_initialize = FPC_INITIALIZE, int_finalize = FPC_FINALIZE,
> int_addref = FPC_ADDREF, fpc_Copy_internal = FPC_COPY
> 
> Let me explain this with complex example:
> 
> === code begin ===
> type
>   TFoo = record // record with all management operators. Existence of management operators means
> that the record became managed
>   public
>     {... some field definitions ...  }
>   private
>     class operator Initialize(var aFoo: TFoo);
>     class operator Finalize(var aFoo: TFoo);
>     class operator AddRef(var aFoo: TFoo);
>     class operator Copy(constref aSrc: TFoo; var aDst: TFoo);
>   end;
> 
> procedure TestValue(Value: TFoo); begin end;
> procedure TestVar(var Value: TFoo); begin end;
> procedure TestConst(const Value: TFoo); begin end;
> procedure TestOut(out Value: TFoo); begin end;
> procedure TestConstref(constref Value: TFoo); begin end;
> 
>   TFooArray = array of TFoo;
> 
> var
>   Foos: TFooArray;
>   Foos2: TFooArray;
> begin
>   SetLength(Foos, 5); // call 5x FPC_INITIALIZE and 5x TFoo.Initialize
>   SetLength(Foos, 6); // call 1x FPC_INITIALIZE and 1x TFoo.Initialize
>   SetLength(Foos, 5); // call 1x FPC_FINALIZE and 1x TFoo.Finalize
>   Foos2 := Copy(Foos); // call 5x FPC_ADDREF and 5x TFoo.AddRef
>   Foos2[0] := Foos[1]; // call 1x FPC_COPY and 1x TFoo.Copy
> 
>   // call 1x FPC_ADDREF and 1x TFoo.AddRef
>   TestValue(Foos2[1]);
>   // call 1x FPC_FINALIZE and 1x TFoo.Finalize
> 
>   // ... none
>   TestVar(Foos2[1]);
>   // ... none
> 
>   // ... none
>   TestConst(Foos2[1]);
>   // ... none
> 
>   // call 1x FPC_FINALIZE and 1x TFoo.Finalize
>   // call 1x FPC_INITIALIZE and 1x TFoo.Initialize
>   TestOut(Foos2[1]);
>   // ... none
> 
>   // ... none
>   TestConstref(Foos2[1]);
>   // ... none
> 
> end;  // call 10x FPC_FINALIZE and 10x TFoo.Finalize (for Foos and Foos2)
> === code end ===

Besides the naming, looks good to me.

> 
> As far as I understand your proposal is to use TFoo.Clone instead of  TFoo.Copy and TFoo.Copy
> instead of TFoo.AddRef. That is correct?

Yes. Maybe we have to do some more research what appropriate names are, the names in system.pp are
historic.

> IMO a little confusing from system.pp point of view ;)
> 

Yes. Addref is IMO something which is implementation specific and should not be exposed. C++ does
not know natively (!) ref. counted types. Instead the copy constructor does the ref. counting and a
separate method normally does the deep copy. So the question arises imo if the deep copy deserves an
own operator.



More information about the fpc-devel mailing list