Recent

Author Topic: understanding management operators  (Read 2830 times)

soerensen3

  • Full Member
  • ***
  • Posts: 213
understanding management operators
« on: July 26, 2018, 10:45:09 pm »
I'm trying to understand management operators but there is something that makes me wonder. I just implemented a simple test record to implement all four management operators to understand when which operator gets called.

Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. {$MODE delphi}
  4. uses Classes;
  5.  
  6. type
  7.  
  8.   TTest = record
  9.     index: Integer;
  10.     class operator Initialize(var aRec:TTest);
  11.     class operator Finalize(var aRec:TTest);
  12.     class operator AddRef(var aRec:TTest);
  13.     class operator Copy(constref aSource:TTest; var aDest:TTest);
  14.   end;
  15.  
  16. class operator TTest.Initialize(var aRec: TTest);
  17. begin
  18.   WriteLn( 'Initialize' );
  19. end;
  20.  
  21. class operator TTest.Finalize(var aRec: TTest);
  22. begin
  23.   WriteLn( 'Finalize' );
  24. end;
  25.  
  26. class operator TTest.AddRef(var aRec: TTest);
  27. begin
  28.   WriteLn( 'AddRef' );
  29. end;
  30.  
  31. class operator TTest.Copy(constref aSource: TTest; var aDest: TTest);
  32. begin
  33.   WriteLn( 'Copy' );
  34. end;
  35.  
  36. type
  37.   PTest = ^TTest;
  38.  
  39. var
  40.   a: TTest;
  41.   b: PTest;
  42.  
  43. begin
  44.   WriteLn( '> a:= default( TTest );' );
  45.   a:= default( TTest );
  46.   WriteLn( '> New( b )' );
  47.   New( b );
  48.   WriteLn( '> b^:= a;' );
  49.   b^:= a;
  50.   WriteLn( '> end.' );
  51. end.
  52.  
The result is strange. I would assume that when the pointer to TTest is "freed" the finalize of the record is called.
But I have to Dispose( b );  to make it do that. I understand that if I assign memory it is not automatically freed but there is no way of telling when a pointer is used when it is freed. So it is not possible to efficiently use pointers of records for managed types? Is that correct?

Quote
Initialize
> a:= default( TTest );
Copy
> New( b )
Initialize
> b^:= a;
Copy
> end.
Finalize
Lazarus 1.9 with FPC 3.0.4
Target: Manjaro Linux 64 Bit (4.9.68-1-MANJARO)

PascalDragon

  • Hero Member
  • *****
  • Posts: 5486
  • Compiler Developer
Re: understanding management operators
« Reply #1 on: July 26, 2018, 11:40:12 pm »
From my understanding it shouldn't matter whether it's a pointer or not, Finalize() should be called nevertheless. Might be a bug...

hnb

  • Sr. Member
  • ****
  • Posts: 270
Re: understanding management operators
« Reply #2 on: July 27, 2018, 01:28:24 am »
This is not bug Sven. It works as expected/designed. ATM the only known bug related to management operators is : https://bugs.freepascal.org/view.php?id=33157

every call of "New" needs "Dispose", nothing new here (it behaves like any other managed record). The hardest part to understand is how AddRef and Copy operators works, maybe this may helps:

https://github.com/newpascal/freepascal/blob/master/tests/test/tmoperator8.pp
https://github.com/maciej-izak/PascalSmartPointers

