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.