NIF resources, environments and GC

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

NIF resources, environments and GC

Loïc Hoguin-3
Hello,

I've got the following situation.

I have a function SDL_CreateWindow that returns an SDL_Window* from
which I create a resource with a destructor which is called when the
resource variable gets GC'd. So far so good.

I also have various other functions which may return the same
SDL_Window* as the one that was created earlier. In this case I want to
return the same resource so that it is possible to match or compare the
resources on the latest Erlang versions so that users can confirm that
yes, it's the same window. This is useful to know for example to know
which window currently has focus.

I therefore need to keep the ERL_NIF_TERM around along with SDL_Window*
since recreating the term would lead to different references and
comparisons failing. I've therefore proceded to use enif_make_copy to
copy it to a static variable and I do enif_make_copy again when I need
to return it.

It works.

Almost.

The only issue with my approach is that the destructor for the
SDL_Window* resource no longer gets called. Apparently enif_make_copy is
the culprit. As soon as I copy the resource term to my private env, the
destructor stops being called.

Is there any way I can keep this resource term while still benefitting
from the destructor being called when the variable is discarded?
Basically I would like the private copy to not be reference counted. Any
way to do this?

Thanks,

--
Loïc Hoguin
https://ninenines.eu
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: NIF resources, environments and GC

Daniel Goertzen-3
This is exactly the weak reference/weak pointer pattern.  I don't see any quick shortcuts for you here.

If you are using c++, your resources can represent shared_ptr and your stored static variable can be a weak_ptr.  Rust has similar types.  Unfortunately you would also need to write a NIF for comparing the underlying referred object.




On Tue, Dec 19, 2017 at 9:03 AM Loïc Hoguin <[hidden email]> wrote:
Hello,

I've got the following situation.

I have a function SDL_CreateWindow that returns an SDL_Window* from
which I create a resource with a destructor which is called when the
resource variable gets GC'd. So far so good.

I also have various other functions which may return the same
SDL_Window* as the one that was created earlier. In this case I want to
return the same resource so that it is possible to match or compare the
resources on the latest Erlang versions so that users can confirm that
yes, it's the same window. This is useful to know for example to know
which window currently has focus.

I therefore need to keep the ERL_NIF_TERM around along with SDL_Window*
since recreating the term would lead to different references and
comparisons failing. I've therefore proceded to use enif_make_copy to
copy it to a static variable and I do enif_make_copy again when I need
to return it.

It works.

Almost.

The only issue with my approach is that the destructor for the
SDL_Window* resource no longer gets called. Apparently enif_make_copy is
the culprit. As soon as I copy the resource term to my private env, the
destructor stops being called.

Is there any way I can keep this resource term while still benefitting
from the destructor being called when the variable is discarded?
Basically I would like the private copy to not be reference counted. Any
way to do this?

Thanks,

--
Loïc Hoguin
https://ninenines.eu
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: NIF resources, environments and GC

Sverker Eriksson-4
In reply to this post by Loïc Hoguin-3
Two resource terms will compare equal (in OTP-20) iff they yield
the same pointer from enif_get_resource().

So, isn't the solution to instead maintain a pointer to your resource
in the static variable. Call enif_make_resource(static_ptr) when you
need to return a resource term.

And then clear that static pointer in the destructor.

/Sverker


On tis, 2017-12-19 at 16:03 +0100, Loïc Hoguin wrote:

> Hello,
>
> I've got the following situation.
>
> I have a function SDL_CreateWindow that returns an SDL_Window* from 
> which I create a resource with a destructor which is called when the 
> resource variable gets GC'd. So far so good.
>
> I also have various other functions which may return the same 
> SDL_Window* as the one that was created earlier. In this case I want
> to 
> return the same resource so that it is possible to match or compare
> the 
> resources on the latest Erlang versions so that users can confirm
> that 
> yes, it's the same window. This is useful to know for example to
> know 
> which window currently has focus.
>
> I therefore need to keep the ERL_NIF_TERM around along with
> SDL_Window* 
> since recreating the term would lead to different references and 
> comparisons failing. I've therefore proceded to use enif_make_copy
> to 
> copy it to a static variable and I do enif_make_copy again when I
> need 
> to return it.
>
> It works.
>
> Almost.
>
> The only issue with my approach is that the destructor for the 
> SDL_Window* resource no longer gets called. Apparently enif_make_copy
> is 
> the culprit. As soon as I copy the resource term to my private env,
> the 
> destructor stops being called.
>
> Is there any way I can keep this resource term while still
> benefitting 
> from the destructor being called when the variable is discarded? 
> Basically I would like the private copy to not be reference counted.
> Any 
> way to do this?
>
> Thanks,
>
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: NIF resources, environments and GC

