Recent

Author Topic: Smart pointers revisited. Let me know what you think.  (Read 13432 times)

Bogen85

  • Full Member
  • ***
  • Posts: 146
Re: Smart pointers revisited. Let me know what you think.
« Reply #60 on: September 25, 2022, 10:58:32 pm »
Well, I'll need to study your update (TAuto) more ASerge.

I like it how I can set the instance pointer directly with your example.

It works, but I have to do more checking to prevent Access violations compared to Thaddy's example (Auto)

Overall I like how Auto works, but I'd prefer to have a way to use procedure/property with it to set the instance pointer as well directly from a constructed object so that I don't need to have an additional pointer wrapper to allow for that.

I see that TAuto is using a record finalize member which I assume is a akin to a destructor, where as Auto is using a destructor in the nested TFreeTheValue to accomplish something similar.

I just need to learn advanced records and IInterface and TInterfacedObject ...
« Last Edit: September 26, 2022, 07:14:50 am by Bogen85 »

Bogen85

  • Full Member
  • ***
  • Posts: 146
Re: Smart pointers revisited. Let me know what you think.
« Reply #61 on: October 05, 2022, 07:21:02 pm »
Well, I'll need to study your update (TAuto) more ASerge.

I like it how I can set the instance pointer directly with your example.

It works, but I have to do more checking to prevent Access violations compared to Thaddy's example (Auto)

I was using Thaddy's Auto for a while but I had to wrap classes with parameterized creates in a separate pointer holder.
That was working but had added overhead was a bit awkward.

After getting use to doing it that way I revisited ASerge's and was able to resolve all my access/initialization problems.

I understand ASerge's TAuto unit a lot more than Thaddy's Auto unit.

Also, it is simpler for me to use. I just had learn a few things using Auto before I revisited TAuto.

Thanks ASerge!  ;D
« Last Edit: October 05, 2022, 07:25:14 pm by Bogen85 »

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1133
Re: Smart pointers revisited. Let me know what you think.
« Reply #62 on: October 10, 2022, 03:01:20 pm »
Ok, let's make an overview. Uses objpash.inc.

We have classes, that have a virtual method table (record TVmt), static methods and class methods, like:

Code: Pascal  [Select][+][-]
  1. class function NewInstance: TObject; virtual;

If you call the constructor, NewInstance is called in the background.

The difference between class methods and other methods is, that the latter get an invisible first parameter, Self, that points to the instance. While class methods are regular functions. NewInstance is just a function that returns a TObject.

After the TObject, we see the definition of IUnknown. This basically extends your classes with two new functions: _AddRef and _Release, which are used for reference counting.

The basic class that implements both, is TInterfacedObject. The main difference with a TObject is, that it adds a property RefCount and overrides NewInstance and Destroy, to add to or substract from that reference count.

Why does it do that and how does that help us with the memory management?

How it actually works isn't explained in this source file. To understand that, we have to read between the lines and fill in the blanks that are hidden inside the compiler. Like. how it calls NewInstance automatically. Every time you assign an instance to a variable, the compiler calls _AddRef (if available). And every time you assign something else to that variable, or it goes out of scope, it calls _Release. See:

Code: Pascal  [Select][+][-]
  1. function TObject.GetInterface(const iid : tguid; out obj) : boolean;

