14 个版本

0.3.7 2021 年 5 月 7 日
0.3.6 2021 年 4 月 8 日
0.3.3 2021 年 2 月 4 日
0.3.1 2021 年 1 月 30 日
0.1.1 2020 年 9 月 4 日

#1828Rust 模式

Download history 5/week @ 2024-03-09 5/week @ 2024-03-16 5/week @ 2024-03-30

每月 59 次下载

Apache-2.0/MIT

59KB
848

async-wormhole

文档

这个库是实验性的,我使用它来为 Lunatic 做原型。

目前仅在 Rust nightly 下工作,因为它依赖于 switcheroo

async-wormhole 允许你在非异步函数中进行异步调用,例如 extern "C" 或 JIT 生成的代码。它在 Windows、MacOs 和 Linux(x64 & AArch64)上运行。

动机

有时,当你在一个异步环境中运行时,你需要调用 JIT 生成的代码(例如 wasm)并从那里 .await。因为 JIT 代码在编译时不可用,Rust 编译器无法执行它们“创建状态机”的魔法。最终你无法在非异步函数中有 .await 语句。

这个库创建了一个特殊的堆栈来执行 JIT 代码,因此可以在执行过程中的任何一点挂起它。一旦你在 AsyncWormhole::new 中传递一个闭包,你将得到一个可以 .await 的未来。传递的闭包将在一个新的堆栈上执行。

示例

use async_wormhole::{AsyncWormhole, AsyncYielder};
use switcheroo::stack::*;

// non-async function
#[allow(improper_ctypes_definitions)]
extern "C" fn non_async(mut yielder: AsyncYielder<u32>) -> u32 {
	// Suspend the runtime until async value is ready.
	// Can contain .await calls.
    yielder.async_suspend(async { 42 })
}

fn main() {
    let stack = EightMbStack::new().unwrap();
    let task = AsyncWormhole::<_, _, fn()>::new(stack, |yielder| {
        let result = non_async(yielder);
        assert_eq!(result, 42);
        64
    })
    .unwrap();

    let outside = futures::executor::block_on(task);
    assert_eq!(outside, 64);
}

性能

在传递给 AsyncWormhole::new 并由 async_suspend 捕获的闭包内部的 .await 调用应该几乎没有性能开销。但实例化一个新的 AsyncWormhole 将需要一次内存分配。当然,你不会得到 完美大小的堆栈

许可证

根据以下任一许可证许可:

由您选择。

贡献

除非您明确说明,否则您根据Apache-2.0许可证定义,有意提交以包含在作品中的任何贡献,将按照上述方式双许可,不附加任何其他条款或条件。

依赖项

~210KB