Re: [fpc-devel] (ref types / circles) Re: Defer keyword

2021-05-07 Thread Ryan Joseph via fpc-devel


> On May 7, 2021, at 2:52 PM, Sven Barth  wrote:
> 
> As said the main problem of reference counting on object instances, 
> especially if enabled by default like the Delphi NextGen compiler did, will 
> lead to problems in *existing* code and thus is a no-go. 
> 

What did you think about me other email that had ideas to add compiler 
directives like $M+? The way record management operators are implemented is 
that if you include any of the operators then the type becomes "managed" in the 
same way other ref counted types are handled.

For classes this is different because there is a hierarchy which is now altered 
but the compiler could still insert a hidden super class above it and use that 
to store the extra data. Indeed this would mean that existing classes (like the 
RTL) would not be eligible for reference counting unless it was compiled using 
said directive.

For example the follow class:

{$RETAINED+}
type
 TMyObject = class(TBaseClass)
 end;
{$RETAINED-}

would become:

type
 TMyObject_RefCounted = class abstract(TBaseClass)
  strict private
refCount: LongInt;
 end;
 TMyObject = class(TMyObject_RefCounted)
 end;

and now "TMyObject" is a managed type and Initialize/Finalize/AddRef/Copy will 
be called. It occurs to me now though that the ref counting would be tied to 
the type so if you cast the class to TObject and passed it around then ref 
counting wouldn't happen. Not sure if that's a deal breaker or not but it could 
easily cause hard to fix memory leaks just like normal classes. :)

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] (ref types / circles) Re: Defer keyword

2021-05-07 Thread Sven Barth via fpc-devel
Ryan Joseph via fpc-devel  schrieb am Fr.,
7. Mai 2021, 05:58:

>
>
> > On May 6, 2021, at 7:14 PM, Ryan Joseph  wrote:
> >
> > This can be detected at compile and at least give a warning. "a" is a
> member of TR and the element type of "a" is TR, then we're assigning TR to
> said array. It's that simple I think.
>
> It also occurs to me that record management operators already allow these
> types of circular references. It's just par for the course with ref
> counting and something programmers need to be aware of.
>

As said the main problem of reference counting on object instances,
especially if enabled by default like the Delphi NextGen compiler did, will
lead to problems in *existing* code and thus is a no-go.

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


[fpc-devel] Defer keyword

