From a7c1d27b09e334d8239185b5da3f98c92294992c Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Fri, 6 Sep 2024 12:29:36 -0400 Subject: [PATCH] Example coroutine library --- examples/coroutine.tm | 72 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 examples/coroutine.tm diff --git a/examples/coroutine.tm b/examples/coroutine.tm new file mode 100644 index 0000000..1d3d4dc --- /dev/null +++ b/examples/coroutine.tm @@ -0,0 +1,72 @@ +# This is a coroutine library that uses libaco. If you don't have it installed, +# you can get it from the website: 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 libaco.so +use + +func main(): + !! Example usage: + co := new(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() + +_main_co := !@Memory +_shared_stack := !@Memory + +struct Coroutine(co:@Memory): + func is_finished(co:Coroutine; inline)->Bool: + return inline C ( + ((aco_t*)$co.$co)->is_finished + ):Bool + + func resume(co:Coroutine)->Bool: + if co:is_finished(): + return no + inline C { + aco_resume($co.$co); + } + return yes + +func _init(): + inline C { + aco_set_allocator(GC_malloc, NULL); + aco_thread_init(aco_exit_fn); + } + _main_co = inline C( + aco_create(NULL, NULL, 0, NULL, NULL) + ):@Memory + + _shared_stack = inline C( + aco_shared_stack_new(0); + ):@Memory + +func new(co:func())->Coroutine: + if not _main_co: + _init() + + main_co := _main_co + shared_stack := _shared_stack + aco_ptr := inline C ( + aco_create($main_co, $shared_stack, 0, (void*)$co.fn, $co.userdata) + ):@Memory + return Coroutine(aco_ptr) + +func yield(; inline): + inline C { + aco_yield(); + } +