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``).
|
: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:
|
: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.
|
.. 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: '',
|
saveStack: '',
|
||||||
yieldCallbacks: [],
|
yieldCallbacks: [],
|
||||||
postAsync: null,
|
postAsync: null,
|
||||||
|
asyncFinalizers: [], // functions to run when all asynchronicity is done
|
||||||
|
|
||||||
ensureInit: function() {
|
ensureInit: function() {
|
||||||
if (this.initted) return;
|
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
|
// 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();
|
Browser.resumeAsyncCallbacks();
|
||||||
}
|
}
|
||||||
|
if (EmterpreterAsync.state === 0) {
|
||||||
|
EmterpreterAsync.asyncFinalizers.forEach(function(func) {
|
||||||
|
func();
|
||||||
|
});
|
||||||
|
EmterpreterAsync.asyncFinalizers.length = 0;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
EmterpreterAsync.setState(1);
|
EmterpreterAsync.setState(1);
|
||||||
#if ASSERTIONS
|
#if ASSERTIONS
|
||||||
|
|
|
@ -393,9 +393,10 @@ var cwrap, ccall;
|
||||||
if (returnType === 'string') ret = Pointer_stringify(ret);
|
if (returnType === 'string') ret = Pointer_stringify(ret);
|
||||||
if (stack !== 0) {
|
if (stack !== 0) {
|
||||||
if (opts && opts.async) {
|
if (opts && opts.async) {
|
||||||
return function() {
|
EmterpreterAsync.asyncFinalizers.push(function() {
|
||||||
Runtime.stackRestore(stack);
|
Runtime.stackRestore(stack);
|
||||||
};
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
Runtime.stackRestore(stack);
|
Runtime.stackRestore(stack);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7378,17 +7378,12 @@ int main() {
|
||||||
printf("Hello");
|
printf("Hello");
|
||||||
emscripten_sleep(100);
|
emscripten_sleep(100);
|
||||||
printf("World\n");
|
printf("World\n");
|
||||||
EM_ASM( Module.doCleanup() );
|
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
open('post.js', 'w').write('''
|
open('post.js', 'w').write('''
|
||||||
Module.cleanup = Module['ccall']('main', null, ['number', 'string'], [2, 'waka'], { async: true });
|
Module['ccall']('main', null, ['number', 'string'], [2, 'waka'], { async: true });
|
||||||
Module.doCleanup = function() {
|
|
||||||
Module.print('cleanup');
|
|
||||||
Module.cleanup();
|
|
||||||
};
|
|
||||||
''')
|
''')
|
||||||
self.do_run(src, 'HelloWorld\ncleanup');
|
self.do_run(src, 'HelloWorld');
|
||||||
|
|
||||||
def test_coroutine(self):
|
def test_coroutine(self):
|
||||||
if not Settings.ASM_JS: return self.skip('asyncify requires asm.js')
|
if not Settings.ASM_JS: return self.skip('asyncify requires asm.js')
|
||||||
|
|
Загрузка…
Ссылка в новой задаче