emscripten使用C++20实现sleep功能

125 阅读1分钟

使用C++20中的协程实现一个WASM函数,此函数可以实现js中setTimeout的效果

实现方案

  • 定义一个Awaitable协议的结构实现sleep逻辑
  • 声明一个返回值为val的函数,并且使用co_return进行返回,因为val这个变量在emscripte中已经有promise_type的声明,所以无需进行额外处理
  • 使用embind导出函数并在html中调用

实现代码

struct Sleep {
  int _ms;
  std::coroutine_handle<> _handle;
  Sleep(int val) : _ms(val) {}

  bool await_ready() { return false; }

  void await_suspend(std::coroutine_handle<> handle) {
    _handle = handle;
    emscripten_async_call(
        [](void* val) {
          auto obj = (Sleep*)val;
          obj->_handle.resume();
        },
        this, _ms);
  }

  void await_resume() {}
};

val sleep2(int ms) {
  co_await Sleep(ms);
  co_return val::null();
}

EMSCRIPTEN_BINDINGS(module) {
  function("sleep2", sleep2);
}

调用示例

<html>

<script>
  var Module = {
    onRuntimeInitialized: async () => {
      try {
        console.log('sleep2 start')
        Module.sleep2(1000)
        await Module.sleep2(1000)
        console.log('sleep2 end')
      } catch (e) {
        console.error(e)
      }
    }
  };
</script>
<script src="./build/main.js"></script>

</html>