Skip to content

Opaque: allow immediate run of finalize handler#50

Open
xhaakon wants to merge 2 commits into
GLibSharp:masterfrom
xhaakon:opaque-custom-finalize
Open

Opaque: allow immediate run of finalize handler#50
xhaakon wants to merge 2 commits into
GLibSharp:masterfrom
xhaakon:opaque-custom-finalize

Conversation

@xhaakon

@xhaakon xhaakon commented Jul 8, 2020

Copy link
Copy Markdown
Contributor

Introduces global flag Opaque.ForceFinalizeInMainThread. When set to
false, objects inheriting Glib.Opaque will not schedule to conclude
their finalization from withing GLib main loop in the main thread, but
will do it immediately. This can be useful in programs that don't deal
with GTK widgets, which are expected to be freed from application's UI
thread.

For backward compatibility ForceFinalizeInMainThread defaults to true.

xhaakon added 2 commits July 8, 2020 15:49
Introduces global flag Opaque.ForceFinalizeInMainThread. When set to
false, objects inheriting Glib.Opaque will not schedule to conclude
their finalization from withing GLib main loop in the main thread, but
will do it immediately. This can be useful in programs that don't deal
with GTK widgets, which are expected to be freed from application's UI
thread.

For backward compatibility ForceFinalizeInMainThread defaults to true.
@ylatuya

ylatuya commented Jul 7, 2021

Copy link
Copy Markdown
Collaborator

I find this patch very useful too. For unit tests I end up starting a main loop in a separate thread:

  var mainContext = MainContext.Default;
            var thread = new System.Threading.Thread(() =>
            {
                mainContext.PushThreadDefault();
                mainLoop = new MainLoop(mainContext);
                mainLoop.Run();
            });
            thread.Start();

@thiblahute

Copy link
Copy Markdown
Contributor

I wonder if the right solution would be to have the Gtk wrapper to assert that nothing is happening in the wrong thread instead and make that be behavior the only acceptable behavior?

@ylatuya

ylatuya commented Jul 8, 2021

Copy link
Copy Markdown
Collaborator

Does any one knows the historical reason of why finalizers are scheduled to run in the main loop? Do the unref/free functions need to be run in the main thread too because they are not thread safe? I would assume that is the reason.

I would say that, because of its own multi-threaded nature, GStreamer's free/unref funcs are thread-safe, but GTK ones are for sure not thread-safe (here is an example https://gitlab.gnome.org/GNOME/gtk/blob/3.24.24/gtk/gtkwidgetpath.c#L203).

The bindings will be used in 2 different use cases:

  • From a GTK application running a main loop that require some free/unref funcs (the Gtk ones) to be run in the main thread
  • From applications not using GTK and running or not a main loop where free/unref funcs can be called from any thread

I don't think that having the Gtk wrapper to assert that nothing is happening in the wrong thread can be of any help here, unless it's for debugging purposes. If a user is incorrectly using the GTK API from secondary threads, finalizers will be the least of his/her problems :D. We also know that in both the mono and the .net runtimes, finalizers are run in a dedicated thread, the Finalizer thread. So unless users call Dispose() manually, it will run in that dedicated thread that is not the main thread.

To me, this patch makes sense because it allows to tune the behavior for 2 very different uses cases. The ideal solution would be to have it done automatically by detecting if a main loop is running. All this assuming that non-GTK free/free are thread-safe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants