#async-executor #no-alloc #executor

no-std miniloop

The simpliest async executor without heap memory allocation

5 releases (3 breaking)

Uses new Rust 2024

0.4.0 Sep 27, 2025
0.3.0 Dec 24, 2024
0.2.1 Dec 2, 2024
0.2.0 Dec 1, 2024
0.1.0 Nov 14, 2024

#1621 in Asynchronous

Download history 21/week @ 2025-12-28 119/week @ 2026-01-04 77/week @ 2026-01-11 223/week @ 2026-01-18 274/week @ 2026-01-25 295/week @ 2026-02-01 195/week @ 2026-02-08 50/week @ 2026-02-15 212/week @ 2026-02-22 177/week @ 2026-03-01 190/week @ 2026-03-08 195/week @ 2026-03-15 148/week @ 2026-03-22 80/week @ 2026-03-29 175/week @ 2026-04-05 183/week @ 2026-04-12

593 downloads per month
Used in sntpc

Apache-2.0

30KB
305 lines

build Crates.io Version

miniloop - simple asynchronous executor

This repository is created as an attempt to clarify some more low-level details about how things work in Rust asynchronous world.

The miniloop executor creates a statically allocated list of tasks.

miniloop in action

Create your tasks on the stack, add them to the executor and enjoy!

use miniloop::executor::Executor;
use miniloop::helpers::yield_me;
use miniloop::task::Task;

fn sleep(s: u64) {
  std::thread::sleep(std::time::Duration::from_secs(s));
}

async fn dummy_func(data: &str) {
  const TICKS: usize = 4;
  let mut counter = 0usize;

  while counter != TICKS {
    sleep(2);
    let now = get_timestamp_sec();
    println!("{now}: {data}");
    yield_me().await;
    counter += 1;
  }
}

fn get_timestamp_sec() -> u64 {
  std::time::SystemTime::now()
          .duration_since(std::time::UNIX_EPOCH)
          .unwrap()
          .as_secs()
}

fn pending_print(task_name: &str) {
  let now = get_timestamp_sec();
  println!("{now}: Task {task_name} is pending. Waiting for the next tick...");
}

fn main() {
    const TASK_ARRAY_SIZE: usize = 4;
    let mut executor = Executor::<TASK_ARRAY_SIZE>::new();
    executor.set_pending_callback(pending_print);

    let mut task1 = Task::new("hello", async {
        dummy_func("hello").await;
    });
    let mut handle1 = task1.create_handle();
    let mut task2 = Task::new("world", async {
        dummy_func("world").await;
    });
    let mut handle2 = task2.create_handle();

    let _ = executor.spawn(&mut task1, &mut handle1);
    let _ = executor.spawn(&mut task2, &mut handle2);

    executor.run();
    println!("Done!");
    assert!(handle1.value.is_some());
    assert!(handle2.value.is_some());
}

License

This project is licensed under Apache License, Version 2.0
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in time by you, as defined in the Apache-2.0 license, shall be licensed as above, without any additional terms or conditions.

No runtime deps