summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/scripts/lua/ErrorQueue.lua4
-rw-r--r--indra/newview/scripts/lua/WaitQueue.lua2
-rw-r--r--indra/newview/scripts/lua/fiber.lua42
-rw-r--r--indra/newview/scripts/lua/leap.lua9
-rw-r--r--indra/newview/tests/llluamanager_test.cpp2
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;