aboutsummaryrefslogtreecommitdiffstats
path: root/util/async.lua
diff options
context:
space:
mode:
Diffstat (limited to 'util/async.lua')
-rw-r--r--util/async.lua48
1 files changed, 45 insertions, 3 deletions
diff --git a/util/async.lua b/util/async.lua
index 20397785..ece589cb 100644
--- a/util/async.lua
+++ b/util/async.lua
@@ -11,6 +11,12 @@ local function checkthread()
return thread;
end
+-- Configurable functions
+local schedule_task = nil; -- schedule_task(seconds, callback)
+local next_tick = function (f)
+ f();
+end
+
local function runner_from_thread(thread)
local level = 0;
-- Find the 'level' of the top-most function (0 == current level, 1 == caller, ...)
@@ -53,14 +59,16 @@ local function runner_continue(thread)
return false;
end
call_watcher(runner, "error", debug.traceback(thread, err));
- runner.state, runner.thread = "ready", nil;
+ runner.state = "ready";
return runner:run();
elseif state == "ready" then
-- If state is 'ready', it is our responsibility to update runner.state from 'waiting'.
-- We also have to :run(), because the queue might have further items that will not be
-- processed otherwise. FIXME: It's probably best to do this in a nexttick (0 timer).
- runner.state = "ready";
- runner:run();
+ next_tick(function ()
+ runner.state = "ready";
+ runner:run();
+ end);
end
return true;
end
@@ -118,6 +126,15 @@ local function guarder()
end;
end
+local function sleep(seconds)
+ if not schedule_task then
+ error("async.sleep() is not available - configure schedule function");
+ end
+ local wait, done = waiter();
+ schedule_task(seconds, done);
+ wait();
+end
+
local runner_mt = {};
runner_mt.__index = runner_mt;
@@ -159,6 +176,10 @@ function runner_mt:run(input)
local q, thread = self.queue, self.thread;
if not thread or coroutine.status(thread) == "dead" then
+ --luacheck: ignore 143/coroutine
+ if thread and coroutine.close then
+ coroutine.close(thread);
+ end
self:log("debug", "creating new coroutine");
-- Create a new coroutine for this runner
thread = runner_create_thread(self.func, self);
@@ -246,9 +267,30 @@ local function ready()
return pcall(checkthread);
end
+local function wait_for(promise)
+ local async_wait, async_done = waiter();
+ local ret, err = nil, nil;
+ promise:next(
+ function (r) ret = r; end,
+ function (e) err = e; end)
+ :finally(async_done);
+ async_wait();
+ if ret then
+ return ret;
+ else
+ return nil, err;
+ end
+end
+
return {
ready = ready;
waiter = waiter;
guarder = guarder;
runner = runner;
+ wait = wait_for; -- COMPAT w/trunk pre-0.12
+ wait_for = wait_for;
+ sleep = sleep;
+
+ set_nexttick = function(new_next_tick) next_tick = new_next_tick; end;
+ set_schedule_function = function (new_schedule_function) schedule_task = new_schedule_function; end;
};