diff options
Diffstat (limited to 'examples/coroutines/coroutines.tm')
| -rw-r--r-- | examples/coroutines/coroutines.tm | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/examples/coroutines/coroutines.tm b/examples/coroutines/coroutines.tm new file mode 100644 index 00000000..b530a685 --- /dev/null +++ b/examples/coroutines/coroutines.tm @@ -0,0 +1,67 @@ +# This is a coroutine library that uses libaco (https://libaco.org) +# +# Lua programmers will recognize this as similar to Lua's stackful coroutines. +# +# Async/Await programmers will weep at its beauty and gnash their teeth and +# rend their garments in despair at what they could have had. + +use ./aco.h +use ./aco.c +use ./acoyield.S + +func main() + say("Example usage") + co := Coroutine(func() + say("I'm in the coroutine!") + yield() + say("I'm back in the coroutine!") + ) + >> co + say("I'm in the main func") + >> co.resume() + say("I'm back in the main func") + >> co.resume() + say("I'm back in the main func again") + >> co.resume() + +struct aco_t(; extern, opaque) +struct aco_shared_stack_t(; extern, opaque) + +_main_co : @aco_t? = none +_shared_stack : @aco_shared_stack_t? = none + +struct Coroutine(co:@aco_t) + convert(fn:func() -> Coroutine) + if not _main_co + _init() + + main_co := _main_co + shared_stack := _shared_stack + aco_ptr := C_code:@aco_t( + aco_create(@main_co, @shared_stack, 0, (void*)@fn.fn, @fn.userdata) + ) + return Coroutine(aco_ptr) + + func is_finished(co:Coroutine->Bool; inline) + return C_code:Bool(((aco_t*)@co.co)->is_finished) + + func resume(co:Coroutine->Bool) + if co.is_finished() + return no + C_code { aco_resume(@co.co); } + return yes + +func _init() + C_code { + aco_set_allocator(GC_malloc, NULL); + aco_thread_init(aco_exit_fn); + } + _main_co = C_code:@aco_t(aco_create(NULL, NULL, 0, NULL, NULL)) + + _shared_stack = C_code:@aco_shared_stack_t(aco_shared_stack_new(0)) + +func yield(; inline) + C_code { + aco_yield(); + } + |
