Am 10.04.2016 um 18:53 schrieb Maciej Izak: > 2016-04-10 14:45 GMT+02:00 Florian Klämpfl <flor...@freepascal.org > <mailto:flor...@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. _______________________________________________ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel