I am writing an app using gtk-rs and I have encountered a problem when trying to call glib::idle_add from another thread.
When the callback passed to glib::idle_add contains a GObject, the compilation fails.
This is a simplified example:
extern crate glib;
extern crate gtk;
use std::thread;
use glib::prelude::*;
use gtk::prelude::*;
fn perform_some_long_computation() {}
fn main() {
if gtk::init().is_err() {
println!("Failed to initialize GTK.");
return;
}
let window = gtk::Window::new(gtk::WindowType::Toplevel);
let button = gtk::Button::new_with_label("Click me!");
let window_clone = window.clone();
button.connect_clicked(move |_| {
thread::spawn(move || {
perform_some_long_computation();
glib::idle_add(move || {
window_clone.set_title("Finished"); // cannot use any GObject inside this callback
glib::Continue(false)
});
});
});
window.add(&button);
window.show_all();
gtk::main();
}
These are the compilation errors:
error[E0277]: the trait bound `*mut glib::object::GObject: std::marker::Send` is not satisfied in `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
--> src/main.rs:24:13
|
24 | glib::idle_add(move || {
| ^^^^^^^^^^^^^^ within `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`, the trait `std::marker::Send` is not implemented for `*mut glib::object::GObject`
|
= note: `*mut glib::object::GObject` cannot be sent between threads safely
= note: required because it appears within the type `glib::shared::Shared<glib::object::GObject, glib::object::MemoryManager>`
= note: required because it appears within the type `glib::object::ObjectRef`
= note: required because it appears within the type `gtk::Window`
= note: required because it appears within the type `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
= note: required by `glib::idle_add`
error[E0277]: the trait bound `*mut gtk_sys::GtkWindowPrivate: std::marker::Send` is not satisfied in `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
--> src/main.rs:24:13
|
24 | glib::idle_add(move || {
| ^^^^^^^^^^^^^^ within `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`, the trait `std::marker::Send` is not implemented for `*mut gtk_sys::GtkWindowPrivate`
|
= note: `*mut gtk_sys::GtkWindowPrivate` cannot be sent between threads safely
= note: required because it appears within the type `gtk_sys::GtkWindow`
= note: required because it appears within the type `std::marker::PhantomData<gtk_sys::GtkWindow>`
= note: required because it appears within the type `gtk::Window`
= note: required because it appears within the type `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
= note: required by `glib::idle_add`
error[E0277]: the trait bound `*const glib::object::MemoryManager: std::marker::Send` is not satisfied in `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
--> src/main.rs:24:13
|
24 | glib::idle_add(move || {
| ^^^^^^^^^^^^^^ within `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`, the trait `std::marker::Send` is not implemented for `*const glib::object::MemoryManager`
|
= note: `*const glib::object::MemoryManager` cannot be sent between threads safely
= note: required because it appears within the type `std::marker::PhantomData<*const glib::object::MemoryManager>`
= note: required because it appears within the type `glib::shared::Shared<glib::object::GObject, glib::object::MemoryManager>`
= note: required because it appears within the type `glib::object::ObjectRef`
= note: required because it appears within the type `gtk::Window`
= note: required because it appears within the type `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
= note: required by `glib::idle_add`
error[E0277]: the trait bound `*mut gtk_sys::GtkBinPrivate: std::marker::Send` is not satisfied in `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
--> src/main.rs:24:13
|
24 | glib::idle_add(move || {
| ^^^^^^^^^^^^^^ within `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`, the trait `std::marker::Send` is not implemented for `*mut gtk_sys::GtkBinPrivate`
|
= note: `*mut gtk_sys::GtkBinPrivate` cannot be sent between threads safely
= note: required because it appears within the type `gtk_sys::GtkBin`
= note: required because it appears within the type `gtk_sys::GtkWindow`
= note: required because it appears within the type `std::marker::PhantomData<gtk_sys::GtkWindow>`
= note: required because it appears within the type `gtk::Window`
= note: required because it appears within the type `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
= note: required by `glib::idle_add`
error[E0277]: the trait bound `*mut gtk_sys::GtkContainerPrivate: std::marker::Send` is not satisfied in `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
--> src/main.rs:24:13
|
24 | glib::idle_add(move || {
| ^^^^^^^^^^^^^^ within `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`, the trait `std::marker::Send` is not implemented for `*mut gtk_sys::GtkContainerPrivate`
|
= note: `*mut gtk_sys::GtkContainerPrivate` cannot be sent between threads safely
= note: required because it appears within the type `gtk_sys::GtkContainer`
= note: required because it appears within the type `gtk_sys::GtkBin`
= note: required because it appears within the type `gtk_sys::GtkWindow`
= note: required because it appears within the type `std::marker::PhantomData<gtk_sys::GtkWindow>`
= note: required because it appears within the type `gtk::Window`
= note: required because it appears within the type `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
= note: required by `glib::idle_add`
error[E0277]: the trait bound `*mut gtk_sys::GtkWidgetPrivate: std::marker::Send` is not satisfied in `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
--> src/main.rs:24:13
|
24 | glib::idle_add(move || {
| ^^^^^^^^^^^^^^ within `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`, the trait `std::marker::Send` is not implemented for `*mut gtk_sys::GtkWidgetPrivate`
|
= note: `*mut gtk_sys::GtkWidgetPrivate` cannot be sent between threads safely
= note: required because it appears within the type `gtk_sys::GtkWidget`
= note: required because it appears within the type `gtk_sys::GtkContainer`
= note: required because it appears within the type `gtk_sys::GtkBin`
= note: required because it appears within the type `gtk_sys::GtkWindow`
= note: required because it appears within the type `std::marker::PhantomData<gtk_sys::GtkWindow>`
= note: required because it appears within the type `gtk::Window`
= note: required because it appears within the type `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
= note: required by `glib::idle_add`
error[E0277]: the trait bound `*mut glib_sys::GData: std::marker::Send` is not satisfied in `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
--> src/main.rs:24:13
|
24 | glib::idle_add(move || {
| ^^^^^^^^^^^^^^ within `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`, the trait `std::marker::Send` is not implemented for `*mut glib_sys::GData`
|
= note: `*mut glib_sys::GData` cannot be sent between threads safely
= note: required because it appears within the type `gobject_sys::GInitiallyUnowned`
= note: required because it appears within the type `gtk_sys::GtkWidget`
= note: required because it appears within the type `gtk_sys::GtkContainer`
= note: required because it appears within the type `gtk_sys::GtkBin`
= note: required because it appears within the type `gtk_sys::GtkWindow`
= note: required because it appears within the type `std::marker::PhantomData<gtk_sys::GtkWindow>`
= note: required because it appears within the type `gtk::Window`
= note: required because it appears within the type `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
= note: required by `glib::idle_add`
error[E0277]: the trait bound `*mut gobject_sys::GTypeClass: std::marker::Send` is not satisfied in `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
--> src/main.rs:24:13
|
24 | glib::idle_add(move || {
| ^^^^^^^^^^^^^^ within `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`, the trait `std::marker::Send` is not implemented for `*mut gobject_sys::GTypeClass`
|
= note: `*mut gobject_sys::GTypeClass` cannot be sent between threads safely
= note: required because it appears within the type `gobject_sys::GTypeInstance`
= note: required because it appears within the type `gobject_sys::GInitiallyUnowned`
= note: required because it appears within the type `gtk_sys::GtkWidget`
= note: required because it appears within the type `gtk_sys::GtkContainer`
= note: required because it appears within the type `gtk_sys::GtkBin`
= note: required because it appears within the type `gtk_sys::GtkWindow`
= note: required because it appears within the type `std::marker::PhantomData<gtk_sys::GtkWindow>`
= note: required because it appears within the type `gtk::Window`
= note: required because it appears within the type `[closure@src/main.rs:24:28: 27:14 window_clone:gtk::Window]`
= note: required by `glib::idle_add`
error: aborting due to 8 previous errors
Thank you for any advice!