To handle certain kinds of operations better (and not leak memory), NativeCall needs to be able to control the lifecycle of objects. Specifically, we need to be able to relinquish control of memory allocated on the Perl side (so that it can be handed to C code), and the ability to take responsibility for a chunk of memory (so that it will be freed when the object is GCed.
To do this, I suggest adding two new functions, adopt()
and disown()
, and reworking the string marshalling rules.
These two functions do what you'd expect. adopt()
assumes control of the memory allocated by the object, indicating that it should be freed when the object is GCed. disown()
releases control, so that the memory is untouched on GC. Neither function should apply recursively to the members of structs or arrays.
NativeCall objects created in Perl 6 will be adopted by default, and those returned from C will be disowned by default.
Implementation-wise, I expect to add a flag for adoption state in the dyncall REPR types and NQP ops for setting it. Zavolaj will then only need to expose the ops through the functions.
explicitly-manage()
is terribly named, not very elegant, and I don't like it much. So we'll remove it and replace it with something else.
Under the new scheme, a normal Str object passed to a native function will be marshalled to a temporary string buffer which is sent to C and immediately freed after the function returns. No exceptions.
If you need more expressive handling than that, I propose adding a new standard class (a la OpaquePointer
): CStr
, which will be backed by a reworked CStr REPR (which we have from our current explicitly-manage()
scheme). Functionally, it will be similar to a CArray[int8]
, but with some additional functionality to work with string semantics. Objects of this class will be normal NativeCall objects that can be adopted and disowned.
Implementation-wise, this'll require reworking the CStr REPR and adding a class to Zavolaj doing the necessary NQP/6model plumbing.
+1
What I just want to mention: For the SDL Perl 5 module we wrapped the C-Objects, to attach information to it. This included an identifier of the thread which created the object. Only this thread was allowed to free an object when its refcount was zero. I have no clue if this applies to Perl 6's threading models, but I still wanted to tell.
Btw, in case I have a C-Object, that keeps pointers to other C-Objetcs, has Zavolay the capabilities to adopt/disown a tree of objects? Since I cant free child-objects that are referenced by parents I (Perl) dont own.