Re: Updates on Eu 4.2.0
- Posted by ghaberek (admin) Jan 26, 2022
- 1915 views
I believe Euphoria needs to copy some C++ ideas
I've been doing some pretty deep digging on the Euphoria source code over the past year or so. I'm by no means an expert yet but I don't think much of that is necessary. Here are my thoughts.
like RAII
As I understand it, RAII is only concerned with stack-allocated objects that are holding heap-allocated resources, and ensuring those heap-allocated resources get released when the stack-allocated object goes out of scope. (Please correct me if I'm wrong.) However in Euphoria, everything (except the integer type) is already heap-allocated, and you can use delete_routine() as a "destructor" to release any associated resources. This is how things like map:new() and allocate_string() work.
One feature that could be beneficial here is a using syntax that guarantees the lifetime of an object. But, while this might be a nice feature to have, I think it would also have to come with some sort of tracing/profiling feature that could tell you where those references accumulated. I already ran into this trying to use maps with Euphoria MVC to the point where I made the mapdbg library to trace each allocation and then back-track where things didn't get cleaned up correctly.
Here's an example of what using might look like:
include std/machine.e sequence globalFoos = {} memstruct FooType -- some data types here end memstruct function newFoo() atom foo = allocate_data( sizeof(FooType) ) return delete_routine( foo, "free" ) -- free foo when it goes out of scope end function procedure saveFoo( atom foo ) globalFoos &= foo -- this will keep a reference to foo end procedure using atom myFoo = newFoo() do saveFoo( myFoo ) end using -- tries to delete myFoo but a reference is held in globalFoos, so -- it throws an error ("cannot delete myFoo: too many references")
and move-semantics
Like I said, everything in Euphoria is heap-allocated. Objects are syntactically passed by value but they're actually passed by reference. The backend just hides the pointers from you. Objects are reference counted so values are automatically "moved" simply by being assigned to one variable when another goes out of scope. Only when an object is modified does it get copied, and for sequences that's always "shallow" copy (elements are ref'd by 1) not a "deep" copy (elements are also copied).
and hide the structs inside an object system to keep the value semantics for the rest of the program
So skip implementing memstruct and move straight to classes? That's not a terrible idea but it would scrap a bunch of existing work. I'm not opposed to it though. It also would get 4.2 out the door sooner. Do you have more thoughts on what that might look like? I guess it'd probably be similar to Python's struct library?
-Greg