jeremyletang / rgtk

GTK+ bindings and wrappers for Rust (DEPRECATED SEE https://github.com/rust-gnome )
GNU Lesser General Public License v3.0
121 stars 22 forks source link

Work out the thread safety/affinity story #243

Closed gkoz closed 9 years ago

gkoz commented 9 years ago

https://developer.gnome.org/gdk3/stable/gdk3-Threads.html#gdk3-Threads.description

GTK+ is not thread safe. You should only use GTK+ and GDK from the thread gtk_init() and gtk_main() were called on. This is usually referred to as the “main thread”. Signals on GTK+ and GDK types, as well as non-signal callbacks, are emitted in the main thread.

We need a way to enforce this invariant and it's not enough to make every widget !Send because a constructor could be called from any thread.

It can be done statically by having some !Send object that represents the GTK runtime (or the default MainContext) and making every constructor take a reference to this object:

let gtk = Gtk::new();
let button = Button::new(&gtk);

We're guaranteed that GTK callbacks (but not all callbacks possible under GLib) happen on the same thread so don't need extra checking there.

To avoid the usability hit of passing an extra argument to each constructor it might be possible to add methods on the Gtk struct to achieve something like

let button1 = gtk.button().new();
let button2 = gtk.button().with_label("Hello");

Here gtk.button() returns a ButtonBuilder or a ButtonFactory that supports all the constructors of a button.

It may actually be possible to make each widget have only one constructor (living under the Gtk struct) and refactor the others into setters (possibly allowing method chaining), so this example would look like

let button1 = gtk.button();
let button2 = gtk.button().set_label("Hello");

All of this can be sidestepped by doing runtime checks but it doesn't seem very Rust-y.

gkoz commented 9 years ago

The Gtk struct doesn't need to contain all those constructors as inherent methods (that would be pretty ugly). Each widget module can make a trait like ButtonFactory and implement it for the Gtk struct.