remove the need for manual cleanup in async ccalls #3307
This commit is contained in:
Родитель
7939f342fe
Коммит
9bff6f5bed
|
@ -58,7 +58,7 @@ Calling compiled C functions from JavaScript
|
|||
:returns: The result of the function call as a native JavaScript value (as in ``returnType``).
|
||||
:opts: An optional options object. It can contain the following properties:
|
||||
|
||||
- ``async``: Implies that the ccall will perform an async operation. This assumes you are using the Emterpreter-Async option for your code. When using this option, the ccalled function cannot return a value (it can't be received synchronously anyhow); instead, ccall will return a function that you should call after all asynchronous operations conclude (the function does some cleanup).
|
||||
- ``async``: Implies that the ccall will perform an async operation. This assumes you are using the Emterpreter-Async option for your code. When using this option, the ccalled function cannot return a value (it can't be received synchronously anyhow).
|
||||
|
||||
.. COMMENT (not rendered): The ccall/cwrap functions only work for C++ functions that use "extern C". In theory ordinary C++ names can be unmangled, but it would require tool to ship a fairly large amount of code just for this purpose.
|
||||
|
||||
|
|
|
@ -214,6 +214,7 @@ mergeInto(LibraryManager.library, {
|
|||
saveStack: '',
|
||||
yieldCallbacks: [],
|
||||
postAsync: null,
|
||||
asyncFinalizers: [], // functions to run when all asynchronicity is done
|
||||
|
||||
ensureInit: function() {
|
||||
if (this.initted) return;
|
||||
|
@ -275,6 +276,12 @@ mergeInto(LibraryManager.library, {
|
|||
// if we did *not* do another async operation, then we know that nothing is conceptually on the stack now, and we can re-allow async callbacks as well as run the queued ones right now
|
||||
Browser.resumeAsyncCallbacks();
|
||||
}
|
||||
if (EmterpreterAsync.state === 0) {
|
||||
EmterpreterAsync.asyncFinalizers.forEach(function(func) {
|
||||
func();
|
||||
});
|
||||
EmterpreterAsync.asyncFinalizers.length = 0;
|
||||
}
|
||||
});
|
||||
EmterpreterAsync.setState(1);
|
||||
#if ASSERTIONS
|
||||
|
|
|
@ -393,9 +393,10 @@ var cwrap, ccall;
|
|||
if (returnType === 'string') ret = Pointer_stringify(ret);
|
||||
if (stack !== 0) {
|
||||
if (opts && opts.async) {
|
||||
return function() {
|
||||
EmterpreterAsync.asyncFinalizers.push(function() {
|
||||
Runtime.stackRestore(stack);
|
||||
};
|
||||
});
|
||||
return;
|
||||
}
|
||||
Runtime.stackRestore(stack);
|
||||
}
|
||||
|
|
|
@ -7378,17 +7378,12 @@ int main() {
|
|||
printf("Hello");
|
||||
emscripten_sleep(100);
|
||||
printf("World\n");
|
||||
EM_ASM( Module.doCleanup() );
|
||||
}
|
||||
'''
|
||||
open('post.js', 'w').write('''
|
||||
Module.cleanup = Module['ccall']('main', null, ['number', 'string'], [2, 'waka'], { async: true });
|
||||
Module.doCleanup = function() {
|
||||
Module.print('cleanup');
|
||||
Module.cleanup();
|
||||
};
|
||||
Module['ccall']('main', null, ['number', 'string'], [2, 'waka'], { async: true });
|
||||
''')
|
||||
self.do_run(src, 'HelloWorld\ncleanup');
|
||||
self.do_run(src, 'HelloWorld');
|
||||
|
||||
def test_coroutine(self):
|
||||
if not Settings.ASM_JS: return self.skip('asyncify requires asm.js')
|
||||
|
|
Загрузка…
Ссылка в новой задаче