GLibSharp / GtkSharp

.Net bindings for gtk+3 and above
Other
27 stars 21 forks source link

Opaque: allow immediate run of finalize handler #50

Open xhaakon opened 4 years ago

xhaakon commented 4 years ago

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 commented 3 years ago

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 commented 3 years ago

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 commented 3 years ago

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:

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