在 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;
}
}
如果我记录这些帧结构的原始字节(据我所知,它们是不透明的并且不支持字段访问?我对 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]
然而,盲目地阅读这些数据似乎有点鲁莽,如果我知道结构布局得到保证或者有一些内置方法可以发现这些信息,我会感觉更舒服。
编辑::
特别是,我要解决的问题是,在设计事件循环时(例如,在 JS 和 Zig/WASM 之间进行接口时),您似乎必须将异步函数的实现与事件循环本身的 API 结合起来.
例如,内置事件循环具有yield()
精确的功能,因此它可以进行必要的簿记以确保代码在每次挂起时有一个恢复,但据我所知,这是一个不必要的限制,因为帧是否返回似乎存储并易于访问。
我肯定有可能误解了 Zig 的 async/await 的目的,但我看不出有任何根本原因为什么能够处理任何异步函数的通用事件循环(不仅仅是那些遵守特定循环 API 的事件循环)不能'没有写,但我很难看到如果没有比文档指示的更多运行时内省,这是如何可能的。