aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--src/library_browser.js21
-rw-r--r--system/include/emscripten/emscripten.h9
-rw-r--r--tests/test_browser.py4
-rw-r--r--tests/worker_api_3_main.cpp44
-rw-r--r--tests/worker_api_3_worker.cpp25
6 files changed, 98 insertions, 6 deletions
diff --git a/AUTHORS b/AUTHORS
index d47b3199..f2b6651d 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -118,3 +118,4 @@ a license to everyone to use it as detailed in LICENSE.)
* Alexandre Perrot <alexandre.perrot@gmail.com>
* Emerson José Silveira da Costa <emerson.costa@gmail.com>
* Jari Vetoniemi <mailroxas@gmail.com>
+* Dave Nicponski <dave.nicponski@gmail.com>
diff --git a/src/library_browser.js b/src/library_browser.js
index 458a8dd2..9261a2cf 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -1,7 +1,6 @@
//"use strict";
// Utilities for browser environments
-
mergeInto(LibraryManager.library, {
$Browser__deps: ['$PATH'],
$Browser__postset: 'Module["requestFullScreen"] = function Module_requestFullScreen(lockPointer, resizeCanvas) { Browser.requestFullScreen(lockPointer, resizeCanvas) };\n' + // exports
@@ -918,8 +917,11 @@ mergeInto(LibraryManager.library, {
var callbackId = msg.data['callbackId'];
var callbackInfo = info.callbacks[callbackId];
if (!callbackInfo) return; // no callback or callback removed meanwhile
- info.awaited--;
- info.callbacks[callbackId] = null; // TODO: reuse callbackIds, compress this
+ // Don't trash our callback state if we expect additional calls.
+ if (msg.data['finalResponse']) {
+ info.awaited--;
+ info.callbacks[callbackId] = null; // TODO: reuse callbackIds, compress this
+ }
var data = msg.data['data'];
if (data) {
if (!data.byteLength) data = new Uint8Array(data);
@@ -964,12 +966,23 @@ mergeInto(LibraryManager.library, {
});
},
+ emscripten_worker_respond_provisionally: function(data, size) {
+ if (!inWorkerCall) throw 'not in worker call!';
+ if (workerResponded) throw 'already responded with final response!';
+ postMessage({
+ 'callbackId': workerCallbackId,
+ 'finalResponse': false,
+ 'data': data ? new Uint8Array({{{ makeHEAPView('U8', 'data', 'data + size') }}}) : 0 // XXX copy to a new typed array as a workaround for chrome bug 169705
+ });
+ },
+
emscripten_worker_respond: function(data, size) {
if (!inWorkerCall) throw 'not in worker call!';
- if (workerResponded) throw 'already responded!';
+ if (workerResponded) throw 'already responded with final response!';
workerResponded = true;
postMessage({
'callbackId': workerCallbackId,
+ 'finalResponse': true,
'data': data ? new Uint8Array({{{ makeHEAPView('U8', 'data', 'data + size') }}}) : 0 // XXX copy to a new typed array as a workaround for chrome bug 169705
});
},
diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h
index b6e6307b..918059f2 100644
--- a/system/include/emscripten/emscripten.h
+++ b/system/include/emscripten/emscripten.h
@@ -377,10 +377,15 @@ void emscripten_destroy_worker(worker_handle worker);
void emscripten_call_worker(worker_handle worker, const char *funcname, char *data, int size, void (*callback)(char *, int, void*), void *arg);
/*
- * Sends a response when in a worker call. Should only be
- * called once in each call.
+ * Sends a response when in a worker call. Both functions post a message
+ * back to the thread which called the worker. The _respond_provisionally
+ * variant can be invoked multiple times, which will queue up messages to
+ * be posted to the worker's creator. Eventually, the _respond variant can
+ * be invoked, which will disallow further messages and free framework
+ * resources previously allocated for this worker call.
*/
void emscripten_worker_respond(char *data, int size);
+void emscripten_worker_respond_provisionally(char *data, int size);
/*
* Checks how many responses are being waited for from a worker. This
diff --git a/tests/test_browser.py b/tests/test_browser.py
index eed18a3d..3b9d6ebb 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -1678,6 +1678,10 @@ keydown(100);keyup(100); // trigger the end
Popen([PYTHON, EMCC, path_from_root('tests', 'worker_api_2_worker.cpp'), '-o', 'worker.js', '-s', 'BUILD_AS_WORKER=1', '-O2', '--minify', '0', '-s', 'EXPORTED_FUNCTIONS=["_one", "_two", "_three", "_four"]']).communicate()
self.btest('worker_api_2_main.cpp', args=['-O2', '--minify', '0'], expected='11')
+ def test_worker_api_3(self):
+ Popen([PYTHON, EMCC, path_from_root('tests', 'worker_api_3_worker.cpp'), '-o', 'worker.js', '-s', 'BUILD_AS_WORKER=1', '-s', 'EXPORTED_FUNCTIONS=["_one"]']).communicate()
+ self.btest('worker_api_3_main.cpp', expected='5')
+
def test_emscripten_async_wget2(self):
self.btest('http.cpp', expected='0', args=['-I' + path_from_root('tests')])
diff --git a/tests/worker_api_3_main.cpp b/tests/worker_api_3_main.cpp
new file mode 100644
index 00000000..595f99b9
--- /dev/null
+++ b/tests/worker_api_3_main.cpp
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <assert.h>
+#include <emscripten.h>
+
+int w1;
+
+bool sawCalls[] = { false, false, false, false };
+
+void c1(char *data, int size, void *arg) {
+ assert((int)arg == 97);
+ assert(size >= sizeof(int));
+
+ int *x = (int*)data;
+ printf("c1: %d\n", x[0]);
+
+ if (*x >= 0 && *x < 4) {
+ // Calls should have happened in order.
+ sawCalls[*x] = true; // Note the call with current param was made
+ for (int i = 0; i < *x - 1; ++i) {
+ if (!sawCalls[i]) {
+ // If we were called out of order, fail this and all following calls.
+ sawCalls[*x] = false;
+ break;
+ }
+ }
+ } else {
+ assert(*x == 4);
+ // This is the last call. All prior calls should have occurred.
+ int result = 1; // Final call occurred.
+ for (int i = 0; i < 4; ++i)
+ if (sawCalls[i]) result++;
+ REPORT_RESULT();
+ }
+}
+
+int main() {
+ w1 = emscripten_create_worker("worker.js");
+
+ int x[1] = { 0 };
+ emscripten_call_worker(w1, "one", (char*)x, sizeof(x), c1, (void*)97);
+
+ return 0;
+}
+
diff --git a/tests/worker_api_3_worker.cpp b/tests/worker_api_3_worker.cpp
new file mode 100644
index 00000000..db14377a
--- /dev/null
+++ b/tests/worker_api_3_worker.cpp
@@ -0,0 +1,25 @@
+#include <assert.h>
+#include <emscripten.h>
+
+extern "C" {
+
+// Respond with 0, 1, 2, 3 each with finalResponse=false, and 4 with
+// finalResponse=true.
+void one(char *data, int size) {
+ int *x = (int*)data;
+
+ if (*x == 0) {
+ // Respond 0, 1, 2, 3
+ for (int i = 0; i < 4; ++i) {
+ *x = i;
+ emscripten_worker_respond_provisionally(data, size);
+ }
+ }
+
+ // Respond 4
+ *x = 4;
+ emscripten_worker_respond(data, size);
+}
+
+}
+