Crate gidle_future[−][src]
An executor to run futures in the idle cycles of a Glib/Gtk application.
This crate provides a function that programs a future to be run using the
idle time of the main loop, as provided by glib::idle_add
.
It works by registering an idle function to poll the future once, and whenever the future is awoken, it will register another idle function to be continued, and so on.
The main advantage of this approach is that the future is run in the main loop.
As such, it does not need to be Send
, it does not require any kind of synchronization
to access shared state, and it can even manipulate GUI objects directly.
Naturally, you still need to be careful, because if you set up several idle futures at the same time they will be run intermixed.
What can it be used for?
You can use this crate to implement async I/O that handles the GUI without the need of synchronization. For example you can download assets or updates from the internet, or provide an API for automating your GUI.
You can also use async functions to implement background tasks that run when the program is idle. They can be interrupted at any time and they can update the GUI directly. A similar technique can be used to easily build a progress bar for a long-running process. Just add something like this call here and there:
async_std::task::yield_now().await;
Working with other async frameworks
You can run almost any future as an idle future, but if it uses functionality from any async
framework (async_std
, smol
, tokio
…) it will most likely need to be initialized first,
or else your futures will not advance. This is because these frameworks usually work by creating
a background thread that does the actual polling and wakes up the other futures. If this
background thread is not created, nothing will be polled and your futures will stall forever.
You may think that interacting with other fraworks is going to be difficult. But actually it is super easy, barely an inconvenience:
async_std
Spawning any async task will bootstrap the runtime, so just this from your main
is enough:
async_std::task::spawn(async {});
smol
There must be at least one thread runing an async job, and it will do that and poll all the futures. So the code would be something like this, that will spawn a never-ending future:
std::thread::spawn(|| smol::run(futures::future::pending::<()>()));
If you also use async_std
, since it uses smol
under the hood, you just need one of these.
tokio
In tokio
futures need to be spawn from a tokio reactor. It is enough if you run your main loop from there:
let mut rt = tokio::runtime::Builder::new() .threaded_scheduler() .enable_all() .build() .unwrap(); rt.block_on(async { gtk::main() });
Or you can decorate your main
function with:
#[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { //... }
Structs
Handle | A handle to a running idle future. |
Functions
spawn | Spawns an idle future. |