2021-05-07 Thread Luis Henrique via fpc-devel
07.05.2021, 06:09, "Michael Van Canneyt via fpc-devel" :On Fri, 7 May 2021, Sven Barth via fpc-devel wrote:  I thought it was agreed at the time that this was the most viable way forward ?  As far as I remember there wasn't really any agreement.Can be, I was not sure... I remember this path was investigated.  IIRC there was also the proposal that this could be done automatically using a keyword: varSomeClass : TSomeClass; dispose; The compiler can internally create the management record with a single default field and the needed management operator, so the user does not need to create all that.  I'm not aboard with such a keyword. The compiler should provide the necessary language mechanisms (default field, operator hoisting) and then there should be a default implementation as part of the RTL. There is no need to hide this behind a keyword, attribute or whatever.There is:Using a keyword, the compiler could also optimize things by simply initializingand freeing the instance if the usage of the object in the procedure allows it;it would allow to skip the record and operators and whatnot.I'm not proposing to abolish the record approach, just an additional automatismthat will use it, but allows to skip it for simple enough cases which areprobably the largest use-case.Don't forget that the record/management operator approach will again blow upbinary size; for every variable declared like this you risk creating a new type.The introduction of generics and their abundant use in Delphi has noticablyslowed down the compiler and increased binary sizes.To my dismay, compile times of 20 seconds up to 2 minutes have become notuncommon in Delphi. Something almmost unthinkable in D7 days.If that can be avoided by use of a keyword for 90% of use cases,I think it is worth thinking about it and not dismissing it offhand.Michael.___fpc-devel maillist - fpc-devel@lists.freepascal.orghttps://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-develI would love to see defer keyword in free pascal, but i think that at some degree we already can emulate it, see: program project2; {$mode objfpc}{$modeswitch advancedrecords} type  TDeferedProc = procedure of object;   TDefer = record    fProc: TDeferedProc;  public    procedure Enqueue(aProc: TDeferedProc);    class operator finalize(var aDefered: TDefer);  end;   { TSampleObj1 }   TSampleObj1 = class    procedure Echo;    destructor Destroy; override;  end;   TSampleObj2 = class(TSampleObj1); function Defer: TDefer;begin  Result.fProc:= nil;end; { TDefer } procedure TDefer.Enqueue(aProc: TDeferedProc);begin  fProc:= aProc;end; class operator TDefer.finalize(var aDefered: TDefer);begin  aDefered.fProc();end; { TSampleObj1 } procedure TSampleObj1.Echo;begin  WriteLn('Echo from ', ClassName);end; destructor TSampleObj1.Destroy;begin  Writeln('Freeing ', ClassName);   inherited;end; procedure MyProc;var  Obj1: TSampleObj1;  Obj2: TSampleObj2;begin  Obj1:= TSampleObj1.Create;  Obj2:= TSampleObj2.Create;   WriteLn('Objects created');   Defer.Enqueue(@Obj1.Free);  Defer.Enqueue(@Obj2.Free);   WriteLn('Objects freed defered');   Obj1.Echo;  Obj2.Echo;   WriteLn('End of MyProc');end; begin  MyProc;end. -- Luis Lima___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-07 Thread Ryan Joseph via fpc-devel


> On May 6, 2021, at 11:40 PM, Sven Barth  wrote:
> 
> There is no "finalization" section. It's really just an implicit try ... 
> finally block that the compiler inserts. Look for "cs_implicit_exceptions" 
> and "pi_needs_implicit_finally" if you want to learn more.

Does that mean if you disable implicit exceptions then ALL ref counted types 
leak memory? I could swear there was some post-routine code did all the cleanup 
stuff and called finalization* on different types. That's how record operators 
worked I thought and so i thought a defer keyword could simply hook into that 
system.


>> Either way looking at the programming language landscape the better way 
>> forward seems to be some opt-in ARC for TObject but I don't know if the 
>> compiler team is receptive to that (Sven made some attempt years ago but 
>> abandoned it). it's kind of frustrating that we have ref counted types but 
>> that isn't extended to classes. Hopefully that's something we can tackle one 
>> of these days...
> The problem is that the whole class tree needs to support it for it to work 
> correctly even if it's not the whole hierarchy that has as it enabled. That 
> means at least one additional field inside TObject that a) controls that 
> behavior and b) contains the reference count. This means that *all* class 
> instances increase by a LongInt. This might not sound like much, but FPC also 
> allows to work on smaller systems (and I don't mean the really small embedded 
> ones as those don't have TObject enabled anyway) and there an additional 
> LongInt for each instance might be critical.

That can never be an option to blow up TObject. I figured there could be 
something like a $M+ switch that would compile a class with ref counting. Then 
in the RTTI units we would simply have an entry for this new class type which 
had initialize/finalize/addref etc... functions. I saw this for record 
operators and dynamic arrays so I thought the system could be extended to 
classes.

> 
> If the reference count feature is optional (in addition to the above) then an 
> open question is what would happen if such a reference counted instance is 
> assigned to a non-reference counted one. This would need to take into account 
> all ways such an instance or type can be used including TClass.

That doesn't sound like a problem to me but I haven't thought about it deeply. 
If it was confusing there could be a new var section to denote ARC objects:

var
  someClass: TMyObject;
retained
  someClass: TMyObject;
begin
end;

{$RETAINED+}
type
  TMyObject = class
private
  someClass: TMyObject;
public retained
  someClass: TMyObject;
  otherClass:  TObject; // this would give an error because class is not 
compiled for ARC
  end;
{$RETAINED-}


Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-07 Thread Ryan Joseph via fpc-devel


> On May 7, 2021, at 9:40 AM, Benito van der Zander via fpc-devel 
>  wrote:
> 
> the classic Delphi way was to use an interface for freeing. It only requires 
> one type and nothing blows up.
> 

That's clever but even try..finally is less overhead.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


[fpc-devel] default property (was Defer keyword)

2021-05-07 Thread Ryan Joseph via fpc-devel


> On May 6, 2021, at 11:40 PM, Sven Barth  wrote:
> 
> In my opinion the better solution is to continue the road that Maciej started 
> and to implement that "default field" concept together with operator 
> hoistening so that records with management operators can be used as 
> containers. This is essentially the way it's done in C++ as well (e.g. we use 
> that extensively at work), but it needs some questions solved for the default 
> field functionality. This way the functionality is definitely optional and 
> can be controlled per-instance instead of per-type. What it wouldn't solve 
> however would be the assignment problems ("wrapped" to non-"wrapped" 
> instance) though that could be probably be more or less solved by only 
> allowing an explicit conversion to the non-"wrapped" instance.

