[foreign] Pulling the string on Scope
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Fri Dec 21 21:16:23 UTC 2018
Yep - it's the _safe_ thing to do, and, with the right API, clients can
correct that behavior if they really want to
Maurizio
On 21/12/2018 16:26, Jorn Vernee wrote:
> Nvm, I see what you mean now.
>
> i.e. tie the pointer to the scope of the struct any ways, and then
> someone has to manually correct this in the counter example case I gave.
>
> Jorn
>
> Jorn Vernee schreef op 2018-12-21 16:42:
>> Maurizio Cimadamore schreef op 2018-12-20 21:59:
>>> On 20/12/2018 13:54, Jorn Vernee wrote:
>>>> The above example does not actually throw an exception. There is a
>>>> solution for this problem for Callbacks; if you have a
>>>> Pointer<Callback<...>> then when the pointer is de-referenced the
>>>> callback is added to the Scope of the enclosing Pointer, and in the
>>>> case of struct fields this just happens to be the same scope that
>>>> the struct belongs to, but this seems like an unwanted side-effect.
>>>> If the Callback was not in the same scope as the Pointer we
>>>> inadvertently add it to the wrong scope. The right way to solve
>>>> this seems to be to track the Scope of a Struct's field when
>>>> setting it, and then setting it again when getting. But, we can't
>>>> ask native code to do that, so maybe the only solution is to say
>>>> that when you get a struct's field it does not belong to any scope,
>>>> and the missing exception in the above example is intended
>>>> behavior. Adding a resource field to the scope of the enclosing
>>>> struct when getting seems to make sense for nested structs and
>>>> fused arrays only, since you can say for sure that when the struct
>>>> is freed so are it's contents.
>>>
>>> I think a sensible behavior here is to tie the scope of whatever
>>> pointer we get back from a struct to the struct itself. We can't do
>>> much better than that, but I think it's a start, and, once we have a
>>> way to transfer pointer ownership, the user will be able to 'expand'
>>> the lifecycle of the pointer if he chooses to do so.
>>
>> So, this is only a good solution if the pointer we get back actually
>> points to the memory region of the struct.
>>
>> To give a counter example;
>>
>> @NativeStruct("[" +
>> " u64(get=getPtr)(set=setPtr):i32" +
>> "](MyStruct)")
>> interface MyStruct extends Struct<MyStruct> {
>> Pointer<Integer> getPtr();
>> void setPtr(Pointer<Integer> ptr);
>> }
>>
>> public static void main(String[] args) {
>> Scope scope1 = Scope.newNativeScope();
>> Pointer<Integer> myPointer =
>> scope1.allocated(NativeTypes.INT32);
>> Pointer<Integer> outside;
>> try(Scope scope2 = Scope.newNativeScope()) {
>> MyStruct struct = scope2.allocateStruct(MyStruct.class);
>> struct.setPtr(myPointer));
>> outside = struct.getPtr(); // returned pointer tied to
>> scope of struct
>> } // struct scope closed, and thus scope of 'outside'
>> int i = outside.get(); // should work, but will throw
>> }
>>
>> If a getter of a struct ties a returned pointer to the scope of the
>> struct, it will get closed too soon in this case, and the example
>> above will throw, even though it's safe.
>>
>> However, if we get back a pointer that points to the internals of a
>> struct I think we can safely tie it to the struct's scope.
>>
>> Jorn
>>
>>> In the past I've looked into other solutions so that the binder could
>>> somehow reify all the scopes of all the pointer fields, but it seemed
>>> overkill (think of cases where you have Pointer<Pointer<Pointer...>>>
>>> )
>>>
>>> Maurizio
More information about the panama-dev
mailing list