diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2024-03-13 14:37:48 -0400 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2024-03-13 14:37:48 -0400 |
commit | 354d7b55c0a267b542dc51e3985f7d3739ffcdfd (patch) | |
tree | 7d1c401b89d8c292cfc691bdfed9b4d380ce58e6 /indra | |
parent | 587d65dc127fd72cd72aed5f02dbfd3bf277a9ef (diff) |
Introduce a resume() wrapper to surface coroutine errors.
Diffstat (limited to 'indra')
-rw-r--r-- | indra/newview/scripts/lua/qtest.lua | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/indra/newview/scripts/lua/qtest.lua b/indra/newview/scripts/lua/qtest.lua index 12e425b7b2..009446d0c3 100644 --- a/indra/newview/scripts/lua/qtest.lua +++ b/indra/newview/scripts/lua/qtest.lua @@ -7,6 +7,19 @@ util = require('util') inspect = require('inspect') +-- resume() wrapper to propagate errors +function resume(co, ...) + -- if there's an idiom other than table.pack() to assign an arbitrary + -- number of return values, I don't yet know it + local ok_result = table.pack(coroutine.resume(co, ...)) + if not ok_result[1] then + -- if [1] is false, then [2] is the error message + error(ok_result[2]) + end + -- ok is true, whew, just return the rest of the values + return table.unpack(ok_result, 2) +end + -- ------------------ Queue variables are instance-specific ------------------ q1 = Queue:new() q2 = Queue:new() @@ -51,9 +64,9 @@ coa = coroutine.create(consumer) cob = coroutine.create(consumer) -- Since consumer() doesn't yield while it can still retrieve values, -- consumer(a) will dequeue all values from q1 and return when done. -coroutine.resume(coa, 'a', q1) +resume(coa, 'a', q1) -- consumer(b) will wake up to find the queue empty and closed. -coroutine.resume(cob, 'b', q1) +resume(cob, 'b', q1) coroutine.close(coa) coroutine.close(cob) @@ -72,7 +85,7 @@ for _, name in {'a', 'b'} do local coro = coroutine.create(consumer) table.insert(coros, coro) -- Resuming both coroutines should leave them both waiting for a queue item. - coroutine.resume(coro, name, q3) + resume(coro, name, q3) end for _, s in pairs(values) do @@ -89,6 +102,8 @@ function joinall(coros) for i, coro in pairs(coros) do if coroutine.status(coro) == 'suspended' then running = true + -- directly call coroutine.resume() instead of our resume() + -- wrapper because we explicitly check for errors here local ok, message = coroutine.resume(coro) if not ok then print('*** ' .. message) @@ -105,7 +120,7 @@ end joinall(coros) -print(string.format('%q', util.join(result, ' '))) +print(string.format('%q', table.concat(result, ' '))) assert(util.equal(values, result)) -- ----------------------------- test ErrorQueue ----------------------------- @@ -118,7 +133,7 @@ for _, name in {'a', 'b'} do local coro = coroutine.create(consumer) table.insert(coros, coro) -- Resuming both coroutines should leave them both waiting for a queue item. - coroutine.resume(coro, name, q4) + resume(coro, name, q4) end for i = 1, 4 do |