fiber.h

Fibers 是轻量级的、协作式的执行线程。 fiber.h 头文件定义了用于在 Emscripten 中操作 Fibers 的底层 API。Fibers 是使用 异步代码 实现的,因此如果要使用它们,必须将程序与 ASYNCIFY 链接。

Fibers 旨在作为异步控制流构造(如协程)的构建块。它们取代了 fastcomp 后端中提供的传统协程 API。此 API 与 POSIX ucontext 类似,但不同。

API 参考

类型

emscripten_fiber_t

此结构代表一个 Fiber 上下文 continuation。运行时不会保留对这些对象的引用,它们只包含执行上下文切换所需的信息。切换操作会更新其中的一些内容,但是。

void *stack_base

C 栈区域的上限。栈向下增长,因此这是栈指针的初始位置。必须至少 16 字节对齐。

void *stack_limit

C 栈区域的下限。必须低于 emscripten_fiber_t.stack_base

void *stack_ptr

栈指针的当前位置。必须介于 emscripten_fiber_t.stack_baseemscripten_fiber_t.stack_limit 之间。

em_arg_callback_func entry

入口点。如果非空,则在切换到该 fiber 时会调用此函数。否则,emscripten_fiber_t.asyncify_data 用于回溯调用栈。

void *user_data

不透明指针,按原样传递给 emscripten_fiber_t.entry

asyncify_data_t asyncify_data

Asyncify 数据结构。用于在切换 fibers 时回溯和重绕调用栈。

asyncify_data_t
void *stack_ptr

Asyncify 栈指针的当前位置。

Asyncify 栈不同于 C 栈。它包含调用栈以及 WASM 局部变量的状态。与 C 栈不同,它向上增长。

void *stack_limit

Asyncify 栈区域的上限。

int rewind_id

用于重绕调用栈的函数的不透明句柄。此值仅对运行时有意义。

警告

重绕 ID 目前是线程特定的。这使得无法恢复从不同线程启动的 fiber。

函数

void emscripten_fiber_init(emscripten_fiber_t *fiber, em_arg_callback_func entry_func, void *entry_func_arg, void *c_stack, size_t c_stack_size, void *asyncify_stack, size_t asyncify_stack_size)

初始化一个 fiber 上下文。然后可以通过调用 emscripten_fiber_swap() 来进入它。

参数
  • fiber (emscripten_fiber_t*) – 指向 fiber 结构的指针。

  • entry_func (em_arg_callback_func) – 入口点函数,在第一次进入 fiber 时调用。

  • entry_func_arg (void*) – 传递给 entry_func 的不透明指针。

  • c_stack (void*) – 指向要用于 C 栈的内存区域的指针。必须至少 16 字节对齐。无论增长方向如何,这都指向栈的下界。

  • c_stack_size (size_t) – C 栈内存区域的大小(以字节为单位)。

  • asyncify_stack (void*) – 指向要用于 Asyncify 栈的内存区域的指针。没有特殊对齐要求。

  • asyncify_stack_size (size_t) – Asyncify 栈内存区域的大小(以字节为单位)。

注意

如果 entry_func 返回,则整个程序将结束,就像 main 返回一样。为了避免这种情况,可以使用 emscripten_fiber_swap() 跳转到另一个 fiber。

void emscripten_fiber_init_from_current_context(emscripten_fiber_t *fiber, void *asyncify_stack, size_t asyncify_stack_size)

基于当前活动上下文部分初始化一个 fiber。这对于从 fiber 切换回线程的原始上下文是必需的。

此函数将 emscripten_fiber_t.stack_baseemscripten_fiber_t.stack_limit 设置为引用当前栈边界,将 emscripten_fiber_t.entry 设置为 NULL,并将 emscripten_fiber_t.asyncify_data 设置为引用提供的 Asyncify 栈内存。其他字段不会更改。

通过此函数初始化的 Fibers 不完整。它们仅适合作为 emscripten_fiber_swap() 的第一个参数传递。执行此操作将完成 continuation,使其能够通过另一个 emscripten_fiber_swap() 切换回原始上下文,就像使用普通 fiber 一样。

参数
  • fiber (emscripten_fiber_t*) – 指向 fiber 结构的指针。

  • asyncify_stack (void*) – 指向要用于 Asyncify 栈的内存区域的指针。没有特殊对齐要求。

  • asyncify_stack_size (size_t) – Asyncify 栈内存区域的大小(以字节为单位)。

void emscripten_fiber_swap(emscripten_fiber_t *old_fiber, emscripten_fiber_t *new_fiber)

执行一个 fiber 上下文切换。

参数
  • old_fiber (emscripten_fiber_t*) – 代表当前上下文的 Fiber。它将被部分更新,例如,通过对 emscripten_fiber_swap() 的另一个调用切换回它,将看起来是从原始调用返回。

  • new_fiber (emscripten_fiber_t*) – 表示目标上下文的纤程。如果纤程具有入口点,它将在新上下文中调用并设置为 NULL。否则,emscripten_fiber_t.asyncify_data 用于回溯调用堆栈。如果纤程无效或不完整,则行为未定义。