diff options
Diffstat (limited to 'util/async.lua')
-rw-r--r-- | util/async.lua | 48 |
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; }; |