| // Copyright 2019 The Emscripten Authors. All rights reserved. | |
| // Emscripten is available under two separate licenses, the MIT license and the | |
| // University of Illinois/NCSA Open Source License. Both these licenses can be | |
| // found in the LICENSE file. | |
| // Based on test_coroutines.cpp | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <emscripten/fiber.h> | |
| struct Fiber { | |
| emscripten_fiber_t context; | |
| char asyncify_stack[1024]; | |
| alignas(16) char c_stack[4096]; | |
| int result = 0; | |
| void init_with_api(em_arg_callback_func entry, void *arg) { | |
| emscripten_fiber_init(&context, entry, arg, c_stack, sizeof(c_stack), asyncify_stack, sizeof(asyncify_stack)); | |
| } | |
| void init_manually(em_arg_callback_func entry, void *arg) { | |
| context.stack_base = c_stack + sizeof(c_stack); | |
| context.stack_limit = c_stack; | |
| context.stack_ptr = context.stack_base; | |
| context.entry = entry; | |
| context.user_data = arg; | |
| context.asyncify_data.stack_ptr = asyncify_stack; | |
| context.asyncify_data.stack_limit = asyncify_stack + sizeof(asyncify_stack); | |
| } | |
| void swap(emscripten_fiber_t *fiber) { | |
| emscripten_fiber_swap(&context, fiber); | |
| } | |
| }; | |
| struct Globals { | |
| emscripten_fiber_t main; | |
| char asyncify_stack[1024]; | |
| Fiber fibers[2]; | |
| Globals() { | |
| emscripten_fiber_init_from_current_context(&main, asyncify_stack, sizeof(asyncify_stack)); | |
| } | |
| } G; | |
| void leaf(void) { | |
| printf("leaf-"); | |
| } | |
| void fib(void * arg) { | |
| int *p = (int*)arg; | |
| int cur = 1; | |
| int next = 1; | |
| for(int i = 0; i < 9; ++i) { | |
| *p = cur; | |
| G.fibers[0].swap(&G.main); | |
| int next2 = cur + next; | |
| cur = next; | |
| next = next2; | |
| } | |
| } | |
| [[noreturn]] | |
| void f(void *arg) { | |
| int *p = (int*)arg; | |
| *p = 0; | |
| leaf(); | |
| G.fibers[0].swap(&G.main); | |
| fib(arg); | |
| G.fibers[0].result = 1; | |
| G.fibers[0].swap(&G.main); | |
| abort(); | |
| } | |
| [[noreturn]] | |
| void g(void *arg) { | |
| int *p = (int*)arg; | |
| for(int i = 0; i < 10; ++i) { | |
| *p = 100+i; | |
| G.fibers[1].swap(&G.main); | |
| } | |
| G.fibers[1].result = 1; | |
| G.fibers[1].swap(&G.main); | |
| abort(); | |
| } | |
| int main(int argc, char **argv) { | |
| int i; | |
| G.fibers[0].init_with_api(f, &i); | |
| G.fibers[1].init_manually(g, &i); | |
| printf("*"); | |
| while(emscripten_fiber_swap(&G.main, &G.fibers[0].context), !G.fibers[0].result) { | |
| printf("%d-", i); | |
| emscripten_fiber_swap(&G.main, &G.fibers[1].context); | |
| printf("%d-", i); | |
| } | |
| printf("*\n"); | |
| return 0; | |
| } |