remove the need for manual cleanup in async ccalls #3307

This commit is contained in:
Alon Zakai 2015-04-08 11:33:21 -07:00
Родитель 7939f342fe
Коммит 9bff6f5bed
4 изменённых файлов: 13 добавлений и 10 удалений

Просмотреть файл

@ -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')