Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RAII - V2 #680

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open

RAII - V2 #680

wants to merge 9 commits into from

Conversation

renehiemstra
Copy link
Contributor

I've closed #659 [(https://github.com//pull/659)] and reopened it here to put forward the refactored design with a clean git commit history.

I'll summarize the pull request and the revised design:

Objective: The point of the contribution is to add methods to enable RAII in order to implement smart containers and smart pointers, like std::string, std::vector and std::unique_ptr, std::shared_ptr, boost:offset_ptr in C++.

The design does not introduce any breaking changes. No new keywords are introduced. Heap resources are acquired and released using the regular C stdlib functions such malloc and free, leaving memory allocation in the hands of the programmer. The idea here is that allocators are implemented in libraries.

New metamethods: The following metamethods are implemented:

  1. __init(self : &A)
  2. __dtor(self : &A)
  3. __copy(from : &A, to : &B)

If implemented, these methods are inserted judiciously during the type checking phase, implemented in terralib.lua. All these metamethods can be implemented as macro's or as terra functions.

Documenation about the design choices and the implementation can be found here

@renehiemstra renehiemstra mentioned this pull request Nov 27, 2024
@chriku
Copy link
Contributor

chriku commented Nov 29, 2024

As the previous attempt, I really love this. but I can still find remains of __move in some parts of the code, but not in the docs. On the same note, I would recommend to write a sentence about about why you decided not to do the __move-stuff (or if you do include it, how that works), to avoid questions by future people who come from the c++11 world

@renehiemstra
Copy link
Contributor Author

renehiemstra commented Nov 29, 2024

Thanks.

Indeed, there are two additional methods not explained in the documentation. These methods are auto-generated by terralibext.t:

  • __move
  • __forward

These methods are not used within the compiler. They are however useful in libraries when, for instance, you want to implement a custom __copy where you want to move resources over from struct members that are themselfs managed struct variables.

I'll add some documentation on these methods soon.

You can find non-trivial use cases in the following repo where we are developing a standard library and a linear algebra library. The following files are most interesting in this respect:

  • alloc.md, alloc.t
  • smartmem.t
  • dvector.t
  • dmatrix.t

We can't provide documentation right now and all functionality is undergoing heavy development. Nevertheless, it may be of interest.

@elliottslaughter
Copy link
Member

I'm trying to remember how we solved the issue of dangling references, e.g.:

terra f()
  var x : X
  return x
end

Would be compiled as:

terra f()
  var x : X
  x:__init()
  defer x:__dtor()
  return x
end

The defer must clearly run before the function returns, and therefore x is destroyed prior to being able to return the value. Unless the compiler is smart enough to not __dtor objects that are returned (is it?), then we'd need to copy x, as in:

terra f()
  var x : X
  x:__init()
  defer x:__dtor()
  var tmp : X
  tmp:__init()
  X.methods.__copy(tmp, x)
  return tmp
end

This would effectively force us to always copy, which is correct but perhaps inefficient.

I'm pretty sure we already had this discussion and you had a solution to that, so it would be good to document that solution, whatever it is.

@renehiemstra
Copy link
Contributor Author

renehiemstra commented Dec 3, 2024

The destructor is only called for objects that are not returned. Here is an example for a managed variable of type A

terra foo(x : &A)
    var y : A, z : A
    ...
    ...
    defer z:__dtor()    --generated by compiler
    return y
end

x is a reference so its destructor is not called in the function scope. y is a return argument so its destructor is also not called in this function scope. But z is constructed and destructed in the scope.

This example is also in the documentation.

@renehiemstra
Copy link
Contributor Author

The following case is not yet implemented:

When a managed variable is passed by value then a copy should be made using the copy constructor and a deferred destructor call should be scheduled:

terra foo(x : A)
    ...
    ...
    defer x__dtor()    --generated by compiler
end

I've added it as an issue on my fork and I will handle it soon. We can still discuss the default behavior of __copy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants