From 28364023b414e0ae27cc1cb6d510680306316dc2 Mon Sep 17 00:00:00 2001 From: Julian Hofer Date: Wed, 11 Oct 2023 15:54:25 +0200 Subject: [PATCH 01/16] book: Extend main loop chapter with async section --- book/listings/Cargo.lock | 1078 ++++++++++++++++++++++- book/listings/Cargo.toml | 14 + book/listings/main_event_loop/6/main.rs | 61 ++ book/listings/main_event_loop/7/main.rs | 64 ++ book/listings/main_event_loop/8/main.rs | 42 + book/src/main_event_loop.md | 11 +- 6 files changed, 1256 insertions(+), 14 deletions(-) create mode 100644 book/listings/main_event_loop/6/main.rs create mode 100644 book/listings/main_event_loop/7/main.rs create mode 100644 book/listings/main_event_loop/8/main.rs diff --git a/book/listings/Cargo.lock b/book/listings/Cargo.lock index 748cf4ef0a04..541f41a541ce 100644 --- a/book/listings/Cargo.lock +++ b/book/listings/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.72" @@ -9,6 +18,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] +<<<<<<< HEAD +======= +name = "ashpd" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3affe251686bd936a0afb74b9693e8bf2f193d51da1b9a45d3f1303a9bd2cc7" +dependencies = [ + "async-std", + "enumflags2", + "futures-channel", + "futures-util", + "gdk4-wayland", + "gdk4-x11", + "gtk4", + "once_cell", + "rand", + "serde", + "serde_repr", + "url", + "zbus", +] + +[[package]] +name = "async-broadcast" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" +dependencies = [ + "event-listener", + "futures-core", +] + +[[package]] +>>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "async-channel" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -20,6 +63,157 @@ dependencies = [ ] [[package]] +<<<<<<< HEAD +======= +name = "async-executor" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1da3ae8dabd9c00f453a329dfe1fb28da3c0a72e2478cdcd93171740c20499" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand 2.0.1", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +dependencies = [ + "async-lock", + "autocfg", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-global-executor" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite", + "log", + "parking", + "polling", + "rustix 0.37.24", + "slab", + "socket2", + "waker-fn", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-process" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +dependencies = [ + "async-io", + "async-lock", + "autocfg", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 0.37.24", + "signal-hook", + "windows-sys", +] + +[[package]] +name = "async-recursion" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9441c6b2fe128a7c2bf680a44c34d0df31ce09e5b7e401fcca3faa483dbc921" + +[[package]] +name = "async-trait" +version = "0.1.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +>>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -37,6 +231,43 @@ version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c36a4d0d48574b3dd360b4b7d95cc651d2b6557b6402848a27d4b228a473e2a" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "fastrand 2.0.1", + "futures-io", + "futures-lite", + "piper", + "tracing", +] + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "cairo-rs" version = "0.18.0" @@ -88,6 +319,18 @@ dependencies = [ ] [[package]] +<<<<<<< HEAD +======= +name = "cpufeatures" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +dependencies = [ + "libc", +] + +[[package]] +>>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "crossbeam-utils" version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -97,6 +340,40 @@ dependencies = [ ] [[package]] +<<<<<<< HEAD +======= +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +>>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "dirs" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -117,6 +394,27 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "enumflags2" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5998b4f30320c9d93aed72f63af821bfdac50465b75428fce77b48ec482c3939" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -124,21 +422,61 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] +<<<<<<< HEAD +======= +name = "errno" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +>>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "event-listener" version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] +<<<<<<< HEAD +======= +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + +[[package]] +>>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "field-offset" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ - "memoffset", + "memoffset 0.9.0", "rustc_version", ] +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + [[package]] name = "futures-channel" version = "0.3.28" @@ -171,6 +509,21 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.28" @@ -182,6 +535,12 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + [[package]] name = "futures-task" version = "0.3.28" @@ -195,8 +554,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-core", + "futures-io", "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", @@ -260,6 +622,65 @@ dependencies = [ "system-deps", ] +[[package]] +name = "gdk4-wayland" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0db9102ff11e55bd65e153c1192abc21ddfa45ede90622e423d4e4a0e5d5f313" +dependencies = [ + "gdk4", + "gdk4-wayland-sys", + "gio", + "glib", + "libc", +] + +[[package]] +name = "gdk4-wayland-sys" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d48159be256ae0212d5a2b9884627197d08082c7168b28775b53a0f9885d5624" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk4-x11" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c9bbf8ea1ea8469e74c3fdfafc142c9e14810a27f89ddb01b5e9076a60a450" +dependencies = [ + "gdk4", + "gdk4-x11-sys", + "gio", + "glib", + "libc", +] + +[[package]] +name = "gdk4-x11-sys" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3de1709370758192369f5329aa593847797f1c693c95e8a261e9b2e06a5f125" +dependencies = [ + "gdk4-sys", + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -356,6 +777,18 @@ dependencies = [ "system-deps", ] +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "gobject-sys" version = "0.18.0" @@ -461,7 +894,11 @@ name = "gtk4-rs-book-listings" version = "0.1.0" dependencies = [ "anyhow", +<<<<<<< HEAD "async-channel", +======= + "ashpd", +>>>>>>> b238756d02 (book: Extend main loop chapter with async section) "dirs", "glib-build-tools", "gtk4", @@ -505,23 +942,83 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] -name = "indexmap" -version = "2.0.0" +name = "hermit-abi" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" -dependencies = [ - "equivalent", - "hashbrown", -] +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] -name = "itoa" -version = "1.0.9" +name = "hex" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] -name = "libadwaita" +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "libadwaita" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06444f4ca05a60693da6e9e2b591bd40a298e65a118a8d5e830771718b3e0253" @@ -558,12 +1055,42 @@ version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +dependencies = [ + "value-bag", +] + [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.9.0" @@ -573,6 +1100,18 @@ dependencies = [ "autocfg", ] +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -585,6 +1124,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "pango" version = "0.18.0" @@ -610,6 +1159,18 @@ dependencies = [ "system-deps", ] +[[package]] +name = "parking" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + [[package]] name = "pin-project-lite" version = "0.2.10" @@ -622,12 +1183,45 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.1", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -680,6 +1274,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -689,6 +1313,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_users" version = "0.4.3" @@ -696,10 +1329,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", - "redox_syscall", + "redox_syscall 0.2.16", "thiserror", ] +[[package]] +name = "regex" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "rustc_version" version = "0.4.0" @@ -709,6 +1371,33 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.37.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4279d76516df406a8bd37e7dff53fd37d1a093f997a3c34a5c21658c126db06d" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys", +] + +[[package]] +name = "rustix" +version = "0.38.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys 0.4.10", + "windows-sys", +] + [[package]] name = "ryu" version = "1.0.15" @@ -761,6 +1450,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "serde_spanned" version = "0.6.3" @@ -770,6 +1470,36 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.8" @@ -785,6 +1515,22 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "syn" version = "1.0.109" @@ -826,6 +1572,19 @@ version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +dependencies = [ + "cfg-if", + "fastrand 2.0.1", + "redox_syscall 0.3.5", + "rustix 0.38.8", + "windows-sys", +] + [[package]] name = "thiserror" version = "1.0.44" @@ -846,6 +1605,21 @@ dependencies = [ "syn 2.0.28", ] +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "toml" version = "0.7.6" @@ -880,12 +1654,93 @@ dependencies = [ "winnow", ] +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "uds_windows" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" +dependencies = [ + "tempfile", + "winapi", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + [[package]] name = "unicode-ident" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "value-bag" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3" + [[package]] name = "version-compare" version = "0.1.1" @@ -898,6 +1753,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "waker-fn" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" + [[package]] name = "walkdir" version = "2.3.3" @@ -914,6 +1775,82 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.28", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1020,6 +1957,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "xdg-home" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" +dependencies = [ + "nix", + "winapi", +] + [[package]] name = "xshell" version = "0.2.5" @@ -1034,3 +1981,108 @@ name = "xshell-macros" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e2c411759b501fb9501aac2b1b2d287a6e93e5bdcf13c25306b23e1b716dd0e" + +[[package]] +name = "zbus" +version = "3.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "byteorder", + "derivative", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "once_cell", + "ordered-stream", + "rand", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "winapi", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "3.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb80bb776dbda6e23d705cf0123c3b95df99c4ebeaec6c2599d4a5419902b4a9" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zvariant" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c" +dependencies = [ + "byteorder", + "enumflags2", + "libc", + "serde", + "static_assertions", + "url", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] diff --git a/book/listings/Cargo.toml b/book/listings/Cargo.toml index 93b9535d4ef2..af0c448c2ad3 100644 --- a/book/listings/Cargo.toml +++ b/book/listings/Cargo.toml @@ -15,6 +15,7 @@ xshell = "0.2" dirs = "5.0" walkdir = "2.3" async-channel = "1.9.0" +ashpd = { version = "0.6.2", features = ["gtk4"] } [build-dependencies] glib-build-tools = "0.18" @@ -206,6 +207,19 @@ path = "main_event_loop/4/main.rs" name = "main_event_loop_5" path = "main_event_loop/5/main.rs" +[[bin]] +name = "main_event_loop_6" +path = "main_event_loop/6/main.rs" + +[[bin]] +name = "main_event_loop_7" +path = "main_event_loop/7/main.rs" + +[[bin]] +name = "main_event_loop_8" +path = "main_event_loop/8/main.rs" + + # saving_window_state [[bin]] name = "saving_window_state_1" diff --git a/book/listings/main_event_loop/6/main.rs b/book/listings/main_event_loop/6/main.rs new file mode 100644 index 000000000000..e00d14399ac8 --- /dev/null +++ b/book/listings/main_event_loop/6/main.rs @@ -0,0 +1,61 @@ +use glib::{clone, MainContext}; +use gtk::prelude::*; +use gtk::{gio, glib}; +use gtk::{Application, ApplicationWindow, Button}; +use std::thread; +use std::time::Duration; + +const APP_ID: &str = "org.gtk_rs.MainEventLoop5"; + +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); + + // Run the application + app.run() +} + +fn build_ui(app: &Application) { + // Create a button + let button = Button::builder() + .label("Press me!") + .margin_top(12) + .margin_bottom(12) + .margin_start(12) + .margin_end(12) + .build(); + + // ANCHOR: callback + // Connect to "clicked" signal of `button` + button.connect_clicked(move |button| { + let main_context = MainContext::default(); + // The main loop executes the asynchronous block + main_context.spawn_local(clone!(@weak button => async move { + // Deactivate the button until the operation is done + button.set_sensitive(false); + let enable_button = gio::spawn_blocking(move || { + let ten_seconds = Duration::from_secs(10); + thread::sleep(ten_seconds); + true + }) + .await + .expect("Task needs to finish successfully."); + // Set sensitivity of button to `enable_button` + button.set_sensitive(enable_button); + })); + }); + // ANCHOR_END: callback + + // Create a window + let window = ApplicationWindow::builder() + .application(app) + .title("My GTK App") + .child(&button) + .build(); + + // Present window + window.present(); +} diff --git a/book/listings/main_event_loop/7/main.rs b/book/listings/main_event_loop/7/main.rs new file mode 100644 index 000000000000..b4b92ef0ad82 --- /dev/null +++ b/book/listings/main_event_loop/7/main.rs @@ -0,0 +1,64 @@ +use ashpd::desktop::account::UserInformation; +use ashpd::WindowIdentifier; +use glib::{clone, MainContext}; +use gtk::prelude::*; +use gtk::{glib, Application, ApplicationWindow, Button}; + +const APP_ID: &str = "org.gtk_rs.MainEventLoop5"; + +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); + + // Run the application + app.run() +} + +fn build_ui(app: &Application) { + // Create a button + let button = Button::builder() + .label("Press me!") + .margin_top(12) + .margin_bottom(12) + .margin_start(12) + .margin_end(12) + .build(); + + // ANCHOR: callback + // Connect to "clicked" signal of `button` + button.connect_clicked(move |button| { + let main_context = MainContext::default(); + // The main loop executes the asynchronous block + main_context.spawn_local(clone!(@weak button => async move { + // Get native of button for window indentifier + let native = button.native().expect("Need to be able to get native."); + // Get window identifier so that the dialog will be modal to the main window + let identifier = WindowIdentifier::from_native(&native).await; + let request = UserInformation::request() + .reason("App would like to access user information") + .identifier(identifier) + .send() + .await; + + if let Ok(Ok(response)) = request.map(|r| r.response()) { + println!("User name: {}", response.name()); + } else { + println!("Could not access user information.") + } + })); + }); + // ANCHOR_END: callback + + // Create a window + let window = ApplicationWindow::builder() + .application(app) + .title("My GTK App") + .child(&button) + .build(); + + // Present window + window.present(); +} diff --git a/book/listings/main_event_loop/8/main.rs b/book/listings/main_event_loop/8/main.rs new file mode 100644 index 000000000000..db5af3a927a2 --- /dev/null +++ b/book/listings/main_event_loop/8/main.rs @@ -0,0 +1,42 @@ +use gtk::prelude::*; +use gtk::{glib, Application, ApplicationWindow, Button}; + +const APP_ID: &str = "org.gtk_rs.MainEventLoop5"; + +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); + + // Run the application + app.run() +} + +fn build_ui(app: &Application) { + // Create a button + let button = Button::builder() + .label("Press me!") + .margin_top(12) + .margin_bottom(12) + .margin_start(12) + .margin_end(12) + .build(); + + // ANCHOR: callback + // Connect to "clicked" signal of `button` + button + .connect_clicked(move |_| todo!("Execute web request with reqwest and tokio")); + // ANCHOR_END: callback + + // Create a window + let window = ApplicationWindow::builder() + .application(app) + .title("My GTK App") + .child(&button) + .build(); + + // Present window + window.present(); +} diff --git a/book/src/main_event_loop.md b/book/src/main_event_loop.md index 3553d03af161..36b0cfa2ba5d 100644 --- a/book/src/main_event_loop.md +++ b/book/src/main_event_loop.md @@ -176,6 +176,15 @@ help: within `gtk4::Button`, the trait `Sync` is not implemented for `NonNull Date: Wed, 11 Oct 2023 16:25:29 +0200 Subject: [PATCH 02/16] Update book/listings/main_event_loop/7/main.rs Co-authored-by: Bilal Elmoussaoui --- book/listings/main_event_loop/7/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/listings/main_event_loop/7/main.rs b/book/listings/main_event_loop/7/main.rs index b4b92ef0ad82..c0d02d87eba9 100644 --- a/book/listings/main_event_loop/7/main.rs +++ b/book/listings/main_event_loop/7/main.rs @@ -43,7 +43,7 @@ fn build_ui(app: &Application) { .send() .await; - if let Ok(Ok(response)) = request.map(|r| r.response()) { + if let Ok(response) = request.and_then(|r| r.response()) { println!("User name: {}", response.name()); } else { println!("Could not access user information.") From 9316f2e58fce88d00fd97f2f4dc4fe120630b096 Mon Sep 17 00:00:00 2001 From: Julian Hofer Date: Fri, 20 Oct 2023 17:08:06 +0200 Subject: [PATCH 03/16] book: Fix typo --- book/listings/main_event_loop/7/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/listings/main_event_loop/7/main.rs b/book/listings/main_event_loop/7/main.rs index c0d02d87eba9..27d843914f81 100644 --- a/book/listings/main_event_loop/7/main.rs +++ b/book/listings/main_event_loop/7/main.rs @@ -33,12 +33,12 @@ fn build_ui(app: &Application) { let main_context = MainContext::default(); // The main loop executes the asynchronous block main_context.spawn_local(clone!(@weak button => async move { - // Get native of button for window indentifier + // Get native of button for window identifier let native = button.native().expect("Need to be able to get native."); // Get window identifier so that the dialog will be modal to the main window let identifier = WindowIdentifier::from_native(&native).await; let request = UserInformation::request() - .reason("App would like to access user information") + .reason("App would like to access user information.") .identifier(identifier) .send() .await; From 7bd61a9a67a1847378b41c37c662639e7841a542 Mon Sep 17 00:00:00 2001 From: Julian Hofer Date: Fri, 20 Oct 2023 18:09:11 +0200 Subject: [PATCH 04/16] book: Add tokio and reqwest listing --- book/listings/Cargo.lock | 495 +++++++++++++++++++++++- book/listings/Cargo.toml | 2 + book/listings/main_event_loop/8/main.rs | 32 +- book/src/main_event_loop.md | 21 +- 4 files changed, 541 insertions(+), 9 deletions(-) diff --git a/book/listings/Cargo.lock b/book/listings/Cargo.lock index 541f41a541ce..14181167a0c0 100644 --- a/book/listings/Cargo.lock +++ b/book/listings/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aho-corasick" version = "1.1.2" @@ -121,7 +136,7 @@ dependencies = [ "polling", "rustix 0.37.24", "slab", - "socket2", + "socket2 0.4.9", "waker-fn", ] @@ -219,6 +234,27 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" + [[package]] name = "bitflags" version = "1.3.2" @@ -268,6 +304,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + [[package]] name = "cairo-rs" version = "0.18.0" @@ -293,6 +335,15 @@ dependencies = [ "system-deps", ] +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + [[package]] name = "cfg-expr" version = "0.15.4" @@ -320,7 +371,26 @@ dependencies = [ [[package]] <<<<<<< HEAD +<<<<<<< HEAD ======= +======= +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +>>>>>>> e6a11799e4 (book: Add tokio and reqwest listing) name = "cpufeatures" version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -394,6 +464,15 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + [[package]] name = "enumflags2" version = "0.7.8" @@ -468,6 +547,12 @@ dependencies = [ "rustc_version", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "form_urlencoded" version = "1.2.0" @@ -692,6 +777,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + [[package]] name = "gio" version = "0.18.1" @@ -904,8 +995,10 @@ dependencies = [ "gtk4", "libadwaita", "once_cell", + "reqwest", "serde", "serde_json", + "tokio", "walkdir", "xshell", ] @@ -929,6 +1022,31 @@ dependencies = [ "system-deps", ] +[[package]] +name = "h2" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 1.9.3", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.0" @@ -953,6 +1071,78 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2 0.4.9", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + [[package]] name = "idna" version = "0.4.0" @@ -963,6 +1153,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.0.0" @@ -970,7 +1170,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.0", ] [[package]] @@ -993,6 +1193,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "ipnet" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" + [[package]] name = "itoa" version = "1.0.9" @@ -1100,6 +1306,32 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + [[package]] name = "nix" version = "0.26.4" @@ -1112,6 +1344,25 @@ dependencies = [ "memoffset 0.7.1", ] +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -1173,9 +1424,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -1362,6 +1613,67 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +[[package]] +name = "reqwest" +version = "0.11.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "system-configuration", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc_version" version = "0.4.0" @@ -1398,6 +1710,37 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "rustls" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +dependencies = [ + "base64", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "ryu" version = "1.0.15" @@ -1413,6 +1756,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "semver" version = "1.0.18" @@ -1470,6 +1823,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "sha1" version = "0.10.6" @@ -1525,6 +1890,22 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "static_assertions" version = "1.1.0" @@ -1553,6 +1934,27 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "6.1.1" @@ -1620,6 +2022,46 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokio" +version = "1.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2 0.5.4", + "windows-sys", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + [[package]] name = "toml" version = "0.7.6" @@ -1647,13 +2089,19 @@ version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ - "indexmap", + "indexmap 2.0.0", "serde", "serde_spanned", "toml_datetime", "winnow", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.37" @@ -1686,6 +2134,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + [[package]] name = "typenum" version = "1.17.0" @@ -1723,6 +2177,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.4.1" @@ -1769,6 +2229,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1851,6 +2320,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" + [[package]] name = "winapi" version = "0.3.9" @@ -1957,6 +2432,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys", +] + [[package]] name = "xdg-home" version = "1.0.0" diff --git a/book/listings/Cargo.toml b/book/listings/Cargo.toml index af0c448c2ad3..ac10b9292927 100644 --- a/book/listings/Cargo.toml +++ b/book/listings/Cargo.toml @@ -16,6 +16,8 @@ dirs = "5.0" walkdir = "2.3" async-channel = "1.9.0" ashpd = { version = "0.6.2", features = ["gtk4"] } +tokio = { version = "1.33.0", features = ["rt-multi-thread"] } +reqwest = { version = "0.11", default-features = false, features = ["rustls-tls"] } [build-dependencies] glib-build-tools = "0.18" diff --git a/book/listings/main_event_loop/8/main.rs b/book/listings/main_event_loop/8/main.rs index db5af3a927a2..7c98be4fd842 100644 --- a/book/listings/main_event_loop/8/main.rs +++ b/book/listings/main_event_loop/8/main.rs @@ -1,8 +1,17 @@ +use glib::{clone, MainContext, Priority}; +use gtk::glib; use gtk::prelude::*; -use gtk::{glib, Application, ApplicationWindow, Button}; +use gtk::{Application, ApplicationWindow, Button}; +use once_cell::sync::Lazy; +use tokio::runtime::Runtime; const APP_ID: &str = "org.gtk_rs.MainEventLoop5"; +// ANCHOR: tokio_runtime +static RUNTIME: Lazy = + Lazy::new(|| Runtime::new().expect("Setting up tokio runtime needs to succeed.")); +// ANCHOR_END: tokio_runtime + fn main() -> glib::ExitCode { // Create a new application let app = Application::builder().application_id(APP_ID).build(); @@ -25,9 +34,26 @@ fn build_ui(app: &Application) { .build(); // ANCHOR: callback + let (sender, receiver) = MainContext::channel(Priority::default()); // Connect to "clicked" signal of `button` - button - .connect_clicked(move |_| todo!("Execute web request with reqwest and tokio")); + button.connect_clicked(move |_| { + RUNTIME.spawn(clone!(@strong sender => async move { + let response = reqwest::get("https://www.gtk-rs.org").await; + sender + .send(response) + .expect("Could not send through channel"); + })); + }); + + // The main loop executes the closure as soon as it receives the message + receiver.attach(None, move |response| { + if let Ok(response) = response { + println!("Status {}", response.status()); + } else { + println!("Couldn't make a `GET` request."); + } + glib::ControlFlow::Continue + }); // ANCHOR_END: callback // Create a window diff --git a/book/src/main_event_loop.md b/book/src/main_event_loop.md index 36b0cfa2ba5d..fadc187645c8 100644 --- a/book/src/main_event_loop.md +++ b/book/src/main_event_loop.md @@ -178,10 +178,29 @@ After reference cycles we found the second disadvantage of GTK GObjects: They ar ## Async +```rust +{{#rustdoc_include ../listings/main_event_loop/6/main.rs:callback}} +``` +``` +cargo add ashpd@0.6 --features gtk4 +``` + +```rust +{{#rustdoc_include ../listings/main_event_loop/7/main.rs:callback}} +``` ``` -cargo add ashpd --features gtk4 +cargo add tokio@1 --features rt-multi-thread +cargo add reqwest@0.11 --features rustls-tls --no-default-features +``` + +```rust +{{#rustdoc_include ../listings/main_event_loop/8/main.rs:tokio_runtime}} +``` + +```rust +{{#rustdoc_include ../listings/main_event_loop/8/main.rs:callback}} ``` From c37ef6d960d054be8774c08e363bcd62cd3a0480 Mon Sep 17 00:00:00 2001 From: Julian Hofer Date: Fri, 20 Oct 2023 18:25:07 +0200 Subject: [PATCH 05/16] book: Fix app ids --- book/listings/main_event_loop/6/main.rs | 2 +- book/listings/main_event_loop/7/main.rs | 2 +- book/listings/main_event_loop/8/main.rs | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/book/listings/main_event_loop/6/main.rs b/book/listings/main_event_loop/6/main.rs index e00d14399ac8..5fe88068168c 100644 --- a/book/listings/main_event_loop/6/main.rs +++ b/book/listings/main_event_loop/6/main.rs @@ -5,7 +5,7 @@ use gtk::{Application, ApplicationWindow, Button}; use std::thread; use std::time::Duration; -const APP_ID: &str = "org.gtk_rs.MainEventLoop5"; +const APP_ID: &str = "org.gtk_rs.MainEventLoop6"; fn main() -> glib::ExitCode { // Create a new application diff --git a/book/listings/main_event_loop/7/main.rs b/book/listings/main_event_loop/7/main.rs index 27d843914f81..a7454d120aab 100644 --- a/book/listings/main_event_loop/7/main.rs +++ b/book/listings/main_event_loop/7/main.rs @@ -4,7 +4,7 @@ use glib::{clone, MainContext}; use gtk::prelude::*; use gtk::{glib, Application, ApplicationWindow, Button}; -const APP_ID: &str = "org.gtk_rs.MainEventLoop5"; +const APP_ID: &str = "org.gtk_rs.MainEventLoop7"; fn main() -> glib::ExitCode { // Create a new application diff --git a/book/listings/main_event_loop/8/main.rs b/book/listings/main_event_loop/8/main.rs index 7c98be4fd842..99287d88cee0 100644 --- a/book/listings/main_event_loop/8/main.rs +++ b/book/listings/main_event_loop/8/main.rs @@ -5,12 +5,10 @@ use gtk::{Application, ApplicationWindow, Button}; use once_cell::sync::Lazy; use tokio::runtime::Runtime; -const APP_ID: &str = "org.gtk_rs.MainEventLoop5"; - // ANCHOR: tokio_runtime +const APP_ID: &str = "org.gtk_rs.MainEventLoop8"; static RUNTIME: Lazy = Lazy::new(|| Runtime::new().expect("Setting up tokio runtime needs to succeed.")); -// ANCHOR_END: tokio_runtime fn main() -> glib::ExitCode { // Create a new application @@ -22,6 +20,7 @@ fn main() -> glib::ExitCode { // Run the application app.run() } +// ANCHOR_END: tokio_runtime fn build_ui(app: &Application) { // Create a button From a82d1c991c31723b94b2113be8f7b0f1f5eef396 Mon Sep 17 00:00:00 2001 From: Julian Hofer Date: Fri, 20 Oct 2023 18:25:18 +0200 Subject: [PATCH 06/16] book: Add filenames --- book/src/main_event_loop.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/book/src/main_event_loop.md b/book/src/main_event_loop.md index fadc187645c8..df340291f9c2 100644 --- a/book/src/main_event_loop.md +++ b/book/src/main_event_loop.md @@ -178,6 +178,8 @@ After reference cycles we found the second disadvantage of GTK GObjects: They ar ## Async +Filename: listings/main_event_loop/6/main.rs + ```rust {{#rustdoc_include ../listings/main_event_loop/6/main.rs:callback}} ``` @@ -186,6 +188,8 @@ After reference cycles we found the second disadvantage of GTK GObjects: They ar cargo add ashpd@0.6 --features gtk4 ``` +Filename: listings/main_event_loop/7/main.rs + ```rust {{#rustdoc_include ../listings/main_event_loop/7/main.rs:callback}} ``` @@ -195,10 +199,14 @@ cargo add tokio@1 --features rt-multi-thread cargo add reqwest@0.11 --features rustls-tls --no-default-features ``` +Filename: listings/main_event_loop/8/main.rs + ```rust {{#rustdoc_include ../listings/main_event_loop/8/main.rs:tokio_runtime}} ``` +Filename: listings/main_event_loop/8/main.rs + ```rust {{#rustdoc_include ../listings/main_event_loop/8/main.rs:callback}} ``` From e19619296fa1b7f079ada0f9f707ae64f4e32198 Mon Sep 17 00:00:00 2001 From: Julian Hofer Date: Sat, 21 Oct 2023 12:03:09 +0200 Subject: [PATCH 07/16] Explain spawn_blocking in async context and ashpd --- book/src/img/main_event_loop_ashpd.png | Bin 0 -> 37595 bytes book/src/main_event_loop.md | 28 ++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 book/src/img/main_event_loop_ashpd.png diff --git a/book/src/img/main_event_loop_ashpd.png b/book/src/img/main_event_loop_ashpd.png new file mode 100644 index 0000000000000000000000000000000000000000..30f05e5461b3577d9552123f5f0f75b84fc2096e GIT binary patch literal 37595 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/main_event_loop/6/main.rs ```rust {{#rustdoc_include ../listings/main_event_loop/6/main.rs:callback}} ``` +Asynchronous functions from the glib ecosystem can always be spawned on the glib main loop. +Typically, crates from the async-std/smol ecosystem work as well. +Let us take ashpd for example which allows sandboxed applications to interact with the desktop. +Per default it depends on `async-std`. +We can add it to our dependencies by running the following command. + ``` -cargo add ashpd@0.6 --features gtk4 +cargo add ashpd --features gtk4 ``` +You need to use a Linux desktop environment in order to run the following example locally. +We are using [`ashpd::desktop::account::UserInformation`](https://docs.rs/ashpd/latest/ashpd/desktop/account/index.html) in order to access user information. +We are getting a [`gtk::Native`](https://gtk-rs.org/gtk4-rs/stable/latest/docs/gtk4/struct.Native.html) object from our button, create a [`ashpd::WindowIdentifier`](https://docs.rs/ashpd/latest/ashpd/enum.WindowIdentifier.html) and pass it to the user information request. +That way the dialog that will pop up will be modal. +That means that it will be on top of the window and freezes the rest of the application from user input. + Filename: listings/main_event_loop/7/main.rs ```rust {{#rustdoc_include ../listings/main_event_loop/7/main.rs:callback}} ``` +After pressing the button, a dialog should open that shows the information that will be shared. +If you decide to share it, you user name will be printed on the console. + +
Dialog requesting user information.
+ + ``` cargo add tokio@1 --features rt-multi-thread cargo add reqwest@0.11 --features rustls-tls --no-default-features From 7673824c642ba8a267935ef029085adc1b9ffa1f Mon Sep 17 00:00:00 2001 From: Julian Hofer Date: Sun, 22 Oct 2023 12:59:46 +0200 Subject: [PATCH 08/16] book: Add example that reqwest fails without tokio --- book/listings/Cargo.lock | 402 ++++++++++++------------ book/listings/Cargo.toml | 3 + book/listings/main_event_loop/8/main.rs | 12 +- book/listings/main_event_loop/9/main.rs | 67 ++++ book/src/main_event_loop.md | 18 +- 5 files changed, 291 insertions(+), 211 deletions(-) create mode 100644 book/listings/main_event_loop/9/main.rs diff --git a/book/listings/Cargo.lock b/book/listings/Cargo.lock index 14181167a0c0..79148665fab8 100644 --- a/book/listings/Cargo.lock +++ b/book/listings/Cargo.lock @@ -28,17 +28,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.72" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] -<<<<<<< HEAD -======= name = "ashpd" -version = "0.6.2" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3affe251686bd936a0afb74b9693e8bf2f193d51da1b9a45d3f1303a9bd2cc7" +checksum = "2c018490e423efb6f032ef575f873ea57b61d44bec763cfe027b8e8852a027cf" dependencies = [ "async-std", "enumflags2", @@ -61,29 +59,26 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" dependencies = [ - "event-listener", + "event-listener 2.5.3", "futures-core", ] [[package]] ->>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "async-channel" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 2.5.3", "futures-core", ] [[package]] -<<<<<<< HEAD -======= name = "async-executor" -version = "1.5.4" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1da3ae8dabd9c00f453a329dfe1fb28da3c0a72e2478cdcd93171740c20499" +checksum = "4b0c4a4f319e45986f347ee47fef8bf5e81c9abc3f6f58dc2391439f30df65f0" dependencies = [ "async-lock", "async-task", @@ -134,9 +129,9 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.24", + "rustix 0.37.26", "slab", - "socket2 0.4.9", + "socket2 0.4.10", "waker-fn", ] @@ -146,24 +141,23 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener", + "event-listener 2.5.3", ] [[package]] name = "async-process" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" dependencies = [ "async-io", "async-lock", - "autocfg", + "async-signal", "blocking", "cfg-if", - "event-listener", + "event-listener 3.0.0", "futures-lite", - "rustix 0.37.24", - "signal-hook", + "rustix 0.38.20", "windows-sys", ] @@ -175,7 +169,25 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.38", +] + +[[package]] +name = "async-signal" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2a5415b7abcdc9cd7d63d6badba5288b2ca017e3fbd4173b8f405449f1a2399" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.20", + "signal-hook-registry", + "slab", + "windows-sys", ] [[package]] @@ -206,19 +218,19 @@ dependencies = [ [[package]] name = "async-task" -version = "4.4.1" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9441c6b2fe128a7c2bf680a44c34d0df31ce09e5b7e401fcca3faa483dbc921" +checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.38", ] [[package]] @@ -228,7 +240,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] ->>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -263,9 +274,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "block-buffer" @@ -312,11 +323,11 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cairo-rs" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d859b656775a6b1dd078d3e5924884e6ea88aa649a7fdde03d5b2ec56ffcc10b" +checksum = "1c0466dfa8c0ee78deef390c274ad756801e0a6dbb86c5ef0924a298c5761c4d" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "cairo-sys-rs", "glib", "libc", @@ -326,9 +337,9 @@ dependencies = [ [[package]] name = "cairo-sys-rs" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd4d115132e01c0165e3bf5f56aedee8980b0b96ede4eb000b693c05a8adb8ff" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" dependencies = [ "glib-sys", "libc", @@ -346,9 +357,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b40ccee03b5175c18cde8f37e7d2a33bcef6f8ec8f7cc0d81090d1bb380949c9" +checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" dependencies = [ "smallvec", "target-lexicon", @@ -370,10 +381,6 @@ dependencies = [ ] [[package]] -<<<<<<< HEAD -<<<<<<< HEAD -======= -======= name = "core-foundation" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -390,17 +397,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] ->>>>>>> e6a11799e4 (book: Add tokio and reqwest listing) name = "cpufeatures" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" dependencies = [ "libc", ] [[package]] ->>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "crossbeam-utils" version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -410,8 +415,6 @@ dependencies = [ ] [[package]] -<<<<<<< HEAD -======= name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -443,7 +446,6 @@ dependencies = [ ] [[package]] ->>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "dirs" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -491,7 +493,7 @@ checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.38", ] [[package]] @@ -501,8 +503,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -<<<<<<< HEAD -======= name = "errno" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -513,15 +513,23 @@ dependencies = [ ] [[package]] ->>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "event-listener" version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] -<<<<<<< HEAD -======= +name = "event-listener" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e56284f00d94c1bc7fd3c77027b4623c88c1f53d8d2394c6199f2921dea325" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] name = "fastrand" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -537,7 +545,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] ->>>>>>> b238756d02 (book: Extend main loop chapter with async section) name = "field-offset" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -617,7 +624,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.38", ] [[package]] @@ -677,9 +684,9 @@ dependencies = [ [[package]] name = "gdk4" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8965ed5455cbfa1eb45c14a3b971cbacb43481913a3a5b9078b2ef0d9a01bd4b" +checksum = "7edb019ad581f8ecf8ea8e4baa6df7c483a95b5a59be3140be6a9c3b0c632af6" dependencies = [ "cairo-rs", "gdk-pixbuf", @@ -692,9 +699,9 @@ dependencies = [ [[package]] name = "gdk4-sys" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeffd4a7d68046c28666d817071bf025254aaed4df35099443f0c306ca6177f3" +checksum = "dbab43f332a3cf1df9974da690b5bb0e26720ed09a228178ce52175372dcfef0" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -785,9 +792,9 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "gio" -version = "0.18.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7884cba6b1c5db1607d970cadf44b14a43913d42bc68766eea6a5e2fe0891524" +checksum = "57052f84e8e5999b258e8adf8f5f2af0ac69033864936b8b6838321db2f759b1" dependencies = [ "futures-channel", "futures-core", @@ -817,11 +824,11 @@ dependencies = [ [[package]] name = "glib" -version = "0.18.1" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "331156127e8166dd815cf8d2db3a5beb492610c716c03ee6db4f2d07092af0a7" +checksum = "1c316afb01ce8067c5eaab1fc4f2cd47dc21ce7b6296358605e2ffab23ccbd19" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "futures-channel", "futures-core", "futures-executor", @@ -846,16 +853,16 @@ checksum = "3431c56f463443cba9bc3600248bc6d680cb614c2ee1cdd39dab5415bd12ac5c" [[package]] name = "glib-macros" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "179643c50bf28d20d2f6eacd2531a88f2f5d9747dd0b86b8af1e8bb5dd0de3c0" +checksum = "f8da903822b136d42360518653fcf154455defc437d3e7a81475bf9a95ff1e47" dependencies = [ "heck", "proc-macro-crate", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.38", ] [[package]] @@ -916,9 +923,9 @@ dependencies = [ [[package]] name = "gsk4" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b3b9e8090acb325d08cde84b30fc29b963a75fbac93160e9c5a30d2b335742" +checksum = "0d958e351d2f210309b32d081c832d7de0aca0b077aa10d88336c6379bd01f7e" dependencies = [ "cairo-rs", "gdk4", @@ -931,9 +938,9 @@ dependencies = [ [[package]] name = "gsk4-sys" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0770d1ede7189092748c4ef5b6921264eb945fd2318a58e8f59dc273000810f8" +checksum = "12bd9e3effea989f020e8f1ff3fa3b8c63ba93d43b899c11a118868853a56d55" dependencies = [ "cairo-sys-rs", "gdk4-sys", @@ -947,9 +954,9 @@ dependencies = [ [[package]] name = "gtk4" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0973f9b9ade10fc22403810b7283d47b533033715f2aaa36288cd3bf90d63efc" +checksum = "5aeb51aa3e9728575a053e1f43543cd9992ac2477e1b186ad824fd4adfb70842" dependencies = [ "cairo-rs", "field-offset", @@ -968,9 +975,9 @@ dependencies = [ [[package]] name = "gtk4-macros" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9f2c4530f3168fe506b0be7bc15f7a93ef38d020edb27d81a921a26cbca851" +checksum = "d57ec49cf9b657f69a05bca8027cff0a8dfd0c49e812be026fc7311f2163832f" dependencies = [ "anyhow", "proc-macro-crate", @@ -985,11 +992,8 @@ name = "gtk4-rs-book-listings" version = "0.1.0" dependencies = [ "anyhow", -<<<<<<< HEAD - "async-channel", -======= "ashpd", ->>>>>>> b238756d02 (book: Extend main loop chapter with async section) + "async-channel", "dirs", "glib-build-tools", "gtk4", @@ -1005,9 +1009,9 @@ dependencies = [ [[package]] name = "gtk4-sys" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19fde71ef2e78ac8fb18073c345b5f29609048d4045a345613645aa1163243c1" +checksum = "54d8c4aa23638ce9faa2caf7e2a27d4a1295af2155c8e8d28c4d4eeca7a65eb8" dependencies = [ "cairo-sys-rs", "gdk-pixbuf-sys", @@ -1049,9 +1053,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "heck" @@ -1122,7 +1126,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -1165,12 +1169,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.2", ] [[package]] @@ -1225,9 +1229,9 @@ dependencies = [ [[package]] name = "libadwaita" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06444f4ca05a60693da6e9e2b591bd40a298e65a118a8d5e830771718b3e0253" +checksum = "2fe7e70c06507ed10a16cda707f358fbe60fe0dc237498f78c686ade92fd979c" dependencies = [ "gdk-pixbuf", "gdk4", @@ -1241,9 +1245,9 @@ dependencies = [ [[package]] name = "libadwaita-sys" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021cfe3d1fcfa82411765a791f7e9b32f35dd98ce88d2e3fa10e7320f5cc8ce7" +checksum = "5e10aaa38de1d53374f90deeb4535209adc40cc5dba37f9704724169bceec69a" dependencies = [ "gdk4-sys", "gio-sys", @@ -1257,9 +1261,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" [[package]] name = "linux-raw-sys" @@ -1284,9 +1288,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -1412,9 +1416,9 @@ dependencies = [ [[package]] name = "parking" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52c774a4c39359c1d1c52e43f73dd91a75a614652c825408eec30c95a9b2067" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "percent-encoding" @@ -1480,7 +1484,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -1509,18 +1513,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -1586,9 +1590,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.4" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -1598,9 +1602,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.7" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -1609,9 +1613,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" @@ -1685,9 +1689,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.24" +version = "0.37.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4279d76516df406a8bd37e7dff53fd37d1a093f997a3c34a5c21658c126db06d" +checksum = "84f3f8f960ed3b5a59055428714943298bf3fa2d4a1d53135084e0544829d995" dependencies = [ "bitflags 1.3.2", "errno", @@ -1699,11 +1703,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.8" +version = "0.38.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" +checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys 0.4.10", @@ -1768,35 +1772,35 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" [[package]] name = "serde" -version = "1.0.181" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d3e73c93c3240c0bda063c239298e633114c69a888c3e37ca8bb33f343e9890" +checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.181" +version = "1.0.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be02f6cb0cd3a5ec20bbcfbcbd749f57daddb1a0882dc2e46a6c236c90b977ed" +checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.38", ] [[package]] name = "serde_json" -version = "1.0.104" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -1811,7 +1815,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.38", ] [[package]] @@ -1846,16 +1850,6 @@ dependencies = [ "digest", ] -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -1867,24 +1861,24 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -1892,9 +1886,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys", @@ -1925,9 +1919,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.28" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -1957,9 +1951,9 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.1.1" +version = "6.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3" +checksum = "94af52f9402f94aac4948a2518b43359be8d9ce6cd9efc1c4de3b2f7b7e897d6" dependencies = [ "cfg-expr", "heck", @@ -1970,9 +1964,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.11" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tempfile" @@ -1983,28 +1977,28 @@ dependencies = [ "cfg-if", "fastrand 2.0.1", "redox_syscall 0.3.5", - "rustix 0.38.8", + "rustix 0.38.20", "windows-sys", ] [[package]] name = "thiserror" -version = "1.0.44" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.44" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.38", ] [[package]] @@ -2034,7 +2028,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.4", + "socket2 0.5.5", "windows-sys", ] @@ -2064,14 +2058,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.20.2", ] [[package]] @@ -2085,11 +2079,22 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.0.2", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap 2.0.2", "serde", "serde_spanned", "toml_datetime", @@ -2104,11 +2109,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2116,20 +2120,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.38", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] @@ -2164,9 +2168,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -2197,9 +2201,9 @@ dependencies = [ [[package]] name = "value-bag" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3" +checksum = "4a72e1902dde2bd6441347de2b70b7f5d59bf157c6c62f0c44572607a1d55bbe" [[package]] name = "version-compare" @@ -2221,9 +2225,9 @@ checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -2265,7 +2269,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.38", "wasm-bindgen-shared", ] @@ -2299,7 +2303,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.28", + "syn 2.0.38", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2344,9 +2348,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -2368,9 +2372,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -2383,51 +2387,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.3" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46aab759304e4d7b2075a9aecba26228bb073ee8c50db796b2c72c676b5d807" +checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" dependencies = [ "memchr", ] @@ -2486,7 +2490,7 @@ dependencies = [ "byteorder", "derivative", "enumflags2", - "event-listener", + "event-listener 2.5.3", "futures-core", "futures-sink", "futures-util", diff --git a/book/listings/Cargo.toml b/book/listings/Cargo.toml index ac10b9292927..5ecab635a664 100644 --- a/book/listings/Cargo.toml +++ b/book/listings/Cargo.toml @@ -221,6 +221,9 @@ path = "main_event_loop/7/main.rs" name = "main_event_loop_8" path = "main_event_loop/8/main.rs" +[[bin]] +name = "main_event_loop_9" +path = "main_event_loop/9/main.rs" # saving_window_state [[bin]] diff --git a/book/listings/main_event_loop/8/main.rs b/book/listings/main_event_loop/8/main.rs index 99287d88cee0..192f83ed85e2 100644 --- a/book/listings/main_event_loop/8/main.rs +++ b/book/listings/main_event_loop/8/main.rs @@ -2,13 +2,8 @@ use glib::{clone, MainContext, Priority}; use gtk::glib; use gtk::prelude::*; use gtk::{Application, ApplicationWindow, Button}; -use once_cell::sync::Lazy; -use tokio::runtime::Runtime; -// ANCHOR: tokio_runtime const APP_ID: &str = "org.gtk_rs.MainEventLoop8"; -static RUNTIME: Lazy = - Lazy::new(|| Runtime::new().expect("Setting up tokio runtime needs to succeed.")); fn main() -> glib::ExitCode { // Create a new application @@ -20,7 +15,6 @@ fn main() -> glib::ExitCode { // Run the application app.run() } -// ANCHOR_END: tokio_runtime fn build_ui(app: &Application) { // Create a button @@ -36,7 +30,9 @@ fn build_ui(app: &Application) { let (sender, receiver) = MainContext::channel(Priority::default()); // Connect to "clicked" signal of `button` button.connect_clicked(move |_| { - RUNTIME.spawn(clone!(@strong sender => async move { + let main_context = MainContext::default(); + // The main loop executes the asynchronous block + main_context.spawn_local(clone!(@strong sender => async move { let response = reqwest::get("https://www.gtk-rs.org").await; sender .send(response) @@ -49,7 +45,7 @@ fn build_ui(app: &Application) { if let Ok(response) = response { println!("Status {}", response.status()); } else { - println!("Couldn't make a `GET` request."); + println!("Could not make a `GET` request."); } glib::ControlFlow::Continue }); diff --git a/book/listings/main_event_loop/9/main.rs b/book/listings/main_event_loop/9/main.rs new file mode 100644 index 000000000000..ff5b25911b0a --- /dev/null +++ b/book/listings/main_event_loop/9/main.rs @@ -0,0 +1,67 @@ +use glib::{clone, MainContext, Priority}; +use gtk::glib; +use gtk::prelude::*; +use gtk::{Application, ApplicationWindow, Button}; +use once_cell::sync::Lazy; +use tokio::runtime::Runtime; + +// ANCHOR: tokio_runtime +const APP_ID: &str = "org.gtk_rs.MainEventLoop9"; +static RUNTIME: Lazy = + Lazy::new(|| 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(); + + // Connect to "activate" signal of `app` + app.connect_activate(build_ui); + + // Run the application + app.run() +} +// ANCHOR_END: tokio_runtime + +fn build_ui(app: &Application) { + // Create a button + let button = Button::builder() + .label("Press me!") + .margin_top(12) + .margin_bottom(12) + .margin_start(12) + .margin_end(12) + .build(); + + // ANCHOR: callback + let (sender, receiver) = MainContext::channel(Priority::default()); + // Connect to "clicked" signal of `button` + button.connect_clicked(move |_| { + RUNTIME.spawn(clone!(@strong sender => async move { + let response = reqwest::get("https://www.gtk-rs.org").await; + sender + .send(response) + .expect("Could not send through channel"); + })); + }); + + // The main loop executes the closure as soon as it receives the message + receiver.attach(None, move |response| { + if let Ok(response) = response { + println!("Status {}", response.status()); + } else { + println!("Could not make a `GET` request."); + } + glib::ControlFlow::Continue + }); + // ANCHOR_END: callback + + // Create a window + let window = ApplicationWindow::builder() + .application(app) + .title("My GTK App") + .child(&button) + .build(); + + // Present window + window.present(); +} diff --git a/book/src/main_event_loop.md b/book/src/main_event_loop.md index 3dc67560da29..0da2aa123a9e 100644 --- a/book/src/main_event_loop.md +++ b/book/src/main_event_loop.md @@ -221,20 +221,30 @@ If you decide to share it, you user name will be printed on the console. ``` -cargo add tokio@1 --features rt-multi-thread cargo add reqwest@0.11 --features rustls-tls --no-default-features ``` Filename: listings/main_event_loop/8/main.rs ```rust -{{#rustdoc_include ../listings/main_event_loop/8/main.rs:tokio_runtime}} +{{#rustdoc_include ../listings/main_event_loop/8/main.rs:callback}} +``` + +``` +cargo add tokio@1 --features rt-multi-thread ``` -Filename: listings/main_event_loop/8/main.rs + +Filename: listings/main_event_loop/9/main.rs ```rust -{{#rustdoc_include ../listings/main_event_loop/8/main.rs:callback}} +{{#rustdoc_include ../listings/main_event_loop/9/main.rs:tokio_runtime}} +``` + +Filename: listings/main_event_loop/9/main.rs + +```rust +{{#rustdoc_include ../listings/main_event_loop/9/main.rs:callback}} ``` From 7c792e86b73c820ef360ef22e5c5b4ebc4e7c0b5 Mon Sep 17 00:00:00 2001 From: Julian Hofer Date: Sun, 22 Oct 2023 13:20:46 +0200 Subject: [PATCH 09/16] book: Start with conclusion --- book/src/main_event_loop.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/book/src/main_event_loop.md b/book/src/main_event_loop.md index 0da2aa123a9e..00f466b03c89 100644 --- a/book/src/main_event_loop.md +++ b/book/src/main_event_loop.md @@ -249,5 +249,11 @@ Filename: async move { let response = reqwest::get("https://www.gtk-rs.org").await; - sender - .send(response) - .expect("Could not send through channel"); + sender.send(response).await.expect("The channel needs to be open."); })); }); - // The main loop executes the closure as soon as it receives the message - receiver.attach(None, move |response| { - if let Ok(response) = response { - println!("Status {}", response.status()); - } else { - println!("Could not make a `GET` request."); + let main_context = MainContext::default(); + // The main loop executes the asynchronous block + main_context.spawn_local(clone!(@weak button => async move { + while let Ok(response) = receiver.recv().await { + if let Ok(response) = response { + println!("Status {}", response.status()); + } else { + println!("Could not make a `GET` request."); + } } - glib::ControlFlow::Continue - }); + })); // ANCHOR_END: callback // Create a window diff --git a/book/listings/main_event_loop/9/main.rs b/book/listings/main_event_loop/9/main.rs index ff5b25911b0a..79f28cf055b6 100644 --- a/book/listings/main_event_loop/9/main.rs +++ b/book/listings/main_event_loop/9/main.rs @@ -1,4 +1,4 @@ -use glib::{clone, MainContext, Priority}; +use glib::{clone, MainContext}; use gtk::glib; use gtk::prelude::*; use gtk::{Application, ApplicationWindow, Button}; @@ -33,26 +33,26 @@ fn build_ui(app: &Application) { .build(); // ANCHOR: callback - let (sender, receiver) = MainContext::channel(Priority::default()); + let (sender, receiver) = async_channel::bounded(1); // Connect to "clicked" signal of `button` button.connect_clicked(move |_| { RUNTIME.spawn(clone!(@strong sender => async move { let response = reqwest::get("https://www.gtk-rs.org").await; - sender - .send(response) - .expect("Could not send through channel"); + sender.send(response).await.expect("The channel needs to be open."); })); }); - // The main loop executes the closure as soon as it receives the message - receiver.attach(None, move |response| { - if let Ok(response) = response { - println!("Status {}", response.status()); - } else { - println!("Could not make a `GET` request."); + let main_context = MainContext::default(); + // The main loop executes the asynchronous block + main_context.spawn_local(clone!(@weak button => async move { + while let Ok(response) = receiver.recv().await { + if let Ok(response) = response { + println!("Status {}", response.status()); + } else { + println!("Could not make a `GET` request."); + } } - glib::ControlFlow::Continue - }); + })); // ANCHOR_END: callback // Create a window From 31e44f3e7199c2d0adac9dee758ed1bfe9639a62 Mon Sep 17 00:00:00 2001 From: Julian Hofer Date: Sun, 22 Oct 2023 15:57:37 +0200 Subject: [PATCH 11/16] book: Add section about tokio --- book/listings/main_event_loop/8/main.rs | 2 +- book/listings/main_event_loop/9/main.rs | 2 +- book/src/main_event_loop.md | 71 +++++++++++++++++++++---- 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/book/listings/main_event_loop/8/main.rs b/book/listings/main_event_loop/8/main.rs index eb00996eb0ee..1a42beb78c4c 100644 --- a/book/listings/main_event_loop/8/main.rs +++ b/book/listings/main_event_loop/8/main.rs @@ -43,7 +43,7 @@ fn build_ui(app: &Application) { main_context.spawn_local(clone!(@weak button => async move { while let Ok(response) = receiver.recv().await { if let Ok(response) = response { - println!("Status {}", response.status()); + println!("Status: {}", response.status()); } else { println!("Could not make a `GET` request."); } diff --git a/book/listings/main_event_loop/9/main.rs b/book/listings/main_event_loop/9/main.rs index 79f28cf055b6..291f48aeffa2 100644 --- a/book/listings/main_event_loop/9/main.rs +++ b/book/listings/main_event_loop/9/main.rs @@ -47,7 +47,7 @@ fn build_ui(app: &Application) { main_context.spawn_local(clone!(@weak button => async move { while let Ok(response) = receiver.recv().await { if let Ok(response) = response { - println!("Status {}", response.status()); + println!("Status: {}", response.status()); } else { println!("Could not make a `GET` request."); } diff --git a/book/src/main_event_loop.md b/book/src/main_event_loop.md index 00f466b03c89..e8a108f29b33 100644 --- a/book/src/main_event_loop.md +++ b/book/src/main_event_loop.md @@ -65,7 +65,7 @@ However, we don't want to block the main loop while waiting for a message to rec That is the whole point of the exercise after all! We solve that problem by waiting for messages to receive in an [`async`](https://rust-lang.github.io/async-book/) block. -We spawn that `async` block on the glib main loop with [`spawn_local`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn_local) (from other threads than the main thread [`spawn`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn) has to be used). +We spawn that `async` block on the `glib` main loop with [`spawn_local`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn_local) (from other threads than the main thread [`spawn`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn) has to be used). Filename: listings/main_event_loop/3/main.rs @@ -176,9 +176,9 @@ help: within `gtk4::Button`, the trait `Sync` is not implemented for `NonNullDialog requesting user information. +## Tokio + +[`tokio`](https://docs.rs/tokio/latest/tokio/) is Rust's most popular asynchronous platform. +Therefore, many high-quality crates are part of its ecosystem. +The web client [`reqwest`](https://docs.rs/reqwest/latest/reqwest/) belongs to this group. +Let's add it by executing the following command ``` cargo add reqwest@0.11 --features rustls-tls --no-default-features ``` +As soon as the button is pressed, we want to send a `GET` request to [www.gtk-rs.org](https://www.gtk-rs.org). +The response should then be sent to the main thread via a channel. + Filename: listings/main_event_loop/8/main.rs ```rust {{#rustdoc_include ../listings/main_event_loop/8/main.rs:callback}} ``` +This compiles fine and even seems to run. +However, nothing happens when we press the button. +Inspecting the console gives the following error message: + +``` +thread 'main' panicked at +'there is no reactor running, must be called from the context of a Tokio 1.x runtime' +``` + +At the time of writing, `reqwest` doesn't document this requirement. +Unfortunately, that is also the case for other libraries depending on `tokio`. +Let's bite the bullet and add `tokio`: + ``` cargo add tokio@1 --features rt-multi-thread ``` +Since we already run the `glib` main loop on our main thread, we don't want to run the `tokio` runtime there. +Let's bind it to a static variable and initialize it lazily. Filename: listings/main_event_loop/9/main.rs @@ -241,19 +265,44 @@ Filename: listings/main_event_loop/9/main.rs ```rust {{#rustdoc_include ../listings/main_event_loop/9/main.rs:callback}} ``` +If we now press the button, we should find the following message in our console: + +``` +Status: 200 OK +``` + +We will not need `tokio` or `reqwest` in the following chapters, so let's remove it again by executing: + +``` +cargo remove reqwest tokio +``` + +How to find out whether you can spawn an `async` task on the `glib` main loop? +You should be able to do that when the called functions come from libraries that either: +- come from the `glib` ecosystem, +- depend on `async-std`/`smol`, or +- have cargo features that let them depend on `async-std`/`smol` instead of `tokio`. + + +## Conclusion -So when should you spawn an `async` block and when should you spawn a thread? +You don't want to block the main thread long enough that it is noticable by the user. +But when should you spawn an `async` task, and when should you spawn a task in a separate thread? +Let's go again through the different scenarios. -# TODO +If you spend your time calculating rather than waiting for a web response, your task is [CPU-bound](https://en.wikipedia.org/wiki/CPU-bound). +That means you have to run your task in a separate thread and send results back via a channel. -- computation bound -> threads + channels -- IO: - - if you have glib/smol/async-std functions -> spawn on main loop (+ maybe channels) - - if tokio lib is better -> spawn on tokio + channels - - if those are not good options -> threads + channels +If your task is [IO bound](https://en.wikipedia.org/wiki/I/O_bound), it depends on the crates at your disposal +Functions from crates using `glib`/`smol`/`async-std` can be spawned on the main loop. +This typically leads to straightforward code, which can often avoid synchronization via channels. +If the best crate for the job relies on `tokio`, you will have to spawn it with the tokio runtime and send the results via channels. From c35484d7a1d9a3d1da136ca6b938649ae5e0c6dd Mon Sep 17 00:00:00 2001 From: Julian Hofer Date: Sun, 22 Oct 2023 18:00:22 +0200 Subject: [PATCH 12/16] book: Add main_event_loop_1 video --- book/src/main_event_loop.md | 16 +++++++++++++++- book/src/vid/main_event_loop_1.webm | Bin 0 -> 407721 bytes 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 book/src/vid/main_event_loop_1.webm diff --git a/book/src/main_event_loop.md b/book/src/main_event_loop.md index e8a108f29b33..63b7dda94150 100644 --- a/book/src/main_event_loop.md +++ b/book/src/main_event_loop.md @@ -26,6 +26,15 @@ We can't even move the window. The `sleep` call is an artificial example, but it is not unusual wanting 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 there. @@ -36,6 +45,10 @@ Filename: listings/main_event_loop/3/main.rs @@ -88,7 +88,7 @@ Filename: @@ -99,7 +99,7 @@ After the task is finished, the button becomes sensitive again. What if the task is asynchronous by nature? -Let's use [`glib::timeout_future_seconds`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/fn.timeout_future_seconds.html) as representation for our task instead of `std::thread::slepp`. +Let's try [`glib::timeout_future_seconds`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/fn.timeout_future_seconds.html) as representation for our task instead of `std::thread::slepp`. It returns a [`std::future::Future`](https://doc.rust-lang.org/std/future/trait.Future.html), which means we can `await` on it within an `async` context. The converted code looks and behaves very similar to the multithreaded code. @@ -190,14 +190,14 @@ help: within `gtk4::Button`, the trait `Sync` is not implemented for `NonNulllistings/main_event_loop/6/main.rs @@ -206,9 +206,11 @@ Filename: @@ -37,7 +37,7 @@ but it is not unusual wanting 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 there. +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 there. Filename: listings/main_event_loop/2/main.rs @@ -74,7 +74,7 @@ cargo add async-channel We want to send a `bool` to inform, whether we want the button to react to clicks or not. Since we send in a separate thread, we can use [`send_blocking`](https://docs.rs/async-channel/latest/async_channel/struct.Sender.html#method.send_blocking). But what about receiving? -Every time we get a message we want to set the sensitivity of the button according to the `bool` we've received. +Every time we get a message, we want to set the sensitivity of the button according to the `bool` we've received. However, we don't want to block the main loop while waiting for a message to receive. That is the whole point of the exercise after all! @@ -99,7 +99,7 @@ After the task is finished, the button becomes sensitive again. What if the task is asynchronous by nature? -Let's try [`glib::timeout_future_seconds`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/fn.timeout_future_seconds.html) as representation for our task instead of `std::thread::slepp`. +Let's try [`glib::timeout_future_seconds`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/fn.timeout_future_seconds.html) as representation for our task instead of `std::thread::sleep`. It returns a [`std::future::Future`](https://doc.rust-lang.org/std/future/trait.Future.html), which means we can `await` on it within an `async` context. The converted code looks and behaves very similar to the multithreaded code. @@ -195,7 +195,7 @@ After reference cycles we found the second disadvantage of GTK GObjects: They ar We've seen in the previous snippets that spawning an `async` block or `async` future on the `glib` main loop can lead to more concise code than running tasks on separate threads. Let's focus on a few more aspects that are interesting to know when running `async` functions with gtk-rs apps. -For one, blocking functions can be embedded within an `async` context. +For a start, blocking functions can be embedded within an `async` context. In the following listing, we want to execute a synchronous function that returns a boolean and takes ten seconds to run. In order to integrate it in our `async` block, we run the function in a separate thread via `spawn_blocking`. We can then get the return value of the function by calling `await` on the return value of `spawn_blocking`. @@ -296,7 +296,7 @@ If we now press the button, we should find the following message in our console: Status: 200 OK ``` -We will not need `tokio`, `reqwest` or `ashpd` in the following chapters, so let's remove it again by executing: +We will not need `tokio`, `reqwest` or `ashpd` in the following chapters, so let's remove them again by executing: ``` cargo remove reqwest tokio ashpd From e65b8ee09f67f2114af2f2cfc756fd0e23da17f3 Mon Sep 17 00:00:00 2001 From: Hofer-Julian <30049909+Hofer-Julian@users.noreply.github.com> Date: Mon, 23 Oct 2023 20:02:08 +0200 Subject: [PATCH 15/16] Apply suggestions from @felinira's code review Co-authored-by: Fina --- book/src/main_event_loop.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/book/src/main_event_loop.md b/book/src/main_event_loop.md index bc874e187b6b..dd964870b882 100644 --- a/book/src/main_event_loop.md +++ b/book/src/main_event_loop.md @@ -64,7 +64,7 @@ This is not necessarily what we want. Typically, we want to keep track of the work in the task. In our case, we don't want the user to spawn additional tasks while an existing one is still running. -In order exchange information with the task we can create a channel with the crate [`async-channel`](https://docs.rs/async-channel/latest/async_channel/index.html). +In order to exchange information with the task we can create a channel with the crate [`async-channel`](https://docs.rs/async-channel/latest/async_channel/index.html). Let's add it by executing the following in the terminal: ``` @@ -79,7 +79,9 @@ However, we don't want to block the main loop while waiting for a message to rec That is the whole point of the exercise after all! We solve that problem by waiting for messages in an [`async`](https://rust-lang.github.io/async-book/) block. -We spawn that `async` block on the `glib` main loop with [`spawn_local`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn_local) (from other threads than the main thread [`spawn`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn) has to be used). +This `async` block is spawned on the `glib` main loop with [`spawn_local`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn_local) + +> See also [`spawn`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn) for spawning async blocks on the main loop from outside the main thread. Filename: listings/main_event_loop/3/main.rs @@ -219,10 +221,10 @@ cargo add ashpd --features gtk4 ``` You need to use a Linux desktop environment in order to run the following example locally. -We are using [`ashpd::desktop::account::UserInformation`](https://docs.rs/ashpd/latest/ashpd/desktop/account/index.html) to access user information. +This example is using [`ashpd::desktop::account::UserInformation`](https://docs.rs/ashpd/latest/ashpd/desktop/account/index.html) to access user information. We are getting a [`gtk::Native`](https://gtk-rs.org/gtk4-rs/stable/latest/docs/gtk4/struct.Native.html) object from our button, create a [`ashpd::WindowIdentifier`](https://docs.rs/ashpd/latest/ashpd/enum.WindowIdentifier.html) and pass it to the user information request. -That way the dialog that will pop up will be modal. -That means that it will be on top of the window and freezes the rest of the application from user input. + +> We need to pass the `WindowIdentifier` to make the dialog modal. This means that it will be on top of the window and freezes the rest of the application from user input. Filename: listings/main_event_loop/7/main.rs @@ -305,7 +307,8 @@ cargo remove reqwest tokio 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, -- depend on `async-std`/`smol`, or +- 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`. @@ -318,7 +321,9 @@ Let's go again through the different scenarios. If the task spends its time calculating rather than waiting for a web response, it is [CPU-bound](https://en.wikipedia.org/wiki/CPU-bound). That means you have to run the task in a separate thread and let it send results back via a channel. -If your task is [IO bound](https://en.wikipedia.org/wiki/I/O_bound), the answer depends on the crates at your disposal. -Functions from crates using `glib`/`smol`/`async-std` can be spawned on the main loop. -This way, you can often avoid synchronization via channels. +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. +- 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. From 80791241090055fee5d5ffd2d4e94556f5774b7f Mon Sep 17 00:00:00 2001 From: Hofer-Julian <30049909+Hofer-Julian@users.noreply.github.com> Date: Fri, 27 Oct 2023 13:12:04 +0200 Subject: [PATCH 16/16] Update book/src/main_event_loop.md Co-authored-by: Fina --- book/src/main_event_loop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/main_event_loop.md b/book/src/main_event_loop.md index dd964870b882..6a5c47dcb20d 100644 --- a/book/src/main_event_loop.md +++ b/book/src/main_event_loop.md @@ -37,7 +37,7 @@ 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 there. +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. Filename: listings/main_event_loop/2/main.rs