The management operators functionality has not much sense without "default field" functionality and without my further work, which is discontinued in FPC and probably will be continued only with NewPascal (with eventually bug fixes for management operators including #33157).

"default field" functionality can be tested in NewPascal - PascalSmartPointers repository works with NewPascal only.

Management operators in this raw forms are not much end-user friendly (especially copy/addref operators). With management operators you can track how managed types works in FPC/NewPascal in details.
Checkout NewPascal initiative and donate beer - ready to use tuned FPC compiler + Lazarus for mORMot project

best regards,
Maciej Izak

PascalDragon

  • Hero Member
  • *****
  • Posts: 5486
  • Compiler Developer
Re: understanding management operators
« Reply #3 on: July 27, 2018, 09:09:51 am »
This is not bug Sven. It works as expected/designed. ATM the only known bug related to management operators is : https://bugs.freepascal.org/view.php?id=33157

every call of "New" needs "Dispose", nothing new here (it behaves like any other managed record). The hardest part to understand is how AddRef and Copy operators works, maybe this may helps:

https://github.com/newpascal/freepascal/blob/master/tests/test/tmoperator8.pp
https://github.com/maciej-izak/PascalSmartPointers

It's not about the missing Dispose(). The unclear part is what task the Copy-operator needs to fullfill. When record a is assigned to record b (no matter whether its a pointer to a record or a plain variable) does the operator need to finalize the destination record? Probably it simply needs to do what is necessary so that what the user wants to achieve with the managed record is indeed achieved... So it's indeed not a bug. *shrugs*

The management operators functionality has not much sense without "default field" functionality and without my further work, which is discontinued in FPC and probably will be continued only with NewPascal (with eventually bug fixes for management operators including #33157).

"default field" functionality can be tested in NewPascal - PascalSmartPointers repository works with NewPascal only.

Management operators in this raw forms are not much end-user friendly (especially copy/addref operators). With management operators you can track how managed types works in FPC/NewPascal in details.

Would you please stop saying that management operators only make sense with the default field? Because you being so focused on smart pointers blinds you for other purposes such managed records can be used for. After all C++'s copy- and default-constructors (which are the equivalent to the management operators) are useful without an overload of the dereferentiation-operator as well. In fact in our C++ code at work I only know of one instance where we overloaded that operator (namely for automatic reference counting, aka smart pointers), but many more instances where the copy- and default-constructors are overloaded.

soerensen3

  • Full Member
  • ***
  • Posts: 213
Re: understanding management operators
« Reply #4 on: July 27, 2018, 10:21:10 am »
Thanks for your responses. My point was not that it should call dispose automatically because than it would already be a smart pointer. If you think of the operators as events, than there is no event for a pointer to the rec going out of scope and (I don't have the time right now to test this) probably no event for only copying the pointer. So my conclusion was the record is only managed if you are not working with pointers (typed or not), where you have to call either New or GetMem and finally Dispose.
I'm asking because for a linked list I don't see any other way of using a pointer for a next field.
Lazarus 1.9 with FPC 3.0.4
Target: Manjaro Linux 64 Bit (4.9.68-1-MANJARO)

hnb

  • Sr. Member
  • ****
  • Posts: 270
Re: understanding management operators
« Reply #5 on: July 27, 2018, 11:09:38 am »
Would you please stop saying that management operators only make sense with the default field? Because you being so focused on smart pointers blinds you for other purposes such managed records can be used for.
No Sven, I will saying this all the time, because this is part of true. Smart pointers is just part of my work, stop saying nonsense about my "blindness" because you're far away from true. There is also part "and without my further work" which is related to other things (not only related to smart pointers), which was also mentioned in my other messages. Anyway default field is still important part. Management operators are just base for other language features and the current state of management operators is just first step, in general management operators are not much usable yet. The work is discontinued in FPC and will be expanded in NewPascal on other fields. I had no chance to discuss this with core but there will be no occasion for this. *shrugs*

You are too much focused on C++... I will say it again: management operators are not much usable without further extensions (I mean not only default field). Using it as-is is very frustrating and they were designed as part of other features not as main feature. So NewPascal is the last hope : ( .
« Last Edit: July 27, 2018, 11:43:42 am by hnb »
Checkout NewPascal initiative and donate beer - ready to use tuned FPC compiler + Lazarus for mORMot project

best regards,
Maciej Izak

hnb

  • Sr. Member
  • ****
  • Posts: 270
Re: understanding management operators
« Reply #6 on: July 27, 2018, 11:29:41 am »
Thanks for your responses. My point was not that it should call dispose automatically because than it would already be a smart pointer. If you think of the operators as events, than there is no event for a pointer to the rec going out of scope
Pointer is not managed as-is/disposed automatically. For this you need additional smart pointer:

Code: Pascal  [Select][+][-]
  1. var
  2.   a: TTest;
  3.   b: TDisposablePtr<PTest>;
  4. begin
  5. ...
  6.   b := New( PTest );
  7. ...
  8.  

Note1: TDisposablePtr is not yet available in my SmartPointers library.
Note2: class operator Implicit is very important to play with management operators.
Note3: this can be achieved only with NewPascal, because it has also few bug fixes for generics not provided with FPC.
Note4: here TDisposablePtr is the other managed record with management operators and with "default field"
Checkout NewPascal initiative and donate beer - ready to use tuned FPC compiler + Lazarus for mORMot project

best regards,
Maciej Izak

 

TinyPortal © 2005-2018