If you remember I already started this but it got WAY out of hand and I had to 
basically abandon all my work on it because it was such a mess. The problem was 
we opened the possibility of default properties being used on any type (could 
be used for nullable types even) and this was in my opinion a mistake (at least 
for now).

I'm not 100% behind the default implements property Sven proposed for traits 
but it shares most of the functionality with the default property so maybe we 
should figure out how to constrain the default property and work on that angle. 
If I do continue on to the traits this code will be shared anyways.

What I learned is that hoisting the following members is very easy to implement:

- Methods
- Fields
- Properties

and these are much more complicated and had a massive code footprint on the 
compiler:

- Operators
- Assignments
- Array indexing
- Implicit conversions (like if, while statements etc... these where needed for 
nullable types but not for ARC)

From my experience I would say we ONLY allow Methods/Properties and MAYBE 
fields and then ignore all the other stuff. Default properties can ONLY be a 
class type now. There is already an := operator the record can implement and it 
works with management operators already. This covers 90% of the use cases for 
memory management and doesn't introduce all sorts of unpredictable stuff.

What about that?

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-07 Thread Ryan Joseph via fpc-devel


> On May 7, 2021, at 2:46 AM, Sven Barth via fpc-devel 
>  wrote:
> 
> I cannot speak for others, but I think 90% of potential use cases for ref 
> counting
> would be covered like this in my code: objects that only live inside a
> procedure.
> 
> I think the same. 

There's also a function which returns dynamically allocated memory but doesn't 
intend for you to keep it around very long. Cocoa/Objective-C has a good system 
for this which is an "autorelease pool" and while it's not language construct 
but rather a runtime system it does rely on an "Any" type (called id in 
Objective-C) so that methods can be chained together  like this:

a := TArray.Create([1,2,3]).AutoRelease;

We can't do this in Pascal because the AutoRelease functions return type is not 
compatible with the type of the caller. Could we add something like an "Any" 
return type to Pascal which is a type that is compatible with any class? This 
relies on an event loop that can capture this garbage and dispose of it but it 
goes a LONG way in helping with common memory management problems.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-07 Thread Benito van der Zander via fpc-devel

Hi,




Don't forget that the record/management operator approach will again 
blow up binary size; for every variable declared like this you risk 
creating a new type.


the classic Delphi way was to use an interface for freeing. It only 
requires one type and nothing blows up.


type
  TDefer = class(TInterfacedObject)
    toDefer: TObject;
    constructor Create(anobject: tobject);
    destructor destroy; override;
  end;

constructor TDefer.Create(anobject: tobject);
begin
  toDefer := anobject;
end;

destructor TDefer.destroy;
begin
  toDefer.free;
  inherited destroy;
end;

function deferedFree(obj: TObject): IUnknown;
begin
  result := TDefer.Create(obj);