(For the implementations, see 'function fpc_intf*' in compproc.inc. It's hard to show the code where this is used, because the compiler uses offsets into the VMT instead of function names to call the _AddRef and _Release methods. To see it happen, use the debugger.)

The result of all that is, that if there are no variables anymore that reference an instance, it is deleted.

Or, in other words: instead of inheriting from class(TObject), use class(TInterfacedObject) to create your own ones and call the inherited destructor as usual. Like this:

Code: Pascal  [Select][+][-]
  1. type
  2.   TMyClass = class(TInterfacedObject)
  3.     MyVar: string;
  4.     constructor Create(ThisVar: string); virtual;
  5.     destructor Destroy; override;
  6.   end;
  7.  
  8. constructor TMyClass.Create(ThisVar: string);
  9. begin
  10.   inherited Create;
  11.   MyVar := ThisVar;
  12. end;
  13.  
  14. destructor TMyClass.Destroy;
  15. begin
  16.   inherited Destroy;
  17. end;
  18.  
  19. var
  20.   m, n: TMyClass;
  21. begin
  22.   m := TMyClass.Create('Bla');
  23.   n := m;
  24.   m := TMyClass.Create('Zomg!');
  25.   // Do stuff
  26.   // Don't Free them!
  27. end;

That should be enough.

But, there's a lot of existing classes you didn't write yourself, where that doesn't work. What do you do?

Well, the easiest way is probably to inherit a new class, that adds and implements an IUnknown interface, like TInterfacedObject does. Or use a smart pointer. The most interesting one is probably this one as posted earlier, which should now work on trunk.

Bogen85

  • Full Member
  • ***
  • Posts: 146
Re: Smart pointers revisited. Let me know what you think.
« Reply #63 on: October 10, 2022, 03:52:43 pm »
But, there's a lot of existing classes you didn't write yourself, where that doesn't work. What do you do?

Well, the easiest way is probably to inherit a new class, that adds and implements an IUnknown interface, like TInterfacedObject does. Or use a smart pointer. The most interesting one is probably this one as posted earlier, which should now work on trunk.

I'll need to look at that one. I'm using a very short class function (a constructor wrapper) I added to TAuto instantiate existing classes fairly seamlessly, and that has been working well.

I need to post my TAuto additions and slight modifications (does not change it's core functionality in any way, and TAuto only provided the core functionality anyways) but I'm not ready to do that quite yet.

PascalDragon

  • Hero Member
  • *****
  • Posts: 4756
  • Compiler Developer
Re: Smart pointers revisited. Let me know what you think.
« Reply #64 on: October 11, 2022, 07:32:01 am »
The difference between class methods and other methods is, that the latter get an invisible first parameter, Self, that points to the instance. While class methods are regular functions.

Wrong. There are normal class methods and there are static class methods. The later are always marked with  a static modifier at the end. Those (and only those) behave like regular functions or procedures that just happen to be inside a class scope and can be assigned to normal function pointers (at least in main, I think 3.2.x didn't allow that yet).
Regular class methods however do also have that hidden Self parameter, but it won't contain the class instance, but the class type. Regular class methods can also be virtual which means that a sub class can override them. This makes them a very powerful feature (something I deeply miss here and then in C++) and is the reason why NewInstance can be reimplemented by sub classes to use some different allocation mechanism.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1133
Re: Smart pointers revisited. Let me know what you think.
« Reply #65 on: October 11, 2022, 10:00:14 am »
Thanks for making that clear  :)

I don't really use that very much.

Ryan J

  • New member
  • *
  • Posts: 9
Re: Smart pointers revisited. Let me know what you think.
« Reply #66 on: October 16, 2022, 04:49:31 am »
The [box] syntax originated from the current lack of default properties other that array properties.

I just stumbled across this post and thought I'd share my feature branch at https://gitlab.com/genericptr/free-pascal/-/tree/default_record_property so maybe one day some progress can be made on this and we don't forget about it. Sven (@PascalDragon I think?) agreed that smart pointers are the best option for ARC in FPC and I think approved of a default property If I recall correctly so I made this branch which implements a default property for records with a class field.

If the compiler devs ever want to try to implement I'll come back to it but it's just parked here for now.

Thaddy

  • Hero Member
  • *****
  • Posts: 12200
Re: Smart pointers revisited. Let me know what you think.
« Reply #67 on: October 16, 2022, 10:26:13 am »
That is already recorded.
Both AVK and me wrote a proper implementation. Just waiting for a water tight implementation for the default property, which was more or less also implemented in a fork by Maciej. (and as far as I know almost correct, but abandoned?)

Both mentioned implementations work from 3.2 onwards. It is just the sugar candy that does not work yet.

Look up the discussion on this forum.
« Last Edit: October 16, 2022, 10:30:10 am by Thaddy »
Manuals, manuals, manuals first.
You have incompetence and sheer incompetence.

Ryan J

  • New member
  • *
  • Posts: 9
Re: Smart pointers revisited. Let me know what you think.
« Reply #68 on: October 17, 2022, 03:58:47 am »
That is already recorded.
Both AVK and me wrote a proper implementation. Just waiting for a water tight implementation for the default property, which was more or less also implemented in a fork by Maciej. (and as far as I know almost correct, but abandoned?)

Both mentioned implementations work from 3.2 onwards. It is just the sugar candy that does not work yet.

Look up the discussion on this forum.

I'm sorry, there is already a default property developed? Can you show me where it is so I can study it? I didn't get any guidance from Sven on this so I have no idea what would be allowed or not or if I implemented it correctly.

The one I did was pretty complete I think (including for..in loops) but it's scoped was constrained to just class fields since using other types affect far too much of the compiler and was likely to get rejected anyways.

Thaddy

  • Hero Member
  • *****
  • Posts: 12200
Re: Smart pointers revisited. Let me know what you think.
« Reply #69 on: October 17, 2022, 11:14:52 am »
Maciej, a.k.a HNB on this forum did it. He is not good with the compiler people anymore.
(But he contributed many things to Lazarus and FPC: anchor docking resp rtl-generics and many fixes)
« Last Edit: October 17, 2022, 11:18:00 am by Thaddy »
Manuals, manuals, manuals first.
You have incompetence and sheer incompetence.

Ryan J

  • New member
  • *
  • Posts: 9
Re: Smart pointers revisited. Let me know what you think.
« Reply #70 on: October 18, 2022, 08:38:52 am »
Maciej, a.k.a HNB on this forum did it. He is not good with the compiler people anymore.
(But he contributed many things to Lazarus and FPC: anchor docking resp rtl-generics and many fixes)

yes I spoke with him around the time he did the excellent record management operators and we discussed the default property then. At that time he hadn't implement it so I assumed it was left undone. Not sure where I can find his implementation anyways and since he's not going to contribute to FPC anymore it may be hard to get what he has working or finished.

Honestly even if the compiler devs accept this it will be years before it's reviewed and merged in. Personally I have an extended RTTI patch which is in the pipeline for review but it's been well over a year since I hard back from them on that so I expect many years for the default property unfortunately.

 

TinyPortal © 2005-2018