diff --git a/book/src/g_object_memory_management.md b/book/src/g_object_memory_management.md
index 972626b09252..d4941313868a 100644
--- a/book/src/g_object_memory_management.md
+++ b/book/src/g_object_memory_management.md
@@ -7,10 +7,10 @@ With our first example, we have window with a single button.
Every button click should increment an integer `number` by one.
```rust ,no_run,compile_fail
-#use gtk::prelude::*;
-#use gtk::{self, glib, Application, ApplicationWindow, Button};
+# use gtk::prelude::*;
+# use gtk::{self, glib, Application, ApplicationWindow, Button};
#
-#const APP_ID: &str = "org.gtk_rs.GObjectMemoryManagement0";
+# const APP_ID: &str = "org.gtk_rs.GObjectMemoryManagement0";
#
// DOES NOT COMPILE!
fn main() -> glib::ExitCode {
@@ -72,7 +72,7 @@ note: function requires argument type to outlive `'static`
help: to force the closure to take ownership of `number` (and any other referenced variables), use the `move` keyword
|
32 | button_increase.connect_clicked(move |_| number += 1);
- |
+ |
```
Our closure only borrows `number`.
@@ -81,31 +81,31 @@ The compiler also suggests how to fix this.
By adding the `move` keyword in front of the closure, `number` will be moved into the closure.
```rust ,no_run,compile_fail
-#use gtk::prelude::*;
-#use gtk::{self, glib, Application, ApplicationWindow, Button};
+# use gtk::prelude::*;
+# use gtk::{self, glib, Application, ApplicationWindow, Button};
#
-#const APP_ID: &str = "org.gtk_rs.GObjectMemoryManagement0";
+# const APP_ID: &str = "org.gtk_rs.GObjectMemoryManagement0";
#
-#fn main() -> glib::ExitCode {
-# // Create a new application
-# let app = Application::builder().application_id(APP_ID).build();
+# fn main() -> glib::ExitCode {
+# // Create a new application
+# let app = Application::builder().application_id(APP_ID).build();
#
-# // Connect to "activate" signal of `app`
-# app.connect_activate(build_ui);
+# // Connect to "activate" signal of `app`
+# app.connect_activate(build_ui);
#
-# // Run the application
-# app.run()
-#}
+# // Run the application
+# app.run()
+# }
#
-#fn build_ui(application: &Application) {
-# // Create two buttons
-# let button_increase = Button::builder()
-# .label("Increase")
-# .margin_top(12)
-# .margin_bottom(12)
-# .margin_start(12)
-# .margin_end(12)
-# .build();
+# fn build_ui(application: &Application) {
+# // Create two buttons
+# let button_increase = Button::builder()
+# .label("Increase")
+# .margin_top(12)
+# .margin_bottom(12)
+# .margin_start(12)
+# .margin_end(12)
+# .build();
#
// DOES NOT COMPILE!
// A mutable integer
@@ -124,7 +124,7 @@ By adding the `move` keyword in front of the closure, `number` will be moved int
#
# // Present the window
# window.present();
-#}
+# }
```
This still leaves the following error message:
@@ -169,7 +169,6 @@ That is exactly what the [`std::rc::Rc`](https://doc.rust-lang.org/std/rc/struct
If we want to modify the content of our [`Rc`](https://doc.rust-lang.org/std/rc/struct.Rc.html),
we can again use the [`Cell`](https://doc.rust-lang.org/std/cell/struct.Cell.html) type.
-
Filename: listings/g_object_memory_management/2/main.rs
```rust
diff --git a/book/src/main_event_loop.md b/book/src/main_event_loop.md
index d2c8b2a8023a..ad2b6113def6 100644
--- a/book/src/main_event_loop.md
+++ b/book/src/main_event_loop.md
@@ -26,7 +26,6 @@ We can't even move the window.
The `sleep` call is an artificial example,
but frequently, we want to run a slightly longer operation in one go.
-
-
## How to Avoid Blocking the Main Loop
In order to avoid blocking the main loop, we can spawn a new task with [`gio::spawn_blocking`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/gio/fn.spawn_blocking.html) and let the operation run on the thread pool.
@@ -56,7 +54,6 @@ This is not necessarily what we want.
-
> If you come from another language than Rust, you might be uncomfortable with the thought of running tasks in separate threads before even looking at other options.
> Luckily, Rust's safety guarantees allow you to stop worrying about the nasty bugs that concurrency tends to bring.
@@ -123,12 +120,12 @@ But why did we not do the same thing with our multithreaded example?
```rust ,no_run,compile_fail
# use std::{thread, time::Duration};
-#
+#
# use glib::{clone, MainContext, PRIORITY_DEFAULT};
# use gtk::{glib, gio};
# use gtk::prelude::*;
# use gtk::{Application, ApplicationWindow, Button};
-#
+#
# fn main() {
# // Create a new application
# let app = Application::builder()
@@ -137,13 +134,13 @@ But why did we not do the same thing with our multithreaded example?
#
# // Connect to "activate" signal
# app.connect_activate(build_ui);
-#
+#
# // Get command-line arguments
# let args: Vec = args().collect();
# // Run the application
# app.run(&args);
# }
-#
+#
# // When the application is launched…
# fn build_ui(application: &Application) {
# // Create a window
@@ -151,7 +148,7 @@ But why did we not do the same thing with our multithreaded example?
# .application(application)
# .title("My GTK App")
# .build();
-#
+#
# // Create a button
# let button = Button::builder()
# .label("Press me!")
@@ -160,7 +157,7 @@ But why did we not do the same thing with our multithreaded example?
# .margin_start(12)
# .margin_end(12)
# .build();
-#
+#
// DOES NOT COMPILE!
// Connect to "clicked" signal of `button`
button.connect_clicked(move |button| {
@@ -175,7 +172,7 @@ But why did we not do the same thing with our multithreaded example?
button.set_sensitive(true);
});
});
-#
+#
# // Add button
# window.set_child(Some(&button));
# window.present();
@@ -281,32 +278,32 @@ Doing this will block one of the runtime's threads with the GLib main loop, whic
Instead, we bind [`tokio::runtime::Runtime`](https://docs.rs/tokio/latest/tokio/runtime/struct.Runtime.html) to a static variable.
```rust
-#use std::sync::OnceLock;
+# use std::sync::OnceLock;
#
-#use glib::clone;
-#use gtk::glib;
-#use gtk::prelude::*;
-#use gtk::{Application, ApplicationWindow, Button};
-#use tokio::runtime::Runtime;
+# use glib::clone;
+# use gtk::glib;
+# use gtk::prelude::*;
+# use gtk::{Application, ApplicationWindow, Button};
+# use tokio::runtime::Runtime;
#
-#const APP_ID: &str = "org.gtk_rs.MainEventLoop0";
+# const APP_ID: &str = "org.gtk_rs.MainEventLoop0";
#
// DOES NOT COMPILE!
static RUNTIME: Runtime =
Runtime::new().expect("Setting up tokio runtime needs to succeed.");
#
-#fn main() -> glib::ExitCode {
-# // Create a new application
-# let app = Application::builder().application_id(APP_ID).build();
+# fn main() -> glib::ExitCode {
+# // Create a new application
+# let app = Application::builder().application_id(APP_ID).build();
#
-# // Connect to "activate" signal of `app`
-# app.connect_activate(build_ui);
+# // Connect to "activate" signal of `app`
+# app.connect_activate(build_ui);
#
-# // Run the application
-# app.run()
-#}
+# // Run the application
+# app.run()
+# }
#
-#fn build_ui(app: &Application) {
+# fn build_ui(app: &Application) {
# // Create a button
# let button = Button::builder()
# .label("Press me!")
@@ -347,7 +344,7 @@ static RUNTIME: Runtime =
#
# // Present window
# window.present();
-#}
+# }
```
Unfortunately, this doesn't compile.
@@ -362,7 +359,6 @@ consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` cr
We could follow the advice directly, but the standard library also provides solutions for that.
With [`std::sync::OnceLock`](https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html) we can initialize the static with the const function `OnceLock::new()` and initialize it the first time our function `runtime` is called.
-
Filename: listings/main_event_loop/9/main.rs
```rust
@@ -391,12 +387,12 @@ cargo remove tokio reqwest ashpd
How to find out whether you can spawn an `async` task on the `glib` main loop?
`glib` should be able to spawn the task when the called functions come from libraries that either:
+
- come from the `glib` ecosystem,
- don't depend on a runtime but only on the `futures` family of crates (`futures-io`, `futures-core` etc),
- depend on the `async-std` or `smol` runtimes, or
- have cargo features that let them depend on `async-std`/`smol` instead of `tokio`.
-
## Conclusion
You don't want to block the main thread long enough that it is noticeable by the user.
@@ -408,7 +404,7 @@ That means you have to run the task in a separate thread and let it send results
If your task is [IO bound](https://en.wikipedia.org/wiki/I/O_bound), the answer depends on the crates at your disposal and the type of work to be done.
-- Light I/O work with functions from crates using `glib`, `smol`, `async-std` or the `futures` trait family can be spawned on the main loop. This way, you can often avoid synchronization via channels.
+- Light I/O work with functions from crates using `glib`, `smol`, `async-std` or the `futures` trait family can be spawned on the main loop. This way, you can often avoid synchronization via channels.
- Heavy I/O work might still benefit from running in a separate thread / an async executor to avoid saturating the main loop. If you are unsure, benchmarking is advised.
If the best crate for the job relies on `tokio`, you will have to spawn it with the tokio runtime and communicate via channels.