end;

Then it can be used as:

procedure test;
var
  sl: TStringList;
begin
  sl := TStringList.Create;
  deferedFree(sl);
  writeln(sl.count);
end;


Unfortunately it fails in FreePascal because the interface is released 
too soon.





At worst, one could use a temporary variable in Delphi:

procedure test;
var
  sl: TStringList;
begin
  sl := TStringList.Create;
  var temp := deferedFree(sl);
  writeln(sl.count);
end;


The introduction of generics and their abundant use in Delphi has 
noticably slowed down the compiler and increased binary sizes. To my 
dismay, compile times of 20 seconds up to 2 minutes have become not 
uncommon in Delphi. Something almmost unthinkable in D7 days. 


With these generics they copied all the problems of C++. One of the 
worst ways of doing that


It would have been better to implement them like dynamic arrays. The 
generic code gets RTTI, the specialization does not generate any code, 
and just avoids explicit casting.



Cheers,
Benito
On 07.05.21 11:08, Michael Van Canneyt via fpc-devel wrote:



On Fri, 7 May 2021, Sven Barth via fpc-devel wrote:



I thought it was agreed at the time that this was the most viable way
forward ?



As far as I remember there wasn't really any agreement.


Can be, I was not sure... I remember this path was investigated.


IIRC there was also the proposal that this could be done automatically
using
a keyword:

var
   SomeClass : TSomeClass; dispose;

The compiler can internally create the management record with a single
default
field and the needed management operator, so the user does not need
to create all that.



I'm not aboard with such a keyword. The compiler should provide the
necessary language mechanisms (default field, operator hoisting) and 
then

there should be a default implementation as part of the RTL. There is no
need to hide this behind a keyword, attribute or whatever.


There is:

Using a keyword, the compiler could also optimize things by simply 
initializing and freeing the instance if the usage of the object in 
the procedure allows it; it would allow to skip the record and 
operators and whatnot.


I'm not proposing to abolish the record approach, just an additional 
automatism that will use it, but allows to skip it for simple enough 
cases which are

probably the largest use-case.

Don't forget that the record/management operator approach will again 
blow up binary size; for every variable declared like this you risk 
creating a new type.


The introduction of generics and their abundant use in Delphi has 
noticably slowed down the compiler and increased binary sizes. To my 
dismay, compile times of 20 seconds up to 2 minutes have become not 
uncommon in Delphi. Something almmost unthinkable in D7 days.


If that can be avoided by use of a keyword for 90% of use cases, I 
think it is worth thinking about it and not dismissing it offhand.


Michael.
___
fpc-devel maillist  - fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-07 Thread Ryan Joseph via fpc-devel


> On May 7, 2021, at 3:08 AM, Michael Van Canneyt via fpc-devel 
>  wrote:
> 
> The introduction of generics and their abundant use in Delphi has noticably 
> slowed down the compiler and increased binary sizes. To my dismay, compile 
> times of 20 seconds up to 2 minutes have become not uncommon in Delphi. 
> Something almmost unthinkable in D7 days.

Is it badly optimized or just overused? I don't have any way to compare but FPC 
seems pretty good with generics (Sven will know if there are any optimizations 
that could be made). Implicit function specialization will appear (at least at 
first) without any optimizations but I'll fix that later.

> 
> If that can be avoided by use of a keyword for 90% of use cases, I think it 
> is worth thinking about it and not dismissing it offhand.

I already raised the idea of an "auto" keyword some years ago already and it 
got rejected in favor of record operators.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-07 Thread Michael Van Canneyt via fpc-devel



On Fri, 7 May 2021, Sven Barth via fpc-devel wrote:



I thought it was agreed at the time that this was the most viable way
forward ?



As far as I remember there wasn't really any agreement.


Can be, I was not sure... I remember this path was investigated.


IIRC there was also the proposal that this could be done automatically
using
a keyword:

var
   SomeClass : TSomeClass; dispose;

