Recent

Author Topic: Automatic object deletion  (Read 15927 times)

pda

  • Newbie
  • Posts: 1
Automatic object deletion
« on: July 11, 2017, 10:19:31 pm »
Hello. I still do not understand if it is possible to "advertise" myself. I made a small library that implements something kinde a smart pointers. A simple record that provides automatic removal of temporary objects when the function ends.

Instead of writing something like:
Code: Pascal  [Select][+][-]
  1. SomeObject1 := nil;
  2. SomeObject2 := nil;
  3. SomeObject3 := nil;
  4. try
  5.   SomeObject1 := TSomeObject1.Create;
  6.   SomeObject2 := TSomeObject2.Create;
  7.   SomeObject3 := TSomeObject3.Create;
  8.   <...>
  9. finally
  10.   SomeObject3.Free;
  11.   SomeObject2.Free;
  12.   SomeObject1.Free;
  13. end;

you can write like:

Code: Pascal  [Select][+][-]
  1. uses
  2.   AutoScope,<...>;
  3. <...>
  4. procedure SomeProc;
  5. var
  6.   Scoped: TScoped;
  7.   <...>
  8. begin
  9.   SomeObject1 := Scoped[TSomeObject1.Create] as TSomeObject1;
  10.   SomeObject2 := Scoped[TSomeObject2.Create] as TSomeObject2;
  11.   SomeObject3 := Scoped[TSomeObject3.Create] as TSomeObject3;
  12.   <...>
  13. end;

Compatible with Delphi 2007+ (may be with 2006+) and Free Pascal 2.6.0+. I'm interested in your opinion on this matter. I've heard fears that the compiler can delete a variable before it runs out of scope, just when it's no longer used. Although I could not find such behavior for the records.

https://github.com/pda0/AutoScope

carl_caulkett

  • Sr. Member
  • ****
  • Posts: 306
Re: Automatic object deletion
« Reply #1 on: July 12, 2017, 12:10:36 am »
Back in my Delphi 7 days, I did something similar with some code which relied on interfaces.

Code: Pascal  [Select][+][-]
  1. interface
  2.  
  3. type
  4.  
  5.   IcaAutoFree = interface
  6.   ['{FEC11200-4C4E-49D7-9F9F-C7178A687DA4}']
  7.     // Property methods
  8.     function GetInstance: Pointer;
  9.     // Properties
  10.     property Instance: Pointer read GetInstance;
  11.   end;
  12.  
  13.   TcaAutoFree = class(TInterfacedObject, IcaAutoFree)
  14.   private
  15.     // Private fields
  16.     FInstance: TObject;
  17.     // Property methods
  18.     function GetInstance: Pointer;
  19.   public
  20.     constructor Create(AInstance: TObject);
  21.     destructor Destroy; override;
  22.   end;
  23.  
  24. function Auto(AInstance: TObject): IcaAutoFree;
  25.  
  26. implementation
  27.  
  28. constructor TcaAutoFree.Create(AInstance: TObject);
  29. begin
  30.   inherited Create;
  31.   FInstance := AInstance;
  32. end;
  33.  
  34. destructor TcaAutoFree.Destroy;
  35. begin
  36.   FInstance.Free;
  37.   inherited;
  38. end;
  39.  
  40.   // Property methods
  41.  
  42. function TcaAutoFree.GetInstance: Pointer;
  43. begin
  44.   Result := FInstance;
  45. end;
  46.  
  47. function Auto(AInstance: TObject): IcaAutoFree;
  48. begin
  49.   Result := TcaAutoFree.Create(AInstance);
  50. end;
  51.  

Usage would be something along the lines of:

Code: Pascal  [Select][+][-]
  1. var
  2.   List: TStringList;
  3. begin
  4.   List := Auto(TStringList.Create).Instance;
  5.   // Do stuff with List...
  6.   // No need to free anything.
  7.   // Will automatically free contained object when interface goes out of scope. ie. at end of procedure/method.
  8.   // Copes with exceptions - no need for try finally
  9. end;
  10.  