Loïc Hoguin-3
Thanks for the tip, I haven't tried that. I'll report back with the results.

On 12/19/2017 04:33 PM, Sverker Eriksson wrote:

> Two resource terms will compare equal (in OTP-20) iff they yield
> the same pointer from enif_get_resource().
>
> So, isn't the solution to instead maintain a pointer to your resource
> in the static variable. Call enif_make_resource(static_ptr) when you
> need to return a resource term.
>
> And then clear that static pointer in the destructor.
>
> /Sverker
>
>
> On tis, 2017-12-19 at 16:03 +0100, Loïc Hoguin wrote:
>> Hello,
>>
>> I've got the following situation.
>>
>> I have a function SDL_CreateWindow that returns an SDL_Window* from
>> which I create a resource with a destructor which is called when the
>> resource variable gets GC'd. So far so good.
>>
>> I also have various other functions which may return the same
>> SDL_Window* as the one that was created earlier. In this case I want
>> to
>> return the same resource so that it is possible to match or compare
>> the
>> resources on the latest Erlang versions so that users can confirm
>> that
>> yes, it's the same window. This is useful to know for example to
>> know
>> which window currently has focus.
>>
>> I therefore need to keep the ERL_NIF_TERM around along with
>> SDL_Window*
>> since recreating the term would lead to different references and
>> comparisons failing. I've therefore proceded to use enif_make_copy
>> to
>> copy it to a static variable and I do enif_make_copy again when I
>> need
>> to return it.
>>
>> It works.
>>
>> Almost.
>>
>> The only issue with my approach is that the destructor for the
>> SDL_Window* resource no longer gets called. Apparently enif_make_copy
>> is
>> the culprit. As soon as I copy the resource term to my private env,
>> the
>> destructor stops being called.
>>
>> Is there any way I can keep this resource term while still
>> benefitting
>> from the destructor being called when the variable is discarded?
>> Basically I would like the private copy to not be reference counted.
>> Any
>> way to do this?
>>
>> Thanks,
>>
> _______________________________________________
> erlang-questions mailing list
> [hidden email]
> http://erlang.org/mailman/listinfo/erlang-questions
>

--
Loïc Hoguin
https://ninenines.eu
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: NIF resources, environments and GC

Loïc Hoguin-3
It works! And it ended up much simpler than I initially went for.

Worth noting that the destructor takes a while to be called if you are
debugging using io:format.

Thanks a bunch!

On 12/19/2017 04:41 PM, Loïc Hoguin wrote:

> Thanks for the tip, I haven't tried that. I'll report back with the
> results.
>
> On 12/19/2017 04:33 PM, Sverker Eriksson wrote:
>> Two resource terms will compare equal (in OTP-20) iff they yield
>> the same pointer from enif_get_resource().
>>
>> So, isn't the solution to instead maintain a pointer to your resource
>> in the static variable. Call enif_make_resource(static_ptr) when you
>> need to return a resource term.
>>
>> And then clear that static pointer in the destructor.
>>
>> /Sverker
>>
>>
>> On tis, 2017-12-19 at 16:03 +0100, Loïc Hoguin wrote:
>>> Hello,
>>>
>>> I've got the following situation.
>>>
>>> I have a function SDL_CreateWindow that returns an SDL_Window* from
>>> which I create a resource with a destructor which is called when the
>>> resource variable gets GC'd. So far so good.
>>>
>>> I also have various other functions which may return the same
>>> SDL_Window* as the one that was created earlier. In this case I want
>>> to
>>> return the same resource so that it is possible to match or compare
>>> the
>>> resources on the latest Erlang versions so that users can confirm
>>> that
>>> yes, it's the same window. This is useful to know for example to
>>> know
>>> which window currently has focus.
>>>
>>> I therefore need to keep the ERL_NIF_TERM around along with
>>> SDL_Window*
>>> since recreating the term would lead to different references and
>>> comparisons failing. I've therefore proceded to use enif_make_copy
>>> to
>>> copy it to a static variable and I do enif_make_copy again when I
>>> need
>>> to return it.
>>>
>>> It works.
>>>
>>> Almost.
>>>
>>> The only issue with my approach is that the destructor for the
>>> SDL_Window* resource no longer gets called. Apparently enif_make_copy
>>> is
>>> the culprit. As soon as I copy the resource term to my private env,
>>> the
>>> destructor stops being called.
>>>
>>> Is there any way I can keep this resource term while still
>>> benefitting
>>> from the destructor being called when the variable is discarded?
>>> Basically I would like the private copy to not be reference counted.
>>> Any
>>> way to do this?
>>>
>>> Thanks,
>>>
>> _______________________________________________
>> erlang-questions mailing list
>> [hidden email]
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>

--
Loïc Hoguin
https://ninenines.eu
_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions