futures-shuttle 0.2.1

Futures-aware shuttle synchronization object
Documentation
extern crate futures;
extern crate futures_shuttle;

use std::thread;
use std::time::Duration;

use futures::executor::{block_on, LocalPool};
use futures::future::{loop_fn, Loop};
use futures::{FutureExt, IntoFuture};
use futures_shuttle::shuttle;

#[derive(Debug, PartialEq)]
struct Foo(usize);

#[test]
fn simple_future() {
    let onesec = Duration::new(1, 0);
    let (left, right) = shuttle(Foo(4));
    let left = move || {
        thread::sleep(onesec);
        assert!(left.is_mine());
        assert_eq!(left.data(), Foo(4));
        *left.data() = Foo(5);
        assert_eq!(left.data(), Foo(5));
        left.send();
    };

    thread::spawn(left);

    let future = block_on(right.into_future());

    assert!(future.is_ok());
    let right = future.unwrap();

    assert!(right.is_mine());
    //assert!(!left.is_mine());
    assert_eq!(right.data(), Foo(5));
}

#[test]
fn ping_pong() {
    let (ping, pong) = shuttle(1);

    let ping_loop = loop_fn(ping, |s| {
        s.into_future().and_then(|s| {
            let x = *s.data();
            *s.data() = x * 2;
            match s.try_send() {
                Ok(_) => Ok(Loop::Continue(s)),
                Err(_) => Ok(Loop::Break(s)),
            }
        })
    });

    thread::spawn(move || {
        let mut pool = LocalPool::new();
        let mut exec = pool.executor();
        pool.run_until(ping_loop, &mut exec).unwrap()
    });
    let pong_loop = loop_fn(pong, |s| {
        s.into_future().and_then(|s| {
            let x = *s.data();
            if x > 65_536 {
                Ok(Loop::Break(s))
            } else {
                *s.data() = x * 2;
                s.send();
                Ok(Loop::Continue(s))
            }
        })
    });

    let mut pool = LocalPool::new();
    let mut exec = pool.executor();

    let pong = pool.run_until(pong_loop, &mut exec).unwrap();

    assert_eq!(pong.data(), 131_072);
}