Managed record questions

classic Classic list List threaded Threaded
31 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Re: Managed record questions

Michael Van Canneyt


On Fri, 9 Mar 2018, Ryan Joseph wrote:

>
>
>> On Mar 9, 2018, at 3:55 AM, Graeme Geldenhuys <[hidden email]> wrote:
>>
>> My first question....
>>     What is a managed record?
>>
>> My second question....
>>     Why would I need it?
>>
>> My third question.....
>>     What is different compared to a "normal record"
>>     and compared to FPC's Object data type. eg:  TSomeObject = object;
>>
>
> I think the proper term is "management operators” for records which basically tell you when records are going in and out scope. The obvious use for them is ARC-like systems to manage reference counting. There’s probably other interesting things you could do with them we haven’t figured out yet.
>
> I’m still sticking with Apple’s Cocoa model of the auto-release pool that adds temporary data to a list and dumps it after every even cycle. Easy, doesn’t require new languages features. It’s a stupid waste of resources but that’s modern computing in a nutshell.
>
>>
>> Or is this all about trying to follow Delphi again because they broke the Object Pascal "Object" type and then reintroduced that same functionality (because EMBT developers are id**ts these days) using Records, and magically called it "advanced records". aka Objects - what Turbo Pascal 7 had.
>
> In almost every instance I can think of using so called "managed records" I could have achieved the same benefit by simply not allocating the class on the heap in the first place. Pascal has gone the way of Java or other high level languages that produce tons of garbage by allocating everything on the heap and then performing complicated tricks to dispose of all the waste they made.
>
> c++ solves this easily by having a unified class/record model but Pascal would need to basically overhaul the entire system to make this work. Until then we’re stuck in the middle, using records when we want stack allocation (with a broken OOP model) and using Classes when we need OOP features but forced into dynamic memory management scenarios.
Why don't you use objects ? No-one has obsoleted this, and you get what you
want: an object that can be allocated on the stack or on the heap.

I'm sure that we can add some extension to it to get rid of the somewhat awkward
new(someobject,init)
syntax to allocate one on the heap.


Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Managed record questions

Ryan Joseph


> On Mar 9, 2018, at 10:32 AM, Michael Van Canneyt <[hidden email]> wrote:
>
> Why don't you use objects ? No-one has obsoleted this, and you get what you
> want: an object that can be allocated on the stack or on the heap.

Object is just for backwards compatibility right? Does it support new features like generics, helpers, overloads  etc…? I have read over the years they’ve been broken also so I just assumed they were a dead part of the compiler kept around for old projects. If they still worked then why introduce “advanced records” which are merely “basic classes”. :) As pointed out it doesn’t make sense that classes and records diverged in the way they did.

>
> I'm sure that we can add some extension to it to get rid of the somewhat awkward
> new(someobject,init)
> syntax to allocate one on the heap.

If they’re not dead, then yes, making objects more flexible is possible but making classes behave like records on the stack is not. The best we can do now is use management operators on generic records to wrap classes so they get deallocated when out of scope. I can’t believe how complicated we’ve made things. :)

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Managed record questions

Free Pascal - General mailing list
Am 09.03.2018 05:14 schrieb "Ryan Joseph" <[hidden email]>:


> On Mar 9, 2018, at 10:32 AM, Michael Van Canneyt <[hidden email]> wrote:
>
> Why don't you use objects ? No-one has obsoleted this, and you get what you
> want: an object that can be allocated on the stack or on the heap.

Object is just for backwards compatibility right? Does it support new features like generics, helpers, overloads  etc…? I have read over the years they’ve been broken also so I just assumed they were a dead part of the compiler kept around for old projects. If they still worked then why introduce “advanced records” which are merely “basic classes”. :) As pointed out it doesn’t make sense that classes and records diverged in the way they did.

They are broken, deprecated and essentially dead in Delphi, but in FPC we've always cared for them as well.
Overloads and generics are already supported and support for helpers could be easily added. Only major feature missing compared to classes is the support for extensive RTTI. 

Regards, 
Sven 

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Managed record questions

Ryan Joseph


> On Mar 9, 2018, at 1:53 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> They are broken, deprecated and essentially dead in Delphi, but in FPC we've always cared for them as well.
> Overloads and generics are already supported and support for helpers could be easily added. Only major feature missing compared to classes is the support for extensive RTTI.

Out of curiosity I did some quick tests and learned a few things:

1) Interfaces don’t work as far as I can tell (too bad)
2) The constructor/destructor situation is pretty messy (deref using ^ could be omitted like classes probably) but that’s how they were in the past.
3) I suppose it never existed but “override” missing is pretty strange. Historical I guess.
4) Move() on an object copies memory like a record (as a record does, so this is good). Does that mean they laid out in memory just like records?

So why do we have advanced records then if objects do more than records? The overhead of a virtual method table? Records have a better/cleaner syntax for operator overloads than even classes but what else?

Unlike C++ the object’s destructor was not called when it went out of scope but if it did that they would be an interesting replacement for classes in some cases. The compiler knows how to cleanup stack variables but does it call any virtual method on objects in this situation?

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Managed record questions

Michael Van Canneyt


On Fri, 9 Mar 2018, Ryan Joseph wrote:

>
>
>> On Mar 9, 2018, at 1:53 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>>
>> They are broken, deprecated and essentially dead in Delphi, but in FPC we've always cared for them as well.
>> Overloads and generics are already supported and support for helpers could be easily added. Only major feature missing compared to classes is the support for extensive RTTI.
>
> Out of curiosity I did some quick tests and learned a few things:
>
> 1) Interfaces don’t work as far as I can tell (too bad)
> 2) The constructor/destructor situation is pretty messy (deref using ^ could be omitted like classes probably) but that’s how they were in the past.
Hence my proposal to 'clean this up'.

> 3) I suppose it never existed but “override” missing is pretty strange. Historical I guess.

You don't need "overrid"e for objects, it is automatical.

> 4) Move() on an object copies memory like a record (as a record does, so this is good). Does that mean they laid out in memory just like records?

Yes, although I believe there is a hidden VMT field.

>
> So why do we have advanced records then if objects do more than records?
> The overhead of a virtual method table? Records have a better/cleaner syntax for operator overloads than even classes but what else?

Simple: Delphi compatibility.

You can probably find some of my cries of despair on the mailing lists,
lamenting the fact that they decided to invent something new when they had
it all along since many decades :(

>
> Unlike C++ the object’s destructor was not called when it went out of scope but if it did that they would be an interesting replacement
> for classes in some cases. The compiler knows how to cleanup stack variables but does it call any virtual method on objects in this situation?

I do not think so.

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Managed record questions

Ryan Joseph


> On Mar 9, 2018, at 3:55 PM, Michael Van Canneyt <[hidden email]> wrote:
>
> Hence my proposal to 'clean this up’.

A good idea if they would be used. If objects had a couple minor things I personally could replace some records in certain parts of code and get real benefits. Someone on the compiler team would actually have to do this work though so it’s a cost/benefit analysis.

>
>> 3) I suppose it never existed but “override” missing is pretty strange. Historical I guess.
>
> You don't need "overrid"e for objects, it is automatical.

Another mystery of why classes added this then? I personally like it since it’s an indication of an overriding and gives some compiler warnings.

>
>> 4) Move() on an object copies memory like a record (as a record does, so this is good). Does that mean they laid out in memory just like records?
>
> Yes, although I believe there is a hidden VMT field.

Not sure how they look in memory but that code works so I guess they’re safe to use as records. I could be wrong though and cause nasty bugs using them as pure data structors (like passing to C functions!)

type
        TDataObject = object
                v: array[0..2] of integer;
        end;

procedure TestObjectCopy;
var
        obj: TDataObject;
        data: array[0..2] of integer;
        i: integer;
begin
        for i := 0 to 2 do
                obj.v[i] := 100 + (100 * i);
               
        Move(obj, data, sizeof(TDataObject));
        for i := 0 to 2 do
                writeln(data[i]);
end;

>
>>
>> So why do we have advanced records then if objects do more than records? The overhead of a virtual method table? Records have a better/cleaner syntax for operator overloads than even classes but what else?
>
> Simple: Delphi compatibility.
>
> You can probably find some of my cries of despair on the mailing lists,
> lamenting the fact that they decided to invent something new when they had
> it all along since many decades :(

I wonder how much code is shared between objects and records in the compiler. It’s really just a syntax difference if all they really wanted was Delphi compatibility. It’s a real shame to because the time could have been spent making objects more unified with classes.

>
>>
>> Unlike C++ the object’s destructor was not called when it went out of scope but if it did that they would be an interesting replacement for classes in some cases. The compiler knows how to cleanup stack variables but does it call any virtual method on objects in this situation?
>
> I do not think so.

Maciej, could you add your management operators to objects? Maybe the code for records/objects overlaps in places and it could be possible, although, the operator overload syntax for classes is not the same records (which is really a shame in itself) so perhaps not.

If you could add that then objects would have built-in ARC and since you can actually subclass them the implementation would be hidden away (instead of the messy generic wrapper we need to use with records).


Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Managed record questions

Ryan Joseph

> On Mar 9, 2018, at 4:13 PM, Ryan Joseph <[hidden email]> wrote:
>
> type
> TDataObject = object
> v: array[0..2] of integer;
> end;
>
> procedure TestObjectCopy;
> var
> obj: TDataObject;
> data: array[0..2] of integer;
> i: integer;
> begin
> for i := 0 to 2 do
> obj.v[i] := 100 + (100 * i);
>
> Move(obj, data, sizeof(TDataObject));
> for i := 0 to 2 do
> writeln(data[i]);
> end;

Actually this doesn’t work. VMT table breaks the data.

Program below returns:

10
20
30
32766
0
0
 
with the virtual method and:

10
20
30
100
200
300

without the virtual method.


type
        TSuperDataObject = object
                a: array[0..2] of integer;

                procedure Test; virtual; abstract;
        end;

type
        TDataObject = object (TSuperDataObject)
                b: array[0..2] of integer;

                procedure Test;
        end;

procedure TDataObject.Test;
begin
end;

procedure TestObjectCopy;
var
        obj: TDataObject;
        data: array[0..5] of integer;
        i: integer;
begin
        for i := 0 to 2 do
                begin
                        obj.a[i] := 10 + (10 * i);
                        obj.b[i] := 100 + (100 * i);
                end;

        Move(obj, data, sizeof(TDataObject));
        for i := 0 to 5 do
                writeln(data[i]);
end;

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Managed record questions

Free Pascal - General mailing list
In reply to this post by Ryan Joseph
Am 09.03.2018 10:14 schrieb "Ryan Joseph" <[hidden email]>:

>
>> 4) Move() on an object copies memory like a record (as a record does, so this is good). Does that mean they laid out in memory just like records?
>
> Yes, although I believe there is a hidden VMT field.

Not sure how they look in memory but that code works so I guess they’re safe to use as records. I could be wrong though and cause nasty bugs using them as pure data structors (like passing to C functions!)


The VMT field exists if there is at least one virtual method. 


>
>>
>> So why do we have advanced records then if objects do more than records? The overhead of a virtual method table? Records have a better/cleaner syntax for operator overloads than even classes but what else?
>
> Simple: Delphi compatibility.
>
> You can probably find some of my cries of despair on the mailing lists,
> lamenting the fact that they decided to invent something new when they had
> it all along since many decades :(

I wonder how much code is shared between objects and records in the compiler. It’s really just a syntax difference if all they really wanted was Delphi compatibility. It’s a real shame to because the time could have been spent making objects more unified with classes.

Objects share roughly as much code with records as classes do as internally classes and objects share most of their code. 

Regards, 
Sven 

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Managed record questions

Ryan Joseph


> On Mar 9, 2018, at 4:51 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> Objects share roughly as much code with records as classes do as internally classes and objects share most of their code.
>

I’ll be curious what Maciej says about management operators in objects then. Classes don’t have the same operator syntax as records unfortunately so that’s obviously a problem but come to think of it why are those even “operators” anyways? “Initialize” isn’t an operator in the same category as +, * etc… so I wonder why they can’t just be plain methods. Another question Maciej I guess.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Managed record questions

Free Pascal - General mailing list
Am 09.03.2018 16:41 schrieb "Ryan Joseph" <[hidden email]>:


> On Mar 9, 2018, at 4:51 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> Objects share roughly as much code with records as classes do as internally classes and objects share most of their code.
>

I’ll be curious what Maciej says about management operators in objects then. Classes don’t have the same operator syntax as records unfortunately so that’s obviously a problem but come to think of it why are those even “operators” anyways? “Initialize” isn’t an operator in the same category as +, * etc… so I wonder why they can’t just be plain methods. Another question Maciej I guess.

Because this way the user is aware that they are something special and are not supposed to be called manually. 

Regards, 
Sven 

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Managed record questions

Ryan Joseph


> On Mar 9, 2018, at 11:19 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> Because this way the user is aware that they are something special and are not supposed to be called manually.
>

That makes sense.

Why can’t the compiler use a similar method to call a function when a stack based construct like a record or object goes in/out of scope? We have the management operators now (which are more complicated) and reference counted interfaces (I never used those before they sound like the current standard for “ARC” in FPC but nothing which is a low-level compiler feature.

After doing some C++ work this week it appears they simply call the constructor/destructor for stack based structs/classes when they go in/out of scope and on class member variables when their parent class goes in/out of scope. It’s very simple but cleans up so many scenarios that exist in FPC so I’m curious why we never got this feature.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
12