The compiler can internally create the management record with a single
default
field and the needed management operator, so the user does not need
to create all that.



I'm not aboard with such a keyword. The compiler should provide the
necessary language mechanisms (default field, operator hoisting) and then
there should be a default implementation as part of the RTL. There is no
need to hide this behind a keyword, attribute or whatever.


There is:

Using a keyword, the compiler could also optimize things by simply initializing 
and freeing the instance if the usage of the object in the procedure allows it; 
it would allow to skip the record and operators and whatnot.


I'm not proposing to abolish the record approach, just an additional automatism 
that will use it, but allows to skip it for simple enough cases which are

probably the largest use-case.

Don't forget that the record/management operator approach will again blow up 
binary size; for every variable declared like this you risk creating a new type.


The introduction of generics and their abundant use in Delphi has noticably 
slowed down the compiler and increased binary sizes. 
To my dismay, compile times of 20 seconds up to 2 minutes have become not 
uncommon in Delphi. Something almmost unthinkable in D7 days.


If that can be avoided by use of a keyword for 90% of use cases, 
I think it is worth thinking about it and not dismissing it offhand.


Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-07 Thread Sven Barth via fpc-devel
Michael Van Canneyt via fpc-devel  schrieb
am Fr., 7. Mai 2021, 08:14:

>
>
> On Fri, 7 May 2021, Sven Barth via fpc-devel wrote:
>
> >
> > In my opinion the better solution is to continue the road that Maciej
> > started and to implement that "default field" concept together with
> > operator hoistening so that records with management operators can be
> > used as containers. This is essentially the way it's done in C++ as well
> > (e.g. we use that extensively at work), but it needs some questions
> > solved for the default field functionality. This way the functionality
> > is definitely optional and can be controlled per-instance instead of
> > per-type. What it wouldn't solve however would be the assignment
> > problems ("wrapped" to non-"wrapped" instance) though that could be
> > probably be more or less solved by only allowing an explicit conversion
> > to the non-"wrapped" instance.
>
> I thought it was agreed at the time that this was the most viable way
> forward ?
>

As far as I remember there wasn't really any agreement.


> IIRC there was also the proposal that this could be done automatically
> using
> a keyword:
>
> var
>SomeClass : TSomeClass; dispose;
>
> The compiler can internally create the management record with a single
> default
> field and the needed management operator, so the user does not need
> to create all that.
>

I'm not aboard with such a keyword. The compiler should provide the
necessary language mechanisms (default field, operator hoisting) and then
there should be a default implementation as part of the RTL. There is no
need to hide this behind a keyword, attribute or whatever.


> I cannot speak for others, but I think 90% of potential use cases for ref
> counting
> would be covered like this in my code: objects that only live inside a
> procedure.
>

I think the same.

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Defer keyword

2021-05-07 Thread Michael Van Canneyt via fpc-devel



On Fri, 7 May 2021, Sven Barth via fpc-devel wrote:



In my opinion the better solution is to continue the road that Maciej 
started and to implement that "default field" concept together with 
operator hoistening so that records with management operators can be 
used as containers. This is essentially the way it's done in C++ as well 
(e.g. we use that extensively at work), but it needs some questions 
solved for the default field functionality. This way the functionality 
is definitely optional and can be controlled per-instance instead of 
per-type. What it wouldn't solve however would be the assignment 
problems ("wrapped" to non-"wrapped" instance) though that could be 
probably be more or less solved by only allowing an explicit conversion 
to the non-"wrapped" instance.


I thought it was agreed at the time that this was the most viable way
forward ?

IIRC there was also the proposal that this could be done automatically using
a keyword:

var
  SomeClass : TSomeClass; dispose;

The compiler can internally create the management record with a single default 
field and the needed management operator, so the user does not need 
to create all that.


I cannot speak for others, but I think 90% of potential use cases for ref 
counting
would be covered like this in my code: objects that only live inside a
procedure.

Michael.
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel