diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-10-22 15:30:03 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-10-22 15:30:03 -0700 |
commit | e48db465e2a2f13b2e9c4797d3334fc6d2b29b6d (patch) | |
tree | 79937100322df639de1bc78b3f1d3dd25871650c /src | |
parent | 11a4926fc6c2bfe43fef3c66ad30e4b2df612616 (diff) |
initial work on worker api
Diffstat (limited to 'src')
-rw-r--r-- | src/library_browser.js | 66 | ||||
-rw-r--r-- | src/postamble.js | 26 | ||||
-rw-r--r-- | src/settings.js | 7 |
3 files changed, 96 insertions, 3 deletions
diff --git a/src/library_browser.js b/src/library_browser.js index 99106fc3..7e2866b8 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -42,6 +42,7 @@ mergeInto(LibraryManager.library, { }, pointerLock: false, moduleContextCreatedCallbacks: [], + workers: [], ensureObjects: function() { if (Browser.ensured) return; @@ -565,6 +566,71 @@ mergeInto(LibraryManager.library, { } else { return Date.now(); } + }, + + emscripten_create_worker: function(url) { + url = Pointer_stringify(url); + var id = Browser.workers.length; + var info = { + worker: new Worker(url), + callbacks: [], + buffer: 0, + bufferSize: 0 + }; + info.worker.onmessage = function(msg) { + var info = Browser.workers[id]; + if (!info) return; // worker was destroyed meanwhile + var callbackId = msg.data.callbackId; + var callbackInfo = info.callbacks[callbackId]; + if (!callbackInfo) return; // no callback or callback removed meanwhile + info.callbacks[callbackId] = null; // TODO: reuse callbackIds, compress this + var data = msg.data.data; + if (!data.byteLength) data = new Uint8Array(data); + if (!info.buffer || info.bufferSize < data.length) { + if (info.buffer) _free(info.buffer); + info.bufferSize = data.length; + info.buffer = _malloc(data.length); + } + HEAPU8.set(data, info.buffer); + callbackInfo.func(info.buffer, data.length, callbackInfo.arg); + }; + Browser.workers.push(info); + return id; + }, + + emscripten_destroy_worker: function(id) { + var info = Browser.workers[id]; + info.worker.terminate(); + if (info.buffer) _free(info.buffer); + Browser.workers[id] = null; + }, + + emscripten_call_worker: function(id, funcName, data, size, callback, arg) { + funcName = Pointer_stringify(funcName); + var info = Browser.workers[id]; + var callbackId = -1; + if (callback) { + callbackId = info.callbacks.length; + info.callbacks.push({ + func: Runtime.getFuncWrapper(callback), + arg: arg + }); + } + info.worker.postMessage({ + funcName: funcName, + callbackId: callbackId, + data: {{{ makeHEAPView('U8', 'data', 'data + size') }}} + }); + }, + + emscripten_worker_respond: function(data, size) { + if (!inWorkerCall) throw 'not in worker call!'; + if (workerResponded) throw 'already responded!'; + workerResponded = true; + postMessage({ + callbackId: workerCallbackId, + data: {{{ makeHEAPView('U8', 'data', 'data + size') }}} + }); } }); diff --git a/src/postamble.js b/src/postamble.js index d164f049..86c990e8 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -113,3 +113,29 @@ if (shouldRunNow) { // {{POST_RUN_ADDITIONS}} +#if BUILD_AS_WORKER + +var buffer = 0, bufferSize = 0; +var inWorkerCall = false, workerResponded = false, workerCallbackId = -1; + +onmessage = function(msg) { + var func = Module['_' + msg.data.funcName]; + if (!func) throw 'invalid worker function to call: ' + msg.data.funcName; + var data = msg.data.data; + if (!data.byteLength) data = new Uint8Array(data); + if (!buffer || bufferSize < data.length) { + if (buffer) _free(buffer); + bufferSize = data.length; + buffer = _malloc(data.length); + } + HEAPU8.set(data, buffer); + + inWorkerCall = true; + workerResponded = false; + workerCallbackId = msg.data.callbackId; + func(buffer, data.length); + inWorkerCall = false; +} + +#endif + diff --git a/src/settings.js b/src/settings.js index a6c11448..a1c41de7 100644 --- a/src/settings.js +++ b/src/settings.js @@ -213,10 +213,9 @@ var SHOW_LABELS = 0; // Show labels in the generated code var PRINT_SPLIT_FILE_MARKER = 0; // Prints markers in Javascript generation to split the file later on. See emcc --split option. -var BUILD_AS_SHARED_LIB = 0; // Whether to build the code as a shared library, which - // must be loaded dynamically using dlopen(). +var BUILD_AS_SHARED_LIB = 0; // Whether to build the code as a shared library // 0 here means this is not a shared lib: It is a main file. - // 1 means this is a normal shared lib. + // 1 means this is a normal shared lib, load it with dlopen(). // 2 means this is a shared lib that will be linked at runtime, // which means it will insert its functions into // the global namespace. See STATIC_LIBS_TO_LOAD. @@ -225,6 +224,8 @@ var RUNTIME_LINKED_LIBS = []; // If this is a main file (BUILD_AS_SHARED_LIB == // BUILD_AS_SHARED_LIB == 2. // NOTE: LLVM optimizations run separately on the main file and // linked libraries can break things. +var BUILD_AS_WORKER = 0; // If set to 1, this is a worker library, a special kind of library + // that is run in a worker. See emscripten.h var LINKABLE = 0; // If set to 1, this file can be linked with others, either as a shared // library or as the main file that calls a shared library. To enable that, // we will not internalize all symbols and cull the unused ones, in other |