aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--spec/util_async_spec.lua46
-rw-r--r--util/async.lua10
2 files changed, 54 insertions, 2 deletions
diff --git a/spec/util_async_spec.lua b/spec/util_async_spec.lua
index 435a844c..77afd1fc 100644
--- a/spec/util_async_spec.lua
+++ b/spec/util_async_spec.lua
@@ -669,4 +669,50 @@ describe("util.async", function()
assert.spy(r.watchers.ready).was.called();
end);
end);
+
+ describe("#set_nexttick()", function ()
+ after_each(function ()
+ -- Restore to default
+ async.set_nexttick(nil);
+ end);
+ it("should work", function ()
+ local queue = {};
+ local nexttick = spy.new(function (f)
+ assert.is_function(f);
+ table.insert(queue, f);
+ end);
+ async.set_nexttick(nexttick);
+
+ local processed_item;
+ local wait, done;
+ local r = new(function (item)
+ wait, done = async.waiter();
+ wait();
+ processed_item = item;
+ end);
+ r:run("test");
+
+ -- Nothing happened, because the runner is waiting
+ assert.is_nil(processed_item);
+ assert.equal(r.state, "waiting");
+ assert.spy(nexttick).was_called(0);
+ assert.spy(r.watchers.waiting).was.called();
+ assert.spy(r.watchers.ready).was_not.called();
+
+ -- Mark the runner as ready, it should be scheduled for
+ -- the next tick
+ done();
+
+ assert.spy(nexttick).was_called(1);
+ assert.spy(nexttick).was_called_with(match.is_function());
+ assert.equal(1, #queue);
+
+ -- Pretend it's the next tick - call the pending function
+ queue[1]();
+
+ assert.equal(processed_item, "test");
+ assert.equal(r.state, "ready");
+ assert.spy(r.watchers.ready).was.called();
+ end);
+ end);
end);
diff --git a/util/async.lua b/util/async.lua
index 551a5e5c..ece589cb 100644
--- a/util/async.lua
+++ b/util/async.lua
@@ -13,6 +13,9 @@ 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;
@@ -62,8 +65,10 @@ local function runner_continue(thread)
-- 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
@@ -286,5 +291,6 @@ return {
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;
};