summaryrefslogtreecommitdiff
path: root/indra/newview/scripts/lua/leap.lua
AgeCommit message (Collapse)Author
2024-05-31Add timers.lua API module and test_timers.lua test program.Nat Goodspeed
Since timers presents a timers.Timer Lua class supporting queries and cancellation, make TimersListener::scheduleAfter() and scheduleEvery() respond immediately so the newly constructed Timer object has the reqid necessary to perform those subsequent operations. This requires that Lua invocations of these operations avoid calling the caller's callback with that initial response. Reinvent leap.generate() to return a Lua object supporting next() and done() methods. A plain Lua coroutine that (indirectly) calls fiber.wait() confuses the fiber scheduler, so avoid implementing generate() as a Lua coroutine. Add a bit more leap.lua diagnostic output.
2024-05-31Add leap.eventstream() and cancelreq() functions.Nat Goodspeed
leap.eventstream() is used when we expect the viewer's LLEventAPI to send an immediate first response with the reqid from the request, followed by some number of subsequent responses bearing the same reqid. The difference between eventstream() and generate() is that generate() expects the caller to request each such response, whereas eventstream calls the caller's callback with each response. cancelreq() is for canceling the background fiber launched by eventstream() before the callback tells it to quit. Make WaitFor:close() remove the object from the waitfors list; similarly, make WaitForReqid:close() remove the object from the pending list. For this reason, cleanup() must iterate over a copy of each of the pending and waitfors lists. Instead of unregisterWaitFor() manually searching the waitfors list, use table.find().
2024-05-15Make leap.lua honor an "error" key in viewer response.Nat Goodspeed
2024-04-09Add Lua Floater class to simplify Lua script showing floaters.Nat Goodspeed
Add test_luafloater_demo2.lua and test_luafloater_gesture_list2.lua examples.
2024-04-02Defend leap.request(), generate() from garbage collection.Nat Goodspeed
Earlier we had blithely designated the 'pending' list (which stores WaitForReqid objects for pending request() and generate() calls) as a weak table. But the caller of request() or generate() does not hold a reference to the WaitForReqid object. Make pending hold "strong" references. Private collections (pending, waitfors) and private scalars that are never reassigned (reply, command) need not be entries in the leap table.
2024-03-27Enhance Lua debugging output.Nat Goodspeed
Don't use "debug" as the name of a function to conditionally write debug messages: "debug" is a Luau built-in library, and assigning that name locally would shadow the builtin. Use "dbg" instead. Recast fiber.print_all() as fiber.format_all() that returns a string; then print_all() is simply print(format_all()). This refactoring allows us to use dbg(format_all()) as well. Add a couple new dbg() messages at fiber state changes.
2024-03-25Add LL. prefix to viewer entry points, fix existing references.Nat Goodspeed
2024-03-22Fix a couple bugs in fiber.lua machinery.Nat Goodspeed
This fixes a hang if the Lua script explicitly calls fiber.run() before LuaState::expr()'s implicit fiber.run() call. Make fiber.run() remove the calling fiber from the ready list to avoid an infinite loop when all other fibers have terminated: "You're ready!" "Okay, yield()." "You're ready again!" ... But don't claim it's waiting, either, because then when all other fibers have terminated, we'd call idle() in the vain hope that something would make that one last fiber ready. WaitQueue:_wake_waiters() needs to wake waiting fibers if the queue's not empty OR it's been closed. Introduce leap.WaitFor:close() to close the queue gracefully so that a looping waiter can terminate, instead of using WaitFor:exception(), which stops the whole script once it propagates. Make leap's cleanup() function call close(). Streamline fiber.get_name() by using 'or' instead of if ... then. Streamline fiber.status() and fiber.set_waiting() by using table.find() instead of a loop.
2024-03-21WIP: Add fiber.lua module and use in leap.lua and WaitQueue.lua.Nat Goodspeed
fiber.lua goes beyond coro.lua in that it distinguishes ready suspended coroutines from waiting suspended coroutines, and presents a rudimentary scheduler in fiber.yield(). yield() can determine that when all coroutines are waiting, it's time to retrieve the next incoming event from the viewer. Moreover, it can detect when all coroutines have completed and exit without being explicitly told. fiber.launch() associates a name with each fiber for debugging purposes. fiber.get_name() retrieves the name of the specified fiber, or the running fiber. fiber.status() is like coroutine.status(), but can return 'ready' or 'waiting' instead of 'suspended'. fiber.yield() leaves the calling fiber ready, but lets other ready fibers run. fiber.wait() suspends the calling fiber and lets other ready fibers run. fiber.wake(), called from some other coroutine, returns the passed fiber to ready status for a future call to fiber.yield(). fiber.run() drives the scheduler to run all fibers to completion. If, on completion of the subject Lua script, LuaState::expr() detects that the script loaded fiber.lua, it calls fiber.run() to finish running any dangling fibers. This lets a script make calls to fiber.launch() and then just fall off the end, leaving the implicit fiber.run() call to run them all. fiber.lua is designed to allow the main thread, as well as explicitly launched coroutines, to make leap.request() calls. This part still needs debugging. The leap.lua module now configures a fiber.set_idle() function that honors leap.done(), but calls get_event_next() and dispatches the next incoming event. leap.request() and generate() now leave the reqid stamp in the response. This lets a caller handle subsequent events with the same reqid, e.g. for LLLuaFloater. Remove leap.process(): it has been superseded by fiber.run(). Remove leap.WaitFor:iterate(): unfortunately that would run afoul of the Luau bug that prevents suspending the calling coroutine within a generic 'for' iterator function. Make leap.lua use weak tables to track WaitFor objects. Make WaitQueue:Dequeue() call fiber.wait() to suspend its caller when the queue is empty, and Enqueue() call fiber.wake() to set it ready again when a new item is pushed. Make llluamanager_test.cpp's leap test script use the fiber module to launch coroutines, instead of the coro module. Fix a bug in which its drain() function was inadvertently setting and testing the global 'item' variable instead of one local to the function. Since some other modules had the same bug, it was getting confused. Also add printf.lua, providing a printf() function. printf() is short for print(string.format()), but it can also print tables: anything not a number or string is formatted using the inspect() function. Clean up some LL_DEBUGS() output left over from debugging lua_tollsd().
2024-03-14Fix a bug in leap.generate().Nat Goodspeed
We weren't passing the WaitForReqid instance to WaitForReqid:wait(). Also remove 'reqid' from responses returned by leap.request() and generate().
2024-03-13Fix minor bugs. Sprinkle in commented-out diagnostic output.Nat Goodspeed
2024-03-11Polish up leap.lua to make it pass tests.Nat Goodspeed
Add usage comments at the top. Add leap.done() function. Make leap.process() honor leap.done(), also recognize an incoming nil from the viewer to mean it's all done. Support leap.WaitFor with nil priority to mean "don't self-enable." This obviates leap.WaitForReqid:enable() and disable() overrides that do nothing. Add diagnostic logging.
2024-03-07Finish adding leap.WaitFor and WaitForReqid. Untested.Nat Goodspeed
2024-03-06WIP: Unfinished Queue.lua, WaitQueue.lua, ErrorQueue.lua, leap.lua.Nat Goodspeed
Also qtest.lua to exercise the queue classes and inspect.lua (from https://github.com/kikito/inspect.lua) for debugging.