[fpc-devel] Suggestion: reference counted objects

Sven Barth pascaldragon at googlemail.com
Sun Sep 21 14:25:30 CEST 2014


On 21.09.2014 13:20, Marco van de Voort wrote:
> In our previous episode, Sven Barth said:
>
> (as sb purely interested from an academic viewpoint, I have no real need for
> this)

Understood.

>> - a reference counted class (and its child classes) would include a
>> reference count field that the compiler knows how to access (for
>> automatic reference counting) and which can be accessed through RTTI
>> (for manual reference counting); it is *not* exposed as a regular field
>> as this might lead to identifier conflicts
>
> Does this mean multiple roots? That would make creating helpers for the
> refcounting different (since the field would be at a different offset
> everwhere)

No, not multiple roots. If a class is declared as refcounted (and it's 
parent class is not) then a hidden field is inserted into its list of 
fields, just as a normal one would, only that it isn't accesible using 
the "."-operator (because it won't have a valid Pascal identifier). The 
compiler of course knows the offset at compile time and at runtime the 
field can be accessed using the class' RTTI which would have a 
"RefCountOffset" field added (if that offset is < 0 then the object does 
not support reference counting).

>> - only *variables* (or parameters) that have a reference counted class
>> as its type will be subject to ARC; in extension this means that
>> assignments from/to a variable of a not reference counted base class
>> (e.g. TObject) will *not* change the reference count. Take this code for
>> example:
>
> One of the performance sinks with refcounting is passing parameters through
>   a call chain. (e.g. a class calling an inner class in a field to do the
> actual work, inherited() etc).
>
> How do you think to tackle that? With const?
>
> Maybe that can

In the same way it's a problem with strings, interfaces and arrays. They 
all react accordingly to var/const/constref by not changing the 
reference count. Reference counted classes would follow the same rules 
(consistency here). And of course as a user of reference counted classes 
one needs to be aware of the potential performance impact.

Did anyone till now really complain about the performance impact of 
reference counting on interfaces? Especially since they are used *so* 
much in today's OOP designs?

>> This will most likely result in "CreateObject" returning an instance to
>> class that is already freed (because the only reference inside
>> "CreateObject" is a (hypothetical) temporary of type "TARCObject" which
>> goes out of scope once "CreateObject" returns)
>
> It seems to me that implementation details of the return value handling
> (hidden/pseudo temp var etc) now trickle into the ARC design.
>
> Wouldn't it be more logical to make the result temp var a bit special so
> that it is not released when returned (requiring a
>
>     func(); // ignores return value
>
> to pop the result and decrease the refcount?

The function result is just a special case. This can also be achived 
with normal variables or parameters so it is important to have a 
consistent handling here. The only way to consistently handle this 
without making *all* object variables subject to reference counting 
again is to not have assignments of reference counted object instances 
from/to non-reference counted variables influence the reference count in 
any way.

Also this is compatible to how interfaces work, though the analogous 
interface example is highly constructed:

=== code begin ===

program tintfrefcount;

{$mode objfpc}

type
   TTestClass = class(TInterfacedObject, IInterface)
     destructor Destroy; override;
   end;

destructor TTestClass.Destroy;
begin
   Writeln('Destroy');
   inherited;
end;

function Test: TObject;
begin
   Result := (TTestClass.Create as IInterface) as TTestClass;
end;

var
   o: TObject;
begin
   o := Test;
   Writeln('After Test');
   o.Free;
end.

=== code end ===

Will result in:

=== output begin ===

Destroy
After Test

=== output end ===

Regards,
Sven



More information about the fpc-devel mailing list