aboutsummaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/async.lua15
1 files changed, 15 insertions, 0 deletions
diff --git a/util/async.lua b/util/async.lua
index 7b2eae54..76da45fa 100644
--- a/util/async.lua
+++ b/util/async.lua
@@ -7,6 +7,8 @@ local function runner_continue(thread)
end
local ok, state, runner = coroutine.resume(thread);
if not ok then
+ -- Running the coroutine failed, which means we have to find the runner manually,
+ -- in order to inform the error handler
local level = 0;
while debug.getinfo(thread, level, "") do level = level + 1; end
ok, runner = debug.getlocal(thread, level-1, 1);
@@ -99,37 +101,48 @@ local function runner(func, watchers, data)
, runner_mt);
end
+-- Add a task item for the runner to process
function runner_mt:run(input)
if input ~= nil then
table.insert(self.queue, input);
end
if self.state ~= "ready" then
+ -- The runner is busy. Indicate that the task item has been
+ -- queued, and return information about the current runner state
return true, self.state, #self.queue;
end
local q, thread = self.queue, self.thread;
if not thread or coroutine.status(thread) == "dead" then
+ -- Create a new coroutine for this runner
thread = runner_create_thread(self.func, self);
self.thread = thread;
end
+ -- Process task item(s) while the queue is not empty, and we're not blocked
local n, state, err = #q, self.state, nil;
self.state = "running";
while n > 0 and state == "ready" do
local consumed;
+ -- Loop through queue items, and attempt to run them
for i = 1,n do
local input = q[i];
local ok, new_state = coroutine.resume(thread, input);
if not ok then
+ -- There was an error running the coroutine, save the error, mark runner as ready to begin again
consumed, state, err = i, "ready", debug.traceback(thread, new_state);
self.thread = nil;
break;
elseif new_state == "wait" then
+ -- Runner is blocked on waiting for a task item to complete
consumed, state = i, "waiting";
break;
end
end
+ -- Loop ended - either queue empty because all tasks passed without blocking (consumed == nil)
+ -- or runner is blocked/errored, and consumed will contain the number of tasks processed so far
if not consumed then consumed = n; end
+ -- Remove consumed items from the queue array
if q[n+1] ~= nil then
n = #q;
end
@@ -138,6 +151,7 @@ function runner_mt:run(input)
end
n = #q;
end
+ -- Runner processed all items it can, so save current runner state
self.state = state;
if err or state ~= self.notified_state then
if err then
@@ -151,6 +165,7 @@ function runner_mt:run(input)
return true, state, n;
end
+-- Add a task item to the queue without invoking the runner, even if it is idle
function runner_mt:enqueue(input)
table.insert(self.queue, input);
end