在 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 被写入,但我正在努力了解如果没有比文档表明可用的更多的运行时内省,这是如何可能的。