Emscripten中的`Module`变量机制,同时将Pthread编译为工作程序

问题描述

在将Pthread编译为Web Worker + Wasm时,我对Emsripten中的const actuallyAnObject = chat.usersArray; let realArray = actuallyAnObject.map((item,i) => item); // throws an error console.log(Object.keys(actuallyAnObject); // displays in the console correctly let keys = Object.keys(actuallyAnObject); // throws an error let array = []; Object.keys(actuallyAnObject).forEach((key) => { // throws an error array.push({[key]: actuallyAnObject[key]}); }); console.log("actuallyAnObject['0'] : ",actuallyAnObject["0"]); // displays correctly console.log("typeof actuallyAnObject : ",typeof actuallyAnObject); // object 变量感到困惑

一个简单的Pthread代码,只需在每个线程的共享变量Module添加1。 (sum附加在末尾。)

我们可以使用以下命令来编译Pthread代码

simple.c

Emscripten将生成$ emcc simple.c -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=4 -o simple.html simple.htmlsimple.jssimple.worker.js

simple.wasm中,有一个摘要

simple.worker.js

请注意,它在工作程序中声明了// simple.worker.js var Module = {}; // ... Module['instantiateWasm'] = function(info,receiveInstance) { // Instantiate from the module posted from the main thread. // We can just use sync instantiation in the worker. var instance = new WebAssembly.Instance(Module['wasmModule'],info); // We don't need the module anymore; new threads will be spawned from the main thread. Module['wasmModule'] = null; receiveInstance(instance); // The second 'module' parameter is intentionally null here,we don't need to keep a ref to the Module object from here. return instance.exports; }; ,并定义了var Module = {}

但是,Module['instantiateWasm']仅由Module['instantiateWasm']调用,其代码段如下所示:

simple.js

我们可以看到,//simple.js var Module = {} // ... if (Module['instantiateWasm']) { try { var exports = Module['instantiateWasm'](info,receiveInstance); return exports; } catch(e) { err('Module.instantiateWasm callback Failed with error: ' + e); return false; } } // ... 也声明了simple.js

AFAIK,var Module = {}全局变量无法在主线程及其工作线程之间进行访问。 我不明白为什么VAR可以像simple.js的{​​{1}}那样调用Module['instantiateWasm'],而Module的{​​{1}}却不能一样的东西。


Pthread代码

simple.js

解决方法

主程序将自身发送给工作人员。

// simple.js
// Ask the new worker to load up the Emscripten-compiled page. This is a heavy operation.
worker.postMessage({
  'cmd': 'load',// If the application main .js file was loaded from a Blob,then it is not possible
  // to access the URL of the current script that could be passed to a Web Worker so that
  // it could load up the same file. In that case,developer must either deliver the Blob
  // object in Module['mainScriptUrlOrBlob'],or a URL to it,so that pthread Workers can
  // independently load up the same main application file.
  'urlOrBlob': Module['mainScriptUrlOrBlob'] || _scriptDir,'wasmMemory': wasmMemory,'wasmModule': wasmModule,'DYNAMIC_BASE': DYNAMIC_BASE,'DYNAMICTOP_PTR': DYNAMICTOP_PTR
});

然后由工人导入。

// simple.worker.js
if (typeof e.data.urlOrBlob === 'string') {
  importScripts(e.data.urlOrBlob);
} else {
  var objectUrl = URL.createObjectURL(e.data.urlOrBlob);
  importScripts(objectUrl);
  URL.revokeObjectURL(objectUrl);
}

因此Module不被共享,但是它是独立初始化的。