在 Zig 中,如何判断一个帧是否代表一个完全执行的函数?

Han*_*ave 9 zig

在 Zig(当前使用 0.7.1)中,假设由于某种原因您没有任何好的方法来设计resume对于每个suspend. 是否有任何支持的方法可以在运行时检测给定的帧是否已执行完成?

// overly simplistic example designed to illustrate the problem
pub fn main() void {
    var frame = async amain(2);
    resume frame;
    resume frame;

    // panic/UB -- resume async function which already returned
    // 
    // we would prefer to have some kind of check which could allow
    // us to detect at runtime that the following resumption is illegal
    resume frame;
}

fn amain(ubound: i32) void {
    var i: i32 = 0;
    while (i < ubound) : (i += 1) {
        suspend;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我记录这些帧结构的原始字节(据我所知是不透明的并且不支持字段访问?我对 Zig 有点陌生),那么很明显帧的一部分是专用于标记是否已返回:

[70, 3a, 23, 00, 00, 00, 00, 00, 02, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 02, 00, 00, 00, 00, 00, 00, 00]
[70, 3a, 23, 00, 00, 00, 00, 00, 02, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 02, 00, 00, 00, 01, 00, 00, 00]
[70, 3a, 23, 00, 00, 00, 00, 00, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, ff, 02, 00, 00, 00, 02, 00, 00, 00]
Run Code Online (Sandbox Code Playgroud)

然而,盲目地阅读这些数据似乎有点鲁莽,如果我知道结构布局是有保证的,或者有一些内置的方式来发现这些信息,我会感觉更舒服。

编辑::

特别是,我试图解决的问题是,在设计事件循环时(例如在 JS 和 Zig/WASM 之间接口时),您似乎必须将异步函数的实现与事件循环本身的 API 结合起来.

例如,内置事件循环具有一个yield()精确的函数,以便它可以进行必要的簿记以确保代码在每次挂起时都有一个恢复,但据我所知,这是一个不必要的限制,因为帧是否已返回似乎便于存放和取用。

我当然可能误解了 Zig 的 async/await 的目的,但我没有看到任何能够处理任何异步函数(不仅仅是那些遵守特定循环 API 的)的通用事件循环的根本原因t 被写入,但我正在努力了解如果没有比文档表明可用的更多的运行时内省,这是如何可能的。

Han*_*ave 1

截至 2022 年 4 月,有一个用该语言实现此功能的公开提案。在此之前的解决方法可能仍然是手动读取异步帧标头。