roc-streaming / roc-go

Golang bindings for Roc Toolkit.
https://roc-streaming.org
MIT License
22 stars 10 forks source link

Implement finalizers for Context, Sender, Receiver #13

Open gavv opened 4 years ago

gavv commented 4 years ago

Context, Sender, and Receiver are long-living objects that own rather heavy native resources (C library handles). User is responsible to call Close() to free those resources.

If user forgets to call Close(), GC will collect go structs, but corresponding native resources will leak. It may be relatively easy to forget calling Close() because this objects typically are not used as local variables for which we can use defer, but instead are leaving in global variables or being part of other long-living objects.

We could reduce damage by forgetting calling Close() by setting finalizers for those objects. Finalizers have performance hit, but it's not critical here because the number of these kind of objects is not high.

Steps:

gavv commented 4 years ago

cc @Asalle

Asalle commented 4 years ago

nice idea, I think we should merge #20 and do this afterwards to avoid merge conflicts

Asalle commented 3 years ago

After giving it some thought, I have a question: wouldn't it be bad to automatically close the sender/receiver when context is garbage collected? What if the sender/receiver are still sending/receiving something? If we silently close them, when context is collected, wouldn't it create more confusion for the user? One possible solution to this is panic in the finalizer - so that the user clearly knows they are doing something wrong (closing context before closing sender/receiver).

gavv commented 3 years ago

That's why I've suggested to have a private (unexported) reference to context in sender and receiver. Currently sender is a pointer to c struct. We can make it a pointer to go struct instead, that have a pointer to c struct plus a pointer to go's context object. This will prevent gc from collecting context while there are senders and receivers referring it.