Manual sink architecture #114
diamondburned
started this conversation in
Discussions
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Problem
Currently, gotk4 commonly suffers from the following problem which would cause
massive memory leaks due to limitations of the Go garbage collector:
This is because all closures must be stored in a global registry to be
referenced back later, which would cause
w
to also be globally referenced,meaning its finalizer is never called, causing a memory leak.
Current State
The current workaround involves creating a weak reference to
w
and using thatin the closure:
This works for at least GTK widgets, because signals should not own a strong
reference to the object unless it is being called. Signals are strictly only
relevant when the object itself is still alive.
However, this workaround has a limitation: it doesn't work if
w
is stored in astruct and that struct itself is referenced, as it commonly is. Consider the
following example:
This may work if
m
is also created as a weak reference in Go's allocatorsystem, possibly by using a third-party library that handles weak references
like xeus2001/go-weak:
Proposed Solution
The proposed solution is to do what GTK itself does: use a floating reference by
default when new objects are constructed. This means that, unless the object is
immediately referenced by something else, it will be destroyed in the next
iteration of the main loop.
What this means is that the following code will not cause a memory leak:
This is because, assuming
w
is not referenced by anything else, it will bedestroyed in the next iteration of the main loop, and the closure will be
destroyed with it.
This code will cause
w
to sink:This is because
w
is now referenced byparent
, and will not be destroyeduntil
parent
is destroyed.However, this also means that if
w
is stored for longer than the lifetime ofparent
, it will be destroyed in the next iteration of the main loop, causingthe program to crash:
In this case, the user must manually sink
w
to prevent it from beingdestroyed:
However, by manually sinking
w
, the user must also manually destroy it:This doesn't actually destroy
w
immediately, it simply removes the sunkenreference so that Go's garbage collector can destroy it when it is no longer
referenced.
When sunken, references to
w
within closures will cause the same memory leakas before:
However, note that the user should rarely need to sink objects. The only
time this should be necessary is when the user is storing an object for longer
than the lifetime of the object that references it. Doing so is already very
complicated, and the user should be aware of the consequences of doing so.
Implementation
TBD.
Beta Was this translation helpful? Give feedback.
All reactions