[][src]Struct gtk_future_executor::GtkEventLoopAsyncExecutor

pub struct GtkEventLoopAsyncExecutor { /* fields omitted */ }

An executor that executes futures on Gtk+ main loop. This allows executing asynchronous code that manipulates Gtk+ widgets.

Usage:

  1. Create with GtkEventLoopAsyncExecutor::new()
  2. Clone as necessary (all clones refer to the same executor)
  3. Use GtkEventLoopAsyncExecutor::spawn() to launch new async GUI code

GtkEventLoopAsyncExecutor ensures memory- and thread-safety by being not shareable or sendable between threads. This is a requirement for GUI code.

Example:

use futures::prelude::*;
use futures::future;
use futures_cpupool::CpuPool;
 
use gtk_future_executor::GtkEventLoopAsyncExecutor;
use gtk_future_executor::Promise;
use gtk::prelude::*;
 
// An examples that computes Fibonacci numbers in background
 
fn main() -> Result<(), String> {
 
    gtk::init().map_err(|_| "Failed to initialize Gtk+".to_string())?;
 
    // Constuct new executor
    let gtk_executor = GtkEventLoopAsyncExecutor::new();
    // This examples uses CPU pool for invoking long-running computation in background
    let cpu_pool = CpuPool::new_num_cpus();
 
    let fut_main = gui_main(cpu_pool.clone(), gtk_executor.clone())
        .then(|_| {
            // Exit main loop when gui_main() finishes
            gtk::main_quit();
 
            future::ok(())
        });
 
    // This executes the async main function inside Gtk+ event loop
    gtk_executor.spawn(fut_main);
 
    gtk::main();
 
    Result::Ok(())
}
 
// An async function that shows a window. Returned future will resolve when user closes the window.
fn gui_main(cpu_pool: CpuPool, gtk_executor: GtkEventLoopAsyncExecutor) -> impl Future<Item=(), Error=String> {
 
    let promise = Promise::new();
 
    let window = gtk::Window::new(gtk::WindowType::Toplevel);
    let vbox = gtk::Box::new(gtk::Orientation::Vertical, 5);
    let label = gtk::Label::new("Enter n:");
    let result_label = gtk::Label::new("<result>");
    let textbox = gtk::Entry::new();
    let button = gtk::Button::new_with_label("OK");
 
    window.add(&vbox);
    vbox.pack_start(&label, false, true, 0);
    vbox.pack_start(&textbox, false, true, 0);
    vbox.pack_start(&button, false, true, 0);
    vbox.pack_start(&result_label, false, true, 0);
 
    window.set_title("Fib");
    window.set_position(gtk::WindowPosition::Center);
 
    {
        let promise = promise.clone();
        window.connect_delete_event(move |_, _| {
            promise.resolve(());
 
            Inhibit(false)
        });
    }
 
    {
        let cpu_pool = cpu_pool.clone();
        let gtk_executor = gtk_executor.clone();
        let textbox = textbox.clone();
        let result_label = result_label.clone();
        button.connect_clicked(move |_| {
 
            let opt_text = textbox.get_text();
            let text = opt_text.as_ref().map(|s| s.as_str()).unwrap_or("");
            let n: u64 = match text.parse() {
                Ok(x) => x,
                Err(x) => {
                    eprintln!("Error: {}", x);
                    return;
                }
            };
            result_label.set_text("computing...");
            let result_label = result_label.clone();
 
            // With GtkEventLoopAsyncExecutor we can await the long running async computation
            // and continue manipulating GUI widgets on the main thread.
            gtk_executor.spawn(
                // cpu_pool execute `compute_fib` in background thread_pool
                cpu_pool.spawn_fn(move || future::ok(compute_fib(n)))
                    .and_then(move |r| {
                        // this code is executed on main thread
                        result_label.set_text(&format!("fib({}) = {}", n, r));
 
                        future::ok(())
                    })
            );
        });
    }
 
    window.show_all();
 
    promise
}
 
// Fibonacci function. This function will take very long time for large values of `n`.
fn compute_fib(n: u64) -> u64 {
    if n < 2 {
        1
    } else {
        compute_fib(n - 2) + compute_fib(n - 1)
    }
}

Methods

impl GtkEventLoopAsyncExecutor[src]

pub fn new() -> Self[src]

Instantiates new executor. May only be called from Gtk+ main thread. Gtk+ must be initialized. Panics if called before Gtk+ initialization or from non-main thread.

pub fn spawn<F: Future<Item = (), Error = ()> + Sized + 'static>(&self, f: F)[src]

Executes specified future on Gtk+ main thread (using event loop to schedule callbacks)

Trait Implementations

impl Clone for GtkEventLoopAsyncExecutor[src]

fn clone_from(&mut self, source: &Self)1.0.0[src]

Performs copy-assignment from source. Read more

Auto Trait Implementations

Blanket Implementations

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> From<T> for T[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]