diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2024-03-11 16:49:03 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2024-03-11 16:49:03 -0400 |
commit | c371096fc3320f580fd271dad09c852f2e3d5f78 (patch) | |
tree | 44d38d4a4a175e09eb438b63b11c06dbb98fa7d2 /indra | |
parent | 42de5594cd4ebde605e6f93a48a7e7c9ab60ace4 (diff) |
Add coro.lua to aggregate created coroutines.
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/scripts/lua/coro.lua | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/indra/newview/scripts/lua/coro.lua b/indra/newview/scripts/lua/coro.lua new file mode 100644 index 0000000000..8f868f5a48 --- /dev/null +++ b/indra/newview/scripts/lua/coro.lua @@ -0,0 +1,57 @@ +-- Manage Lua coroutines + +local coro = {} + +coro._coros = {} + +-- Launch a Lua coroutine: create and resume. +-- Returns: +-- new coroutine +-- bool ok +-- if not ok: error message +-- if ok: values yielded or returned +function coro.launch(func, ...) + local co = coroutine.create(func) + table.insert(coro._coros, co) + return co, coroutine.resume(co, ...) +end + +-- yield to other coroutines even if you don't know whether you're in a +-- created coroutine or the main coroutine +function coro.yield(...) + if coroutine.running() then + -- this is a real coroutine, yield normally + return coroutine.yield(...) + else + -- This is the main coroutine: coroutine.yield() doesn't work. + -- But we can take a spin through previously-launched coroutines. + -- Walk a copy of coro._coros in case any of these coroutines launches + -- another: next() forbids creating new entries during traversal. + for co in coro._live_coros_iter, table.clone(coro._coros) do + co.resume() + end + end +end + +-- Walk coro._coros table, returning running or suspended coroutines. +-- Once a coroutine becomes dead, remove it from _coros and don't return it. +function coro._live_coros() + return coro._live_coros_iter, coro._coros +end + +-- iterator function for _live_coros() +function coro._live_coros_iter(t, idx) + local k, co = next(t, idx) + while k and coroutine.status(co) == 'dead' do +-- t[k] = nil + -- See coro.yield(): sometimes we traverse a copy of _coros, but if we + -- discover a dead coroutine in that copy, delete it from _coros + -- anyway. Deleting it from a temporary copy does nothing. + coro._coros[k] = nil + coroutine.close(co) + k, co = next(t, k) + end + return co +end + +return coro |