[fpc-pascal] interfaces and smartpointers [was Traits Proposal]
Benito van der Zander
benito at benibela.de
Wed Feb 17 16:27:08 CET 2021
Hi,
>
> (1) A record is not a pointer. So that would require some implicit
> referencing in the property
>
> (2) If it was managed, it would be an allocation, so I don't
> understand this.
I am talking about replacing interfaces with an record.
For example this
/////////////////////////////////////
type ITest = interface
procedure println;
end;
TTest = class(TInterfacedObject, ITest)
v: integer;
constructor Create(av: integer);
procedure println;
end;
constructor TTest.Create(av: integer);
begin
v := av;
end;
procedure TTest.println;
begin
writeln(v);
end;
var c: ITest;
begin
c := TTest.Create(123);
c.println;
/////////////////////////////////
would become:
/////////////////////////////////
type
TTestRec = class
rc: Integer;
v: integer;
constructor Create(av: integer);
procedure println;
end;
RTest = record
ptr: TTestRec;
procedure println; inline;
class operator :=(c: TTestRec): RTest;
class operator Initialize(var aRec: RTest);
class operator finalize(var aRec: RTest);
class operator AddRef(var aRec: RTest);
end;
constructor TTestRec.Create(av: integer);
begin
v := av;
end;
procedure TTestRec.println;
begin
writeln(v);
end;
procedure RTest.println;
begin
ptr.println; //the wrapper function is inlined
end;
class operator RTest.:=(c: TTestRec): RTest;
begin
result := default(RTest);
result.ptr := c;
if c <> nil then
InterlockedIncrement(c.rc);
end;
class operator RTest.Initialize(var aRec: RTest);
begin
aRec.ptr := nil;
end;
class operator RTest.finalize(var aRec: RTest);
begin
if aRec.ptr <> nil then
if InterlockedDecrement(aRec.ptr.rc) = 0 then
aRec.ptr.Free;
end;
class operator RTest.AddRef(var aRec: RTest);
begin
if aRec.ptr <> nil then
InterlockedIncrement(aRec.ptr.rc);
end;
var
r: RTest;
begin
r := TTestRec.Create(123);
r.println;
/////////////////////////////////////////////////////////
Or even replace the class with a record, too:
/////////////////////////////////////////////////////////
type
PTestRec2 = ^TTestRec2;
TTestRec2 = record
rc: Integer;
v: integer;
class function Create(av: integer): PTestRec2; static;
procedure println;
end;
RTest2 = record
ptr: ^TTestRec2;
procedure println; inline;
class operator :=(c: PTestRec2): RTest2;
class operator Initialize(var aRec: RTest2);
class operator finalize(var aRec: RTest2);
class operator AddRef(var aRec: RTest2);
end;
class function TTestRec2.Create(av: integer): PTestRec2;
begin
new(result);
result^.rc := 0;
result^.v := av;
end;
procedure TTestRec2.println;
begin
writeln(v);
end;
procedure RTest2.println;
begin
ptr^.println;
end;
class operator RTest2.:=(c: PTestRec2): RTest2;
begin
result := default(RTest2);
result.ptr := c;
if c <> nil then
InterlockedIncrement(c^.rc);
end;
class operator RTest2.Initialize(var aRec: RTest2);
begin
aRec.ptr := nil;
end;
class operator RTest2.finalize(var aRec: RTest2);
begin
if aRec.ptr <> nil then
if InterlockedDecrement(aRec.ptr^.rc) = 0 then
dispose(aRec.ptr);
end;
class operator RTest2.AddRef(var aRec: RTest2);
begin
if aRec.ptr <> nil then
InterlockedIncrement(aRec.ptr^.rc);
end;
var
r2: RTest2;
begin
r2 := TTestRec2.Create(123);
r2.println;
/////////////////////////////////////////////////////////
Not sure if it is actually faster. That needs to be investigated.
But it definitely helps with the memory usage:
writeln(ttest.InstanceSize);
writeln(ttestrec.InstanceSize);
writeln(sizeof(ttestrec2));
40
16
8
With many small objects it should be faster just because it fits better
in the cache.
Cheers,
Benito
On 17.02.21 14:31, Marco van de Voort via fpc-pascal wrote:
>
> Op 2021-02-17 om 00:02 schreef Benito van der Zander via fpc-pascal:
>>>
>>> And there often is a lot of unintentional deep copying. This is also
>>> why a property returning a record is fairly useless except for
>>> extremely small records like TPoint (and even that is not optimal no
>>
>> But a managed record to replace an interface, would only contain a
>> single pointer/class ref. That can be copied fast
>
> (1) A record is not a pointer. So that would require some implicit
> referencing in the property
>
> (2) If it was managed, it would be an allocation, so I don't
> understand this.
>
>
> _______________________________________________
> fpc-pascal maillist - fpc-pascal at lists.freepascal.org
> https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20210217/a196a510/attachment.htm>
More information about the fpc-pascal
mailing list