The code was adapted from someone's code, but it was in use for several years in production code and never gave me any hassle whatsoever.
« Last Edit: July 12, 2017, 12:23:56 am by carl_caulkett »
"It builds... ship it!"

Mac Mini M1
macOS 13.6 Ventura
Lazarus 2.2.6 (release version)
FPC 3.2.2 (release version)

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Automatic object deletion
« Reply #2 on: July 12, 2017, 02:27:56 am »
Hello. I still do not understand if it is possible to "advertise" myself.
there is the Announcement 3rd party group which is for this purpose.
I made a small library that implements something kinde a smart pointers. A simple record that provides automatic removal of temporary objects when the function ends.

Instead of writing something like:
Code: Pascal  [Select][+][-]
  1. SomeObject1 := nil;
  2. SomeObject2 := nil;
  3. SomeObject3 := nil;
  4. try
  5.   SomeObject1 := TSomeObject1.Create;
  6.   SomeObject2 := TSomeObject2.Create;
  7.   SomeObject3 := TSomeObject3.Create;
  8.   <...>
  9. finally
  10.   SomeObject3.Free;
  11.   SomeObject2.Free;
  12.   SomeObject1.Free;
  13. end;

you can write like:

Code: Pascal  [Select][+][-]
  1. uses
  2.   AutoScope,<...>;
  3. <...>
  4. procedure SomeProc;
  5. var
  6.   Scoped: TScoped;
  7.   <...>
  8. begin
  9.   SomeObject1 := Scoped[TSomeObject1.Create] as TSomeObject1;
  10.   SomeObject2 := Scoped[TSomeObject2.Create] as TSomeObject2;
  11.   SomeObject3 := Scoped[TSomeObject3.Create] as TSomeObject3;
  12.   <...>
  13. end;

I've heard fears that the compiler can delete a variable before it runs out of scope, just when it's no longer used. Although I could not find such behavior for the records.

https://github.com/pda0/AutoScope
Yes there is a difference between delphi and FPC on how it handles unassigned interface variables, while delphi waits until the exit of the current procedure to clean up the stack and decrease the reference counter, fpc will decrease it the moment its not used any more and release it immediately. I haven't seen your library yet but if its interface based then it will not work.
« Last Edit: July 12, 2017, 02:29:41 am by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

carl_caulkett

  • Sr. Member
  • ****
  • Posts: 306
Re: Automatic object deletion
« Reply #3 on: July 12, 2017, 06:46:12 am »
That's interesting. I was afraid that may be the case. Indeed, since switching from Delphi to Lazarus, I've abandoned use of my Auto based construct after experiencing some issues that suggested that memory management had indeed changed.
« Last Edit: July 12, 2017, 06:47:48 am by carl_caulkett »
"It builds... ship it!"

Mac Mini M1
macOS 13.6 Ventura
Lazarus 2.2.6 (release version)
FPC 3.2.2 (release version)

hnb

  • Sr. Member
  • ****
  • Posts: 270
Re: Automatic object deletion
« Reply #4 on: July 12, 2017, 08:47:44 am »
Code: Pascal  [Select][+][-]
  1. var
  2.   List: TStringList;
  3. begin
  4.   List := Auto(TStringList.Create).Instance;
  5.   // Do stuff with List...
  6.   // No need to free anything.
  7.   // Will automatically free contained object when interface goes out of scope. ie. at end of procedure/method.
  8.   // Copes with exceptions - no need for try finally
  9. end;
  10.  
this code will not work in current FPC:

https://bugs.freepascal.org/view.php?id=26602
https://bugs.freepascal.org/view.php?id=30409
Checkout NewPascal initiative and donate beer - ready to use tuned FPC compiler + Lazarus for mORMot project

best regards,
Maciej Izak

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Automatic object deletion
« Reply #5 on: July 12, 2017, 09:08:16 am »
I already showed it works some time ago, Maciej... Ok, adapted example...: 8-) O:-)
Code: Pascal  [Select][+][-]
  1. program smartpointers;
  2. {$ifdef fpc}{$mode delphi}{$endif}
  3. uses
  4.   classes,smartptrs;
  5. var
  6.   L:TStringlist;
  7.   PL:Auto<TStringList>;
  8. begin
  9.   // Auto create
  10.   L:= PL.Value;
  11.   L.Add('Testme');
  12.   writeln(L.Count);
  13.   // Nothing
  14.   L:=PL.Value;
  15.   L.Add('foo');
  16.   L.Add('foo2');
  17.   L.Add('Foobar');
  18.   Writeln(L.Count);  
  19.   writeln(L.Text);
  20.   // Auto cleanup
  21. end.
Code: Pascal  [Select][+][-]
  1. unit smartptrs;
  2. {$ifdef fpc}{$mode delphi}{$endif}
  3. interface
  4. type
  5.   Auto<T:class, constructor> = record
  6.   strict private
  7.     FValue:T;
  8.     FFreeTheValue:IInterface;
  9.     function GetValue:T;
  10.     type
  11.       TFreeTheValue = class(TInterfacedObject)
  12.       private
  13.         fObjectToFree:TObject;
  14.       public
  15.         constructor Create(anObjectToFree: TObject);
  16.         destructor Destroy;override;
  17.       end;
  18.    public
  19.      constructor Create(AValue: T);overload;
  20.      procedure Create;overload;
  21.      class operator Implicit(AValue: T):Auto<T>;
  22.      class operator Implicit(smart: Auto<T>):T;
  23.     property value: T read GetValue;
  24.    end;
  25.  
  26. implementation
  27.    
  28.    constructor Auto<T>.TFreeTheValue.Create(anObjectToFree:TObject);
  29.    begin
  30.      self.fObjectToFree := anObjectToFree;
  31.    end;
  32.    
  33.    destructor Auto<T>.TFreeTheValue.Destroy;
  34.    begin
  35.      fObjectToFree.Free;
  36.      inherited;
  37.    end;
  38.    
  39.    constructor Auto<T>.Create(AValue:T);
  40.    begin
  41.      FValue := AValue;
  42.      FFreeTheValue := TFreeTheValue.Create(FValue);
  43.    end;
  44.    
  45.    procedure Auto<T>.Create;
  46.    begin
  47.      Auto<T>.Create(T.Create);
  48.    end;
  49.    
  50.    class operator Auto<t>.Implicit(AValue:T):Auto<T>;
  51.    begin
  52.      Result := Auto<T>.Create(AValue);
  53.    end;
  54.    
  55.    class operator Auto<T>.Implicit(smart: Auto<T>):T;
  56.    begin
  57.      Result := Smart.Value;
  58.    end;
  59.  
  60.    function Auto<T>.GetValue:T;
  61.    begin
  62.      if not Assigned(FFreeTheValue) then
  63.        Self := Auto<T>.Create(T.Create);
  64.      Result := FValue;
  65.    end;
  66. end.

It just needs some refinements  :D :D :D :D Up to you!
For average readers: Maciej is busy getting rid of the double declarations as I do in my code: it can be done at once. He is doing a great job.

In the mean time, my example gives a solution for the original question: automatic object deletion. It is already possible.
And before anyone behaves being stupid again, no this code does not leak! (compile with -glh)

« Last Edit: July 12, 2017, 09:29:05 am by Thaddy »
Specialize a type, not a var.

hnb

  • Sr. Member
  • ****
  • Posts: 270
Re: Automatic object deletion
« Reply #6 on: July 12, 2017, 09:28:34 am »
I already showed it works some time ago, Maciej... Ok, adapted example...: 8-) O:-)

I mean the concrete example. When interface is returned as result of "Instance" function in Delphi is released at the end of function where "Instance" was called. In FPC the interface from "Instance" is released immediately. To fix differences between FPC and Delphi, the new switch SCOPED_INTERFACE_DESTROY would be not bad.
Checkout NewPascal initiative and donate beer - ready to use tuned FPC compiler + Lazarus for mORMot project

best regards,
Maciej Izak

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Automatic object deletion
« Reply #7 on: July 12, 2017, 09:30:19 am »
I already showed it works some time ago, Maciej... Ok, adapted example...: 8-) O:-)
the new switch SCOPED_INTERFACE_DESTROY would be not bad.
I agree. I am following your efforts as you now.
Specialize a type, not a var.

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Automatic object deletion
« Reply #8 on: July 12, 2017, 09:41:28 am »
For the average readers:
We hope that:
Code: Pascal  [Select][+][-]
  1. var
  2.   L:TStringlist;
  3.   PL:Auto<TStringList>;

can be changed to:
Code: Pascal  [Select][+][-]
  1. var
  2.   L:Auto<TStringList>;

Or similar. Maciej is actively pursuing such syntax in the compiler.
I understand what he is doing, but can not do it myself.
It may be even possible to get rid of Auto altogether, by using a {$modeswitch ARC} or something, which would mean automatic object destruction would be guaranteed.

« Last Edit: July 12, 2017, 09:51:55 am by Thaddy »
Specialize a type, not a var.

Blestan

  • Sr. Member
  • ****
  • Posts: 461
Re: Automatic object deletion
« Reply #9 on: July 12, 2017, 09:45:18 am »
and at least to be able to "mark" a type as for auto initialization / finalization when exiting a scoop


Speak postscript or die!
Translate to pdf and live!

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Automatic object deletion
« Reply #10 on: July 12, 2017, 09:49:01 am »
and at least to be able to "mark" a type as for auto initialization / finalization when exiting a scoop
Well, you can read my example code as doing just that: mark- by using the double declaration - .
As does Maciej's example with the use of auto.
But Maciej has a far more advanced concept in mind.
Note that your remark clutters the syntax. Memory management should be either/or all or nothing. IMHO.
« Last Edit: July 12, 2017, 09:58:26 am by Thaddy »
Specialize a type, not a var.

Blestan

  • Sr. Member
  • ****
  • Posts: 461
Re: Automatic object deletion
« Reply #11 on: July 12, 2017, 10:10:43 am »
yes i know ... ARC i good but the bookkeeping can be broken very easy...
few years ago i was thinking if it possible to create local/nested memory managers depending on the context ... and when exiting a given context to free all memory
(i cannot explain it very well in english) but mozzila has some simiral aproach in some products. another solution (maybe i borrowed the idea from some texts) is to have all pointers to object initialized to null and examine the return stack and finalize all not used in return objects
Speak postscript or die!
Translate to pdf and live!

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Automatic object deletion
« Reply #12 on: July 12, 2017, 10:19:37 am »
yes i know ... ARC i good but the bookkeeping can be broken very easy...
In the case of what Maciej is trying to achieve: no, it can't.
In the case of my already working example: yes, it can.
That's why I am teasing Maciej.. :-\ (and you!)
« Last Edit: July 12, 2017, 10:21:53 am by Thaddy »
Specialize a type, not a var.

Blestan

  • Sr. Member
  • ****
  • Posts: 461
Re: Automatic object deletion
« Reply #13 on: July 12, 2017, 10:24:14 am »
i read the whole communication of maciej with some of the core dev few months ago ... but i has left with the impression that there is some kind of resistentce ...

btw i have another question but will post a separate topic
Speak postscript or die!
Translate to pdf and live!

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Automatic object deletion
« Reply #14 on: July 12, 2017, 10:32:40 am »
i read the whole communication of maciej with some of the core dev few months ago ... but i has left with the impression that there is some kind of resistentce ...
Well, I read that too... Point is that devs are protectors of the language, almost all of them with a scientific qualification, and demand the highest standards (much higher than a commercial company demands).
Maciej is  aware of that, at some point wanted to give up, but now he is fully aware of the standards that are required. And he knows he is extremely respected by the core devs.

So maybe you interpreted the heavy discussions a bit wrong?

Simple Aristotle:
You only argue when you really care!
(I hope Maciej and devs agree that this is, just about, a proper summary)
« Last Edit: July 12, 2017, 10:44:27 am by Thaddy »
Specialize a type, not a var.

 

TinyPortal © 2005-2018