+ for(var i = 0; i < num; ++i) s += ', p' + i + ': p' + i;
+ return s;
+ }
+
+ // This is ad-hoc numbering scheme to map signatures to IDs, and must agree with call handler in src/library_pthread.js.
+ // Once proxied function calls no longer go through postMessage()s but instead in the heap, this will need to change, since int vs float will matter.
@@ -402,7 +504,12 @@ function JSify(data, functionsOnly) {
legalizedI64s = legalizedI64sDefault;
if (!BUILD_AS_SHARED_LIB && !SIDE_MODULE) {
- if (USE_PTHREADS) print('if (!ENVIRONMENT_IS_PTHREAD) {\n // Only main thread initializes these, pthreads copy them over at thread worker init time (in pthread-main.js)');
+ if (USE_PTHREADS) {
+ print('\n // proxiedFunctionTable specifies the list of functions that can be called either synchronously or asynchronously from other threads in postMessage()d or internally queued events. This way a pthread in a Worker can synchronously access e.g. the DOM on the main thread.')
+ for(i in proxiedFunctionInvokers) print(proxiedFunctionInvokers[i]+'\n');
+ print('if (!ENVIRONMENT_IS_PTHREAD) {\n // Only main thread initializes these, pthreads copy them over at thread worker init time (in pthread-main.js)');
+ PThread.currentProxiedOperationCallerThread = worker.pthread.threadInfoStruct; // Sometimes we need to backproxy events to the calling thread (e.g. HTML5 DOM events handlers such as emscripten_set_mousemove_callback()), so keep track in a globally accessible variable about the thread that initiated the proxying.
+ switch(e.data.proxiedCall) {
+ case 1: case 21: returnValue = funcTable[funcIdx](); break;
+ case 2: returnValue = funcTable[funcIdx](e.data.p0); break;
+ case 3: returnValue = funcTable[funcIdx](e.data.p0, e.data.p1); break;
+ case 4: returnValue = funcTable[funcIdx](e.data.p0, e.data.p1, e.data.p2); break;
+ case 5: returnValue = funcTable[funcIdx](e.data.p0, e.data.p1, e.data.p2, e.data.p3); break;
+extern void getDomElementInnerHTML(const char *domElement, char *dst, int size);
+extern int isThisInWorker(void);
+extern int isThisInWorkerOnMainThread(void);
+extern int receivesAndReturnsAnInteger(int i);
+
+// Define this if compiling via -s PROXY_TO_PTHREAD=1
+// #define PROXY_TO_PTHREAD 1
+
+int main()
+{
+ char dst[256];
+ char name[7] = "resize";
+ getDomElementInnerHTML(name, dst, sizeof(dst));
+ memset(name, 0, sizeof(name)); // Try to uncover if there might be a race condition and above line was not synchronously processed, and we could take name string away.
+ int inWorker1 = isThisInWorker(); // Build this application with -s USE_PTHREADS=1 -s PROXY_TO_PTHREAD=1 for this to return 1, otherwise returns 0.
+ int inWorker2 = isThisInWorkerOnMainThread(); // This should always return 0
+ int returnedInt = receivesAndReturnsAnInteger(4);
# Tests the Emscripten HTML5 API emscripten_set_canvas_element_size() and emscripten_get_canvas_element_size() functionality in singlethreaded programs.
-Emscripten supports OpenAL 1.1 "out of the box", with no additional compilation flag required. The implementation uses the Web Audio API.
+Emscripten ships with its own implementation of the OpenAL 1.1 API, using the Web Audio API as a backend.
-You can reasonably expect ported OpenAL applications to "just work" with no additional effort.
-However, there are some implementation-specific aspects which are worth considering - these are documented here.
+You can reasonably expect ported OpenAL applications to "just work" with no additional effort. Just link with the ``-lopenal`` linker flag.
+
+There are some implementation-specific aspects which are worth considering and are documented here.
+
+.. warning:: There used to be no additional flag to pass to the compiler in order to use OpenAL. However, specifying ``-lopenal`` as mentioned above should be considered mandatory (at some point in the future, it **will** be)!
.. _Audio-openal-extensions-g:
@@ -33,32 +36,21 @@ The following extensions are supported by Emscripten's OpenAL implementation.
Guidelines for Audio on Emscripten
==================================
-First: Do not loop on OpenAL calls.
+Know that your application needs to yield to the Javascript main loop for audio processing to take place (See :ref:`Browser main loop <emscripten-runtime-environment-main-loop>`).
-Put simply, avoid completely this kind of code :
+Put simply, this kind of code will block indefinitely :
+The above snippet usually works in native applications because most OpenAL implementations own and manage one or more separate threads. This is **not** the case in Emscripten.
-The reason for this is simple: Your application needs to yield to the Javascript main loop for audio processing to take place (See :ref:`Browser main loop <emscripten-runtime-environment-main-loop>`).
-
-The above snippet usually works because most OpenAL implementations own and manage one or more separate threads. This is not the case in Emscripten.
What you must do instead is perform each such query only once per "main loop iteration" (i.e the callback you provide via :c:func:`emscripten_set_main_loop` or :c:func:`emscripten_set_main_loop_arg`).
-Second: Avoid creating and destroying resources relentlessly.
-
-On some browsers (except, apparently, Firefox), garbage collection does not occur as much as it should. Knowing this, your app should ideally at most use one ``ALCcontext`` for playback and one ``ALCdevice`` for capture.
-
-Even if you're planning to suspend audio capture or playback for extended periods of time, it is probably better to keep contexts in memory (unlike in native apps where you should rather destroy them) to avoid risking memory leaks caused by poorly garbage-collected Javascript implementations.
-
-Of course, the current OpenAL implementation strives to be memory-efficient, but it has no control over lower-level mechanisms involved.