hiasync 0.2.2

Supports only single-threaded asynchronous runtime
Documentation
#![no_std]

extern crate alloc;

pub use alloc::collections::{BTreeMap, BTreeSet};

pub type HashMap<K, V> = BTreeMap<K, V>;
pub type HashSet<T> = BTreeSet<T>;

mod task;
pub(crate) use task::*;

mod join;
pub use join::*;

mod waker;
pub use waker::*;

mod future;
pub use future::*;

mod runtime;
pub use runtime::*;

#[cfg(test)]
mod tests {
    use super::*;

    async fn foo(val: i32) -> i32 {
        sched_yield().await;
        val + 1
    }

    #[test]
    fn test0() {
        let mut rt = Runtime::new();
        let _ = rt.spawn(foo(0));
        let cnt = rt.sched();
        assert_eq!(cnt, 1);
        assert_eq!(rt.pending_count(), 0);
    }

    #[test]
    fn test1() {
        let mut rt = Runtime::new();
        let h1 = rt.spawn(foo(0));
        let h2 = rt.spawn(foo(1));
        let cnt = rt.sched();
        assert_eq!(h1.join(), Some(1));
        assert_eq!(h2.join(), Some(2));
        assert_eq!(cnt, 2);
        assert_eq!(rt.pending_count(), 0);
    }

    async fn bar(val: i32) -> i32 {
        *wait_event::<i32>(val as u64).await.unwrap()
    }

    #[test]
    fn test2() {
        let mut rt = Runtime::new();
        let h = rt.spawn(bar(100));
        let cnt = rt.sched();
        assert_eq!(cnt, 0);
        assert_eq!(h.is_finished(), false);
        assert_eq!(rt.pending_count(), 1);
        let cnt = rt.sched_events(&[Event::new(100, &200)]);
        assert_eq!(cnt, 1);
        assert_eq!(h.join(), Some(200));
        assert_eq!(rt.pending_count(), 0);
    }

    #[test]
    fn test3() {
        let mut rt = Runtime::new();
        let h = rt.spawn(bar(100));
        let cnt = rt.sched();
        assert_eq!(cnt, 0);
        assert_eq!(h.is_finished(), false);
        assert_eq!(rt.pending_count(), 1);
        rt.notify_events(&[Event::new(100, &300)]);
        let cnt = rt.sched();
        assert_eq!(cnt, 1);
        assert_eq!(h.join(), Some(300));
        assert_eq!(rt.pending_count(), 0);
    }

    async fn boo(val: i32) -> i32 {
        spawn(foo(val)).await.await.unwrap()
    }

    #[test]
    fn test4() {
        let mut rt = Runtime::new();
        let h = rt.spawn(boo(99));
        let cnt = rt.sched();
        assert_eq!(rt.pending_count(), 0);
        assert_eq!(cnt, 2);
        assert!(h.is_finished());
        assert_eq!(h.join(), Some(100));
    }

    #[test]
    fn test5() {
        let mut rt = Runtime::new();
        let h = rt.spawn(foo(1).and(foo(2)));
        let cnt = rt.sched();
        assert_eq!(rt.pending_count(), 0);
        assert_eq!(cnt, 1);
        assert!(h.is_finished());
        assert_eq!(h.join(), Some((2, 3)));
    }
    #[test]
    fn test6() {
        let mut rt = Runtime::new();
        let h = rt.spawn(foo(1).or(foo(2)));
        let cnt = rt.sched();
        assert_eq!(rt.pending_count(), 0);
        assert_eq!(cnt, 1);
        assert!(h.is_finished());
        assert_eq!(h.join(), Some((Some(2), None)));
    }
    #[test]
    fn test7() {
        let mut rt = Runtime::new();
        let h = rt.spawn(foo(1).partial_or(foo(2)));
        let cnt = rt.sched();
        assert_eq!(rt.pending_count(), 0);
        assert_eq!(cnt, 1);
        assert!(h.is_finished());
        assert_eq!(h.join(), Some((2, Some(3))));
    }
    #[test]
    fn test8() {
        let mut rt = Runtime::new();
        let h = rt.spawn(foo(1).partial_or(foo(2)));
        h.abort();
        let cnt = rt.sched();
        assert_eq!(rt.pending_count(), 0);
        assert_eq!(cnt, 0);
    }

    #[test]
    fn test9() {
        let mut rt = Runtime::new();
        let h = rt.spawn(bar(10));
        let cnt = rt.sched();
        assert_eq!(rt.pending_count(), 1);
        assert_eq!(cnt, 0);
        rt.notify_events(&[Event::new(10, &1)]);
        h.abort();
        let cnt = rt.sched();
        assert_eq!(rt.pending_count(), 0);
        assert_eq!(cnt, 1);
    }

    async fn join_set_wait_all(data: i32) {
        let mut joinset = JoinSet::<i32>::new().await;
        let id1 = joinset.spawn(foo(0));
        let id2 = joinset.spawn(boo(1));
        let id3 = joinset.spawn(bar(1));
        for (task, val) in joinset.wait_all().await {
            if task == id1 {
                assert_eq!(val, Some(1));
            } else if task == id2 {
                assert_eq!(val, Some(2));
            } else if task == id3 {
                assert_eq!(val, Some(data));
            } else {
                assert!(false);
            }
        }
    }

    #[test]
    fn test10() {
        let mut rt = Runtime::new();
        let _ = rt.spawn(join_set_wait_all(100));
        let cnt = rt.sched();
        // foo, bar, foo
        assert_eq!(cnt, 3);
        assert_eq!(rt.pending_count(), 2);
        rt.notify_events(&[Event::new(1, &100)]);
        let cnt = rt.sched();
        assert_eq!(cnt, 2);
        assert_eq!(rt.pending_count(), 0);
    }

    async fn join_set_wait_any(data: i32) {
        let mut joinset = JoinSet::<i32>::new().await;
        let id1 = joinset.spawn(foo(0));
        let id2 = joinset.spawn(boo(1));
        let id3 = joinset.spawn(bar(1));
        while let Some((task, val)) = joinset.wait_any().await {
            if task == id1 {
                assert_eq!(val, Some(1));
            } else if task == id2 {
                assert_eq!(val, Some(2));
            } else if task == id3 {
                assert_eq!(val, Some(data));
            } else {
                assert!(false);
            }
        }
    }

    #[test]
    fn test11() {
        let mut rt = Runtime::new();
        let _ = rt.spawn(join_set_wait_any(100));
        let cnt = rt.sched();
        // foo, bar, foo
        assert_eq!(cnt, 3);
        assert_eq!(rt.pending_count(), 2);
        rt.notify_events(&[Event::new(1, &100)]);
        let cnt = rt.sched();
        assert_eq!(cnt, 2);
        assert_eq!(rt.pending_count(), 0);
    }

    use core::cell::Cell;
    use alloc::rc::Rc;

    async fn suspend(id: Rc<Cell<u64>>) -> i32 {
        id.set(task_self().await);
        task_suspend().await;
        100
    }

    #[test]
    fn test12() {
        let mut rt = Runtime::new();
        let task_id = Rc::new(Cell::new(0_u64));
        let h = rt.spawn(suspend(task_id.clone()));

        let cnt = rt.sched();
        assert_eq!(cnt, 0);
        assert_eq!(rt.pending_count(), 1);

        rt.task_resume(task_id.get());
        let cnt = rt.sched();
        assert_eq!(cnt, 1);
        assert_eq!(rt.pending_count(), 0);
        assert_eq!(h.join(), Some(100));

    }

    async fn foo_suspend(val: i32) -> i32 {
        task_suspend().await;
        val
    }

    #[test]
    fn test13() {
        let mut rt = Runtime::new();
        let h = rt.spawn(foo_suspend(100));
        let cnt = rt.sched();
        assert_eq!(cnt, 0);
        assert_eq!(rt.pending_count(), 1);

        rt.task_force_abort(h.task_id());
        let cnt = rt.sched();
        assert_eq!(cnt, 0);
        assert_eq!(rt.pending_count(), 0);
        assert_eq!(h.is_finished(), true);
        assert_eq!(h.is_aborted(), true);
        assert_eq!(h.join(), None);
    }

    #[test]
    fn test14() {
        let mut rt = Runtime::new();
        let h = rt.spawn(foo_suspend(100));
        let cnt = rt.sched();
        assert_eq!(cnt, 0);
        assert_eq!(rt.pending_count(), 1);

        async fn abort(task_id: u64) {
            task_force_abort(task_id).await;
        }
        rt.spawn(abort(h.task_id()));
        let cnt = rt.sched();
        assert_eq!(cnt, 1);
        assert_eq!(rt.pending_count(), 0);
        assert_eq!(h.is_finished(), true);
        assert_eq!(h.is_aborted(), true);
        assert_eq!(h.join(), None);
    }

    async fn foo_join(val: i32, cnt: usize) -> i32{
        let mut joinset = JoinSet::new().await;
        for _ in 0..cnt {
            let _ = joinset.spawn(foo_suspend(val));
        }
        let mut cnt = 0;
        for (_, rlt) in joinset.wait_all().await {
            cnt += rlt.unwrap_or(0);
        }
        cnt
    }

    #[test]
    fn test15() {
        let mut rt = Runtime::new();
        let h = rt.spawn(foo_join(100, 2));
        let cnt = rt.sched();
        assert_eq!(cnt, 0);
        assert_eq!(rt.pending_count(), 3);
        async fn force_stop(id: u64) {
            task_force_abort(id).await;
        }
        let _ = rt.spawn(force_stop(h.task_id()));
        let cnt = rt.sched();
        assert_eq!(cnt, 1);
        assert_eq!(rt.pending_count(), 0);
    }
}