[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