WebAssembly

创建webasm字符串模板

my-module.wat:

(module
  (func $add (param $a i32) (param $b i32) (result i32)
    (i32.add 
      (local.get $a) 
      (local.get $b)
    )
  )

  (export "add" (func $add))
)

将wat转化为wasm二进制文件

$ wat2wasm.exe my-module.wat

上面的命令将使用my-module.wat文件生成my-module.wasm文件

js调用

const resp = await fetch("my-module.wasm");
const buf = await resp.arrayBuffer();
const { instance } = await WebAssembly.instantiate(buf);
const r = instance.exports.add(1, 2);
console.assert(r === 3);

wasm 使用导入的模块

(module
  (import "JsModule" "alert" (func $alert (param i32)))

  (func $add (param $a i32) (param $b i32)
    (call $alert (i32.add 
      (local.get $a) 
      (local.get $b)
    ))
  )

  (export "add" (func $add))
)
const resp = await fetch("./my-module.wasm");
const buf = await resp.arrayBuffer();
const { instance } = await WebAssembly.instantiate(buf, {
  JsModule: { alert },
});
const r = instance.exports.add(1, 2);
console.assert(r === undefined);

wasm 使用导入的内存

(module
  (import "env" "memory" (memory 1)) 
  (func $add (result i32)
    (i32.add 
      (i32.load (i32.const 0)) 
      (i32.load (i32.const 4))
    )
  )

  (export "add" (func $add))
)
const mem = new WebAssembly.Memory({ initial: 1 });
const view = new DataView(mem.buffer);

// 你需要使用小端法来存数据
// view默认使用大端,但是在wasm中读取时使用小端
view.setInt32(0, 1, true);
view.setInt32(4, 2, true);

console.assert(view.getInt32(0, true) === 1);
console.assert(view.getInt32(4, true) === 2);

const resp = await fetch("./my-module.wasm");
const buf = await resp.arrayBuffer();
const { instance } = await WebAssembly.instantiate(buf, {
  env: { memory: mem },
});

const r = instance.exports.add(1, 2);
console.assert(r === 3);

在线程中共享内存,及挂起线程

main.js

const sab = new SharedArrayBuffer(4);
const view = new Int32Array(sab);
const worker = new Worker("w.js");
worker.postMessage(sab);

setTimeout(() => {
  view[0] = 100;
  Atomics.notify(view, 0); // 唤醒等待的线程
}, 3000);

w.js

onmessage = (e) => {
  const view = new Int32Array(e.data);

  // 如果数组中给定位置的值等于提供的值,则将当前代理置于睡眠状态,导致执行挂起,
  // 直到超时到期(返回“超时”)或直到代理被唤醒(返回“ ok”)为止。 “); 否则,返回“不等于”。
  Atomics.wait(view, 0, 0); // view[0] === 0 挂起线程
  console.log(view[0]);
  console.assert(view[0] === 100);
};

See also:

posted @ 2020-10-28 12:00  Ajanuw  阅读(297)  评论(0编辑  收藏  举报