#async-task #async #schedule #future #single-thread #task-scheduler #non-preemptive

no-std juggle

在单线程环境下,支持no_std的协同多任务异步任务切换

2个版本

0.1.1 2020年9月21日
0.1.0 2020年9月13日

#513 in 嵌入式开发

MIT/Apache

120KB
2K SLoC

juggle

Build License Crate Documentation Rust version

在单线程环境中支持no_std的协同多任务异步任务切换。

该库提供工具来动态管理单线程或嵌入式环境中的任务组。注意,这不是一个操作系统,但可以作为不需要上下文切换的简单替代品,例如在嵌入式应用程序中。任务使用Rust的async/await机制,而插入切换点的任务则是程序员的职责。幸运的是,这个crate还提供了Yield实用工具,以及处理忙等待。主调度器(Wheel)可以动态地创建、挂起、恢复或取消由轮询算法管理的任务。

Crate默认使用std库(功能std),但也可以配置为#![no_std],使用alloc crate,这将禁用utils模块中的某些功能。

示例

一个简单的程序,用于从传感器读取数据并处理。

use juggle::*;
use alloc::collections::VecDeque;
use core::cell::RefCell;

async fn collect_temperature(queue: &RefCell<VecDeque<i32>>,handle: WheelHandle<'_>){
    loop{ // loop forever or until cancelled
        let temperature: i32 = read_temperature_sensor().await;
        queue.borrow_mut().push_back(temperature);
        yield_once!(); // give scheduler opportunity to execute other tasks
    }
}

async fn wait_for_timer(id: IdNum,queue: &RefCell<VecDeque<i32>>,handle: WheelHandle<'_>){
    init_timer();
    for _ in 0..5 {
        yield_while!(get_timer_value() < 200); // busy wait but also executes other tasks.
        process_data(&mut queue.borrow_mut());
        reset_timer();
    }
    handle.cancel(id); // cancel 'collect_temperature' task.
    shutdown_timer();
}

fn main(){
    let queue = &RefCell::new(VecDeque::new());
    let wheel = Wheel::new();
    let handle = wheel.handle(); // handle to manage tasks, can be cloned inside this thread

    let temp_id = handle.spawn(SpawnParams::default(),
                               collect_temperature(queue,handle.clone()));
    handle.spawn(SpawnParams::default(),
                 wait_for_timer(temp_id.unwrap(),queue,handle.clone()));

    // execute tasks
    smol::block_on(wheel).unwrap(); // or any other utility to block on future.
}

依赖关系

~73KB