proxying.h

Emscripten proxying.h API 提供了一种机制,用于调度要由目标线程执行的工作,并可以选择性地阻塞,直到该工作完成。这在 Web 上下文中特别有用,在该上下文中,某些 JS API 只能在特定线程上调用;任何线程都可以通过将 API 调用代理到正确的线程来访问这些 API。代理对于用同步接口包装异步 JS 任务也很有用。调用线程可以将异步任务代理到专用的工作线程,并在工作线程最终将任务标记为完成之前等待,这可能在多次返回 JS 事件循环后。

在目标线程上,排队的作业可以通过两种方式执行。首先,用户可以显式调用 emscripten_proxy_execute_queue 来执行为当前线程排队的任何任务。或者,如果目标线程返回 JS 事件循环(例如通过 emscripten_exit_with_live_runtime),排队的作业将自动执行。

请参阅 test_pthread_proxying.ctest_pthread_proxying_cpp.cpp 以了解如何使用代理 API 的示例。

API 参考

类型

em_proxying_queue

一组线程局部工作队列(每个线程一个)的不透明句柄,可以从其他线程异步或同步地代理工作到这些队列。

代理工作只能在活动的线程运行时完成,因此用户必须确保在线程退出之前所有代理工作都已完成,或者线程退出时使用活动运行时,例如通过 emscripten_exit_with_live_runtime,以避免丢失工作。

em_proxying_ctx

当前正在执行的代理任务的不透明句柄,用于发出任务结束的信号。

函数

em_proxying_queue* em_proxying_queue_create()

分配一个新的代理队列。

void em_proxying_queue_destroy(em_proxying_queue* q)

释放一个代理队列。队列不应有任何剩余的排队作业。

em_proxying_queue* emscripten_proxy_get_system_queue()

获取用于代理低级运行时工作的队列。此队列上的工作可以在系统函数内部随时处理,因此它必须是非阻塞的,并且可以随时安全运行,类似于本机信号处理程序。用户代码通常不应使用此函数。

void emscripten_proxy_execute_queue(em_proxying_queue* q)

在给定队列上执行为当前线程排队的全部任务。与执行同时排队的全新任务也会被执行。该函数返回,此时它观测到一个空队列。

void emscripten_proxy_finish(em_proxying_ctx* ctx)

发出使用 emscripten_proxy_sync_with_ctx 代理的任务结束的信号。

int emscripten_proxy_async(em_proxying_queue* q, pthread_t target_thread, void (*func)(void*), void* arg)

在给定队列和线程上排队 func 以使用参数 arg 调用,然后立即返回,而不等待执行 func。如果工作成功排队,则返回 1,否则返回 0。

int emscripten_proxy_sync(em_proxying_queue* q, pthread_t target_thread, void (*func)(void*), void* arg)

在给定队列和线程上排队 func 以使用参数 arg 调用,然后在返回之前同步等待执行 func。如果 func 成功完成,则返回 1,否则返回 0,包括如果目标线程在工作完成之前被取消或退出。

int emscripten_proxy_sync_with_ctx(em_proxying_queue* q, pthread_t target_thread, void (*func)(em_proxying_ctx*, void*), void* arg)

emscripten_proxy_sync 相同,除了它不等待代理函数返回,而是等待使用 emscripten_proxy_finish 显式标记完成的代理任务。 func 本身不需要调用 emscripten_proxy_finish;它可以改为存储上下文指针,并在任意时间调用 emscripten_proxy_finish

int emscripten_proxy_callback(em_proxying_queue* q, pthread_t target_thread, void (*func)(void*), void (*callback)(void*), void (*cancel)(void*), void* arg)

在给定队列和线程上排队 func。一旦(以及如果)它完成执行,它将异步代理 callback 回到同一队列上的当前线程,或者如果目标线程在工作完成之前死亡,则将代理 cancel 回来。所有三个函数都将接收相同的参数 arg。如果 func 成功排队且目标线程收到通知,则返回 1,否则返回 0。

int emscripten_proxy_callback_with_ctx(em_proxying_queue* q, pthread_t target_thread, void (*func)(em_proxying_ctx*, void*), void (*callback)(void*), void (*cancel)(void*), void* arg)

在给定队列和线程上排队 func。一旦(以及如果)它通过在给定的 em_proxying_ctx 上调用 emscripten_proxy_finish 完成任务,它将异步代理 callback 回到同一队列上的当前线程,或者如果目标线程在工作完成之前死亡,则将代理 cancel 回来。所有三个函数都将接收相同的参数 arg。如果 func 成功排队且目标线程收到通知,则返回 1,否则返回 0。

C++ API

此 C++ API 由 proxying.h 在使用 C++11 或更高版本编译时提供。它在命名空间 emscripten 中定义。

类型 ProxyingQueue

一个围绕 em_proxying_queue* 的 C++ 薄包装器。

类型 ProxyingCtx

一个围绕 em_proxying_ctx* 的 C++ 薄包装器。

em_proxying_ctx *ctx

包装的 em_proxying_ctx*

void finish()

在包装的 em_proxying_ctx* 上调用 emscripten_proxy_finish

void execute()

在包装的 em_proxying_queue* 上调用 emscripten_proxy_execute_queue

bool proxyAsync(pthread_t target, std::function<void()> &&func)

调用 emscripten_proxy_async 来执行 func,如果函数成功入队则返回 true,否则返回 false

bool proxySync(const pthread_t target, const std::function<void()> &func)

调用 emscripten_proxy_sync 来执行 func,如果函数成功完成则返回 true,否则返回 false

bool proxySyncWithCtx(const pthread_t target, const std::function<void(ProxyingCtx)> &func)

调用 emscripten_proxy_sync_with_ctx 来执行 func,如果函数已成功使用 emscripten_proxy_finishProxyingCtx::finish 标记完成,则返回 true,否则返回 false

bool proxyCallback(pthread_t target, std::function<void()> &&funcstd::function<void()> &&callbackstd::function<void()> &&cancel)

调用 emscripten_proxy_callback 来执行 func 并调度 callbackcancel,如果函数成功入队则返回 true,否则返回 false

bool proxyCallbackWithCtx(pthread_t target, std::function<void(ProxyingCtx)> &&func, std::function<void()> &&callbackstd::function<void()> &&cancel)

调用 emscripten_proxy_callback_with_ctx 来执行 func 并调度 callbackcancel,如果函数成功入队则返回 true,否则返回 false