Last active
October 21, 2019 21:18
-
-
Save corwin-of-amber/8f71f66a4c8c483beb813f6eb870f65e to your computer and use it in GitHub Desktop.
A utility library for coroutines in Emscripten (using Asyncify)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
emcc example.c -s ASYNCIFY \ | |
-s ASYNCIFY_IMPORTS='["emscripten_sleep","emscripten_yield","emscripten_coroutine_create","emscripten_coroutine_next"]' \ | |
--js-library library_coroutine.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <emscripten.h> | |
void cofunc(void *data) { | |
printf("co: 1\n"); | |
emscripten_yield(); | |
printf("co: 2\n"); | |
emscripten_yield(); | |
printf("co: 3\n"); | |
} | |
int main(int argc, char **argv) { | |
emscripten_coroutine co = emscripten_coroutine_create(cofunc, NULL, 64 * 1024); | |
printf("main: 1\n"); | |
emscripten_coroutine_next(co); | |
printf("main: 2\n"); | |
emscripten_coroutine_next(co); | |
printf("main: 3\n"); | |
emscripten_coroutine_next(co); | |
printf("-------\n"); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mergeInto(LibraryManager.library, { | |
$Coroutines__deps: ["Asyncify_restoreState"], | |
$Coroutines: { | |
main: null, live: [], active: null, | |
allocate: function(obj) { | |
id = this.live.length; | |
this.live[id] = obj; | |
return id; | |
}, | |
free: function(id) { | |
delete this.live[id]; | |
}, | |
resume: function(co) { | |
_Asyncify_restoreState(co.savedState); | |
co.jump(); | |
}, | |
return: function(id) { | |
this.free(id); | |
this.resume(this.main); | |
} | |
}, | |
assign$: function(to, from) { for (let k in from) to[k] = from[k]; }, | |
Asyncify_saveState: function() { | |
return {currData: Asyncify.currData}; | |
}, | |
Asyncify_restoreState__deps: ["assign$"], | |
Asyncify_restoreState: function(savedState) { | |
_assign$(Asyncify, savedState); | |
}, | |
emscripten_coroutine_create__deps: ["$Coroutines"], | |
emscripten_coroutine_create: function(funcptr, data, size) { | |
return Coroutines.allocate( | |
{jump: () => Module.asm.dynCall_vi(funcptr, data), savedState: {}}); | |
}, | |
emscripten_coroutine_next__deps: ["$Coroutines", "Asyncify_saveState"], | |
emscripten_coroutine_next: function(id) { | |
co = Coroutines.live[id]; | |
return Asyncify.handleSleep((wakeUp) => { | |
setTimeout(() => { | |
Coroutines.main = {jump: wakeUp, savedState: _Asyncify_saveState()}; | |
Coroutines.active = co; | |
Coroutines.resume(co); | |
if (!Asyncify.currData) Coroutines.return(id); | |
}); | |
}); | |
}, | |
emscripten_yield__deps: ["assign$", "Asyncify_saveState"], | |
emscripten_yield: function() { | |
return Asyncify.handleSleep((wakeUp) => { | |
setTimeout(() => { | |
_assign$(Coroutines.active, | |
{jump: wakeUp, savedState: _Asyncify_saveState()}); | |
Coroutines.resume(Coroutines.main); | |
}); | |
}); | |
}, | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment