diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/scripts/lua/ErrorQueue.lua | 4 | ||||
-rw-r--r-- | indra/newview/scripts/lua/WaitQueue.lua | 2 | ||||
-rw-r--r-- | indra/newview/scripts/lua/fiber.lua | 42 | ||||
-rw-r--r-- | indra/newview/scripts/lua/leap.lua | 9 | ||||
-rw-r--r-- | indra/newview/tests/llluamanager_test.cpp | 2 |
5 files changed, 32 insertions, 27 deletions
diff --git a/indra/newview/scripts/lua/ErrorQueue.lua b/indra/newview/scripts/lua/ErrorQueue.lua index a6d4470044..076742815a 100644 --- a/indra/newview/scripts/lua/ErrorQueue.lua +++ b/indra/newview/scripts/lua/ErrorQueue.lua @@ -3,18 +3,22 @@ -- raise that error. local WaitQueue = require('WaitQueue') +-- local debug = require('printf') +local function debug(...) end local ErrorQueue = WaitQueue:new() function ErrorQueue:Error(message) -- Setting Error() is a marker, like closing the queue. Once we reach the -- error, every subsequent Dequeue() call will raise the same error. + debug('Setting self._closed to %q', message) self._closed = message self:_wake_waiters() end function ErrorQueue:Dequeue() local value = WaitQueue.Dequeue(self) + debug('ErrorQueue:Dequeue: base Dequeue() got %s', value) if value ~= nil then -- queue not yet closed, show caller return value diff --git a/indra/newview/scripts/lua/WaitQueue.lua b/indra/newview/scripts/lua/WaitQueue.lua index b15e9c443b..f69baff09b 100644 --- a/indra/newview/scripts/lua/WaitQueue.lua +++ b/indra/newview/scripts/lua/WaitQueue.lua @@ -38,7 +38,7 @@ function WaitQueue:_wake_waiters() -- Unlike OS threads, with cooperative concurrency it doesn't make sense -- to "notify all": we need wake only one of the waiting Dequeue() -- callers. - if not self:IsEmpty() and next(self._waiters) then + if ((not self:IsEmpty()) or self._closed) and next(self._waiters) then -- Pop the oldest waiting coroutine instead of the most recent, for -- more-or-less round robin fairness. But skip any coroutines that -- have gone dead in the meantime. diff --git a/indra/newview/scripts/lua/fiber.lua b/indra/newview/scripts/lua/fiber.lua index f18d133cc8..8ed99f12b7 100644 --- a/indra/newview/scripts/lua/fiber.lua +++ b/indra/newview/scripts/lua/fiber.lua @@ -104,13 +104,7 @@ end -- Query a fiber's name (nil for the running fiber) function fiber.get_name(co) - if not co then - co = fiber.running() - end - if not names[co] then - return 'unknown' - end - return names[co] + return names[co or fiber.running()] or 'unknown' end -- Query status of the passed fiber @@ -140,10 +134,8 @@ function fiber.status(co) return 'waiting' end -- not waiting should imply ready: sanity check - for _, maybe in pairs(ready) do - if maybe == co then - return 'ready' - end + if table.find(ready, co) then + return 'ready' end -- Calls within yield() between popping the next ready fiber and -- re-appending it to the list are in this state. Once we're done @@ -158,11 +150,9 @@ local function set_waiting() -- if called from the main fiber, inject a 'main' marker into the list co = fiber.running() -- delete from ready list - for i, maybe in pairs(ready) do - if maybe == co then - table.remove(ready, i) - break - end + local i = table.find(ready, co) + if i then + table.remove(ready, i) end -- add to waiting list waiting[co] = true @@ -191,11 +181,16 @@ end -- Run fibers until all but main have terminated: return nil. -- Or until configured idle() callback returns x ~= nil: return x. function fiber.run() - -- A fiber calling run() is not also doing other useful work. Tell yield() - -- that we're waiting. Otherwise it would keep seeing that our caller is - -- ready and return to us, instead of realizing that all coroutines are - -- waiting and call idle(). - set_waiting() + -- A fiber calling run() is not also doing other useful work. Remove the + -- calling fiber from the ready list. Otherwise yield() would keep seeing + -- that our caller is ready and return to us, instead of realizing that + -- all coroutines are waiting and call idle(). But don't say we're + -- waiting, either, because then when all other fibers have terminated + -- we'd call idle() forever waiting for something to make us ready again. + local i = table.find(ready, fiber.running()) + if i then + table.remove(ready, i) + end local others, idle_done repeat debug('%s calling fiber.run() calling yield()', fiber.get_name()) @@ -204,9 +199,10 @@ function fiber.run() tostring(others), tostring(idle_done)) until (not others) debug('%s fiber.run() done', fiber.get_name()) - fiber.wake(fiber.running()) + -- For whatever it's worth, put our own fiber back in the ready list. + table.insert(ready, fiber.running()) -- Once there are no more waiting fibers, and the only ready fiber is - -- main, return to main. All previously-launched fibers are done. Possibly + -- us, return to caller. All previously-launched fibers are done. Possibly -- the chunk is done, or the chunk may decide to launch a new batch of -- fibers. return idle_done diff --git a/indra/newview/scripts/lua/leap.lua b/indra/newview/scripts/lua/leap.lua index 60e8266a76..77f3a3e116 100644 --- a/indra/newview/scripts/lua/leap.lua +++ b/indra/newview/scripts/lua/leap.lua @@ -198,10 +198,10 @@ end local function cleanup(message) -- we're done: clean up all pending coroutines for i, waitfor in pairs(leap._pending) do - waitfor:exception(message) + waitfor:close() end for i, waitfor in pairs(leap._waitfors) do - waitfor:exception(message) + waitfor:close() end end @@ -407,6 +407,11 @@ function leap.WaitFor:process(item) self._queue:Enqueue(item) end +-- called by cleanup() at end +function leap.WaitFor:close() + self._queue:close() +end + -- called by leap.process() when get_event_next() raises an error function leap.WaitFor:exception(message) print_warning(self.name .. ' error: ' .. message) diff --git a/indra/newview/tests/llluamanager_test.cpp b/indra/newview/tests/llluamanager_test.cpp index 1dd081fb98..d1beed84ef 100644 --- a/indra/newview/tests/llluamanager_test.cpp +++ b/indra/newview/tests/llluamanager_test.cpp @@ -361,8 +361,8 @@ namespace tut "fiber.launch('requester(a)', requester, 'a')\n" "-- requester(a)\n" "fiber.launch('requester(b)', requester, 'b')\n" + "fiber.run()\n" "-- fiber.print_all()\n" - "-- fiber.run()\n" ); LLSD requests; |