Re: [fpc-devel] Defer keyword

2021-05-10 Thread Kostas Michalopoulos via fpc-devel

On 5/11/2021 4:09 AM, Ryan Joseph via fpc-devel wrote:




On May 10, 2021, at 5:59 PM, Kostas Michalopoulos via fpc-devel 
 wrote:

You do not need any special language feature for that, you can simply do 
something like

ReleaseLater(TObject.Create)


yes but we can't get back the reference. It's a small thing but making this 
possible as return type means we can chain the calls together and make it a one 
line statement. It's just a nice thing from Objective-C which we use heavily to 
manage memory and it works very well.


How about function ReleaseLater(Obj: TObject): TObject that simply 
returns Obj? (though TBH i can't say i am a fan of these chains from a 
readability perspective).


Kostas
___
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-10 Thread Ryan Joseph via fpc-devel


> On May 10, 2021, at 5:59 PM, Kostas Michalopoulos via fpc-devel 
>  wrote:
> 
> You do not need any special language feature for that, you can simply do 
> something like
> 
>ReleaseLater(TObject.Create)

yes but we can't get back the reference. It's a small thing but making this 
possible as return type means we can chain the calls together and make it a one 
line statement. It's just a nice thing from Objective-C which we use heavily to 
manage memory and it works very well.

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-10 Thread Kostas Michalopoulos via fpc-devel

On 5/8/2021 8:27 PM, Ryan Joseph via fpc-devel wrote:

That was a bad example. It's for ANY class really.

o := TObject.Create.AutoRelease;

Then next event cycle the autorelease pool frees all the objects added to it. 
Very simple but effective however we can't do this in Pascal without a new 
permissive return type.


You do not need any special language feature for that, you can simply do 
something like


ReleaseLater(TObject.Create)

and have ReleaseLater and ReleaseQueuedObjects procedures in a shared 
unit like


procedure ReleaseLater(Obj: TObject);
procedure ReleaseQueuedObjects;

and have ReleaseQueuedObjects called on app idle. LCL already has 
something like that with TApplication.ReleaseComponent but, as the name 
implies, it is only for TComponent instances. However nothing prevents 
you from making your own, it is just a few lines of code and certainly 
an app with flow complex enough to need such a construct wont be 
bothered by a few additional lines for this.


You could even use type helpers to make it look like a method :-P.

Kostas

___
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-08 Thread Ryan Joseph via fpc-devel


> On May 8, 2021, at 8:05 AM, Sven Barth  wrote:
> 
>> 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.
> 
> Dynamic arrays are reference counted, thus you don't need to do any manual 
> memory management on them.

That was a bad example. It's for ANY class really.

o := TObject.Create.AutoRelease;

Then next event cycle the autorelease pool frees all the objects added to it. 
Very simple but effective however we can't do this in Pascal without a new 
permissive return type. 

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-08 Thread Sven Barth via fpc-devel

Am 07.05.2021 um 17:57 schrieb 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.


Dynamic arrays are reference counted, thus you don't need to do any 
manual memory management on them.


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-08 Thread Sven Barth via fpc-devel

Am 07.05.2021 um 17:40 schrieb Benito van der Zander via fpc-devel:
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.


That would also be a much less flexible approach. The way it is now 
allows for much more functionality to be covered with generics.


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-08 Thread Jonas Maebe via fpc-devel
On 07/05/2021 07:26, Sven Barth via fpc-devel wrote:
> Trunk also supports POSIX exceptions on selected *nix based systems,
> though I haven't looked in depth yet in how far they incur a runtime
> penalty (also they need to be enabled by enabling them in the compiler
> and then recompiling everything, cause they're still experimental).

They're not POSIX, but DWARF-EH. They don't incur any cost except if an
exception is triggered (but then the cost is quite high).

They're also the only supported exception type when using the LLVM
backend (which is why adding Windows-support is more work than adding
support for other platforms to the LLVM backend, as even at the LLVM IR
level Windows exceptions are modeled differently).


Jonas
___
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-08 Thread Jonas Maebe via fpc-devel
On 07/05/2021 18:41, Ryan Joseph via fpc-devel wrote:
> Does that mean if you disable implicit exceptions then ALL ref counted types 
> leak memory?

Only if an exception occurs.


Jonas
___
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


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


Re: [fpc-devel] Defer keyword

2021-05-06 Thread Sven Barth via fpc-devel

Am 07.05.2021 um 00:32 schrieb Ryan Joseph via fpc-devel:



On May 6, 2021, at 4:26 PM, J. Gareth Moreton via fpc-devel 
 wrote:

There is a performance penalty when using them, which one reason why the 
compiler sources don't use them.  There's probably other reasons too.  There 
might be some speed-up potential where standard Exit calls are concerned, but 
I'm not sure.

I just did a search and I did indeed see a few try..finally blocks but not many. As I 
understand it there is a "finalization" section of each procedure which is used 
for ref counted objects so I assumed the statement was merely moved to that location but 
I guess there's some concerns over exceptions.
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.

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.


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.


If the reference count would be enabled by default for *all* instance 
(like Delphi did in its platform compilers but which they abandoned now) 
then you'd have a huge backwards compatibility problem, because there 
definitely are cycles out there and thus this option would be an 
absolute no-no.


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.


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-06 Thread Sven Barth via fpc-devel

Am 07.05.2021 um 00:17 schrieb Ryan Joseph via fpc-devel:



On May 6, 2021, at 4:05 PM, Sven Barth via fpc-devel 
 wrote:

Other than that, you're right and what Ryan is trying to do is definitely the 
intended purpose of try ... finally.


Is there any runtime code involved with try..finally or does it just reorganize 
the code to run at the end of the block? My understanding of the defer keyword 
is that is was just a fancy way to move some code into a block which always 
gets run with a function exits.
It depends on the platform. In general FPC uses setjmp/longjmp based 
exception handling, thus there is a slight penalty in setting up the 
exception frame (no matter if "finally" or "except").


In case of Win32 and Win64 the OS' Structured Exception Handling 
functionality is used. On i386-win32 there is still a runtime overhead 
due to how exceptions are managed, but on x86_64-win64 and aarch64-win64 
(and in theory also arm-wince and arm-win32, but we have no ARM support 
for SEH yet (and arm-win32 isn't implemented yet :P )) this is done 
through meta data located in the PE file (the .pdata and .xdata 
sections) which allows for an implicit setup of the frames and thus 
there'll only be a penalty if an exception occurrs (cause the OS and the 
exception handling code will have to parse that data).


Trunk also supports POSIX exceptions on selected *nix based systems, 
though I haven't looked in depth yet in how far they incur a runtime 
penalty (also they need to be enabled by enabling them in the compiler 
and then recompiling everything, cause they're still experimental).


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-06 Thread Nikolai Zhubr via fpc-devel

Hi,

07.05.2021 1:32, Ryan Joseph via fpc-devel:
[...]

it's kind of frustrating that we have ref counted types but that isn't extended 
to classes.


Indeed. However, unfortunately classes are substantially different in 
that they can cause reference circles, which then cause damage to ref 
counting, unless some severe complications are implemented, and then it 
will probably get close to garbage collection. Well, AFAIU.



Regards,
Nikolai



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-06 Thread Ryan Joseph via fpc-devel


> On May 6, 2021, at 4:26 PM, J. Gareth Moreton via fpc-devel 
>  wrote:
> 
> There is a performance penalty when using them, which one reason why the 
> compiler sources don't use them.  There's probably other reasons too.  There 
> might be some speed-up potential where standard Exit calls are concerned, but 
> I'm not sure.

I just did a search and I did indeed see a few try..finally blocks but not 
many. As I understand it there is a "finalization" section of each procedure 
which is used for ref counted objects so I assumed the statement was merely 
moved to that location but I guess there's some concerns over exceptions.

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...

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-06 Thread J. Gareth Moreton via fpc-devel
There is some special handling involved in that the code inside the try 
part (I think) is effectively a nested procedure.  It's important in the 
context of stack unwinding when an exception occurs.  There is a 
performance penalty when using them, which one reason why the compiler 
sources don't use them.  There's probably other reasons too.  There 
might be some speed-up potential where standard Exit calls are 
concerned, but I'm not sure.


Gareth aka. Kit

On 06/05/2021 23:17, Ryan Joseph via fpc-devel wrote:



On May 6, 2021, at 4:05 PM, Sven Barth via fpc-devel 
 wrote:

Other than that, you're right and what Ryan is trying to do is definitely the 
intended purpose of try ... finally.


Is there any runtime code involved with try..finally or does it just reorganize 
the code to run at the end of the block? My understanding of the defer keyword 
is that is was just a fancy way to move some code into a block which always 
gets run with a function exits.

Regards,
Ryan Joseph

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



--
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
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-06 Thread Ryan Joseph via fpc-devel


> On May 6, 2021, at 4:05 PM, Sven Barth via fpc-devel 
>  wrote:
> 
> Other than that, you're right and what Ryan is trying to do is definitely the 
> intended purpose of try ... finally.
> 

Is there any runtime code involved with try..finally or does it just reorganize 
the code to run at the end of the block? My understanding of the defer keyword 
is that is was just a fancy way to move some code into a block which always 
gets run with a function exits.

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-06 Thread Sven Barth via fpc-devel
J. Gareth Moreton via fpc-devel  schrieb am
Do., 6. Mai 2021, 20:03:

> The rule with try...finally is that, outside of something completely
> catastrophic that destroys the program flow, is that once you enter the
> try part, the finally part is guaranteed to be executed no matter how
> you leave it.
>

There are two exceptions (pun not intended :P ):

- Halt (or any other OS function that never returns and terminates the
process)
- LongJmp (because that knows nothing about exception handlers)

Other than that, you're right and what Ryan is trying to do is definitely
the intended purpose of try ... finally.

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-06 Thread J. Gareth Moreton via fpc-devel
The rule with try...finally is that, outside of something completely 
catastrophic that destroys the program flow, is that once you enter the 
try part, the finally part is guaranteed to be executed no matter how 
you leave it.


Gareth aka. Kit

On 06/05/2021 18:53, Ryan Joseph via fpc-devel wrote:



On May 6, 2021, at 11:39 AM, J. Gareth Moreton via fpc-devel 
 wrote:

In the example given:

  obj := TObject.Create;
  defer objects.Free;

What's wrong with Pascal's existing functionality?

  obj := TObject.Create;
  try
...
  finally
objects.Free;
  end;

If there's a concern about performance penalty, maybe the compiler can work 
something out for simple finally blocks and just copy the code to any Exit 
nodes found rather than calling the pseudo-procedure that a try...finally block 
creates.

I didn't know try..finally even worked like that. :) I thought it was just for 
exceptions but I see it captures exit also. The defer keyword is nicer on the 
eyes I would say because it don't require wrapping the entire function in a big 
block of code.

So never mind then I guess. I'll start using try..finally and see how that 
works for me.

Regards,
Ryan Joseph

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



--
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
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-06 Thread Ryan Joseph via fpc-devel


> On May 6, 2021, at 11:39 AM, J. Gareth Moreton via fpc-devel 
>  wrote:
> 
> In the example given:
> 
>  obj := TObject.Create;
>  defer objects.Free;
> 
> What's wrong with Pascal's existing functionality?
> 
>  obj := TObject.Create;
>  try
>...
>  finally
>objects.Free;
>  end;
> 
> If there's a concern about performance penalty, maybe the compiler can work 
> something out for simple finally blocks and just copy the code to any Exit 
> nodes found rather than calling the pseudo-procedure that a try...finally 
> block creates.

I didn't know try..finally even worked like that. :) I thought it was just for 
exceptions but I see it captures exit also. The defer keyword is nicer on the 
eyes I would say because it don't require wrapping the entire function in a big 
block of code.

So never mind then I guess. I'll start using try..finally and see how that 
works for me.

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-06 Thread J. Gareth Moreton via fpc-devel

In the example given:

  obj := TObject.Create;
  defer objects.Free;

What's wrong with Pascal's existing functionality?

  obj := TObject.Create;
  try
...
  finally
    objects.Free;
  end;

If there's a concern about performance penalty, maybe the compiler can 
work something out for simple finally blocks and just copy the code to 
any Exit nodes found rather than calling the pseudo-procedure that a 
try...finally block creates.


Gareth aka. Kit

On 06/05/2021 18:11, Ryan Joseph via fpc-devel wrote:



On May 6, 2021, at 10:44 AM, Marco van de Voort via fpc-devel 
 wrote:

But those types have refcounting built-in and always active. Things like defer don't, 
which makes that all objects gets refcounting overhead in case somebody needs it for 
"defer".

Contrary to Pascal both the language you reference have garbage collectors, so 
their objects are already managed anyway,

The idea of defer isn't necessarily about memory management but rather 
literally just deferring a statements execution until a predicable point in 
execution (end of a block or function). Those articles mentioned using them for 
file IO also so that you can be sure you're going to close the open file handle 
even if the function returns before. Memory management is just one obvious use 
case since we have this problem in Pascal often.

I don't think this even affects ref counting of existing types because it all 
it does it move the statement to the end of the block. Maybe I'm not 
understanding your point though.

Regards,
Ryan Joseph

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



--
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus

___
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-06 Thread Ryan Joseph via fpc-devel


> On May 6, 2021, at 10:44 AM, Marco van de Voort via fpc-devel 
>  wrote:
> 
> But those types have refcounting built-in and always active. Things like 
> defer don't, which makes that all objects gets refcounting overhead in case 
> somebody needs it for "defer".
> 
> Contrary to Pascal both the language you reference have garbage collectors, 
> so their objects are already managed anyway,

The idea of defer isn't necessarily about memory management but rather 
literally just deferring a statements execution until a predicable point in 
execution (end of a block or function). Those articles mentioned using them for 
file IO also so that you can be sure you're going to close the open file handle 
even if the function returns before. Memory management is just one obvious use 
case since we have this problem in Pascal often.

I don't think this even affects ref counting of existing types because it all 
it does it move the statement to the end of the block. Maybe I'm not 
understanding your point though.

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-06 Thread Marco van de Voort via fpc-devel


Op 2021-05-06 om 17:38 schreef Ryan Joseph via fpc-devel:

Something which annoys me about Pascal is cleanup in which a function exits in multiple 
places but there is no formal way to free memory which may be used in the current scope. 
I say ultimately Pascal needs some opt-in automatic reference counting for TObject but 
the "defer" keyword would be helpful alternative to what we have now, which is 
nothing.

The concept is very easy to understand and should be easy to implement by simply making a 
"defer" statement node which is added to a list and then called during function 
finalization like the other ref counted objects (dynamic array, interfaces etc).


But those types have refcounting built-in and always active. Things like 
defer don't, which makes that all objects gets refcounting overhead in 
case somebody needs it for "defer".


Contrary to Pascal both the language you reference have garbage 
collectors, so their objects are already managed anyway,




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


[fpc-devel] Defer keyword

2021-05-06 Thread Ryan Joseph via fpc-devel
Something which annoys me about Pascal is cleanup in which a function exits in 
multiple places but there is no formal way to free memory which may be used in 
the current scope. I say ultimately Pascal needs some opt-in automatic 
reference counting for TObject but the "defer" keyword would be helpful 
alternative to what we have now, which is nothing.

The concept is very easy to understand and should be easy to implement by 
simply making a "defer" statement node which is added to a list and then called 
during function finalization like the other ref counted objects (dynamic array, 
interfaces etc).

I've seen it appear in multiple languages already and it's a sound idea in my 
opinion. Is this something worth perusing for Pascal?

https://www.hackingwithswift.com/example-code/language/how-to-delay-execution-of-code-using-the-defer-keyword
https://www.geeksforgeeks.org/defer-keyword-in-golang/

procedure DoStuff;
begin
  obj := TObject.Create;
  defer objects.Free;

  while true do
begin
  // don't worry, obj will be freed safely
  if not obj.TrySomething then
exit;
end;
end;

Regards,
Ryan Joseph

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