aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wild <mwild1@gmail.com>2013-08-13 21:26:53 +0100
committerMatthew Wild <mwild1@gmail.com>2013-08-13 21:26:53 +0100
commit754483ceb68c6d2a86f2e9a7d704bb1489b09ebd (patch)
treed14734ff92907666cfa2897b4ee6982e9b6f5003
parent025419a40efd66d65805e9c1f1350ede6178a3a8 (diff)
downloadprosody-754483ceb68c6d2a86f2e9a7d704bb1489b09ebd.tar.gz
prosody-754483ceb68c6d2a86f2e9a7d704bb1489b09ebd.zip
util.async: Add guarder method, to create guards to ensure only a single runner can pass through a section of code at a time
-rw-r--r--util/async.lua38
1 files changed, 37 insertions, 1 deletions
diff --git a/util/async.lua b/util/async.lua
index 8af8730f..32ed0542 100644
--- a/util/async.lua
+++ b/util/async.lua
@@ -43,6 +43,42 @@ local function waiter(num)
end;
end
+function guarder()
+ local guards = {};
+ return function (id, func)
+ local thread = coroutine.running();
+ if not thread then
+ error("Not running in an async context, see http://prosody.im/doc/developers/async");
+ end
+ local guard = guards[id];
+ if not guard then
+ guard = {};
+ guards[id] = guard;
+ log("debug", "New guard!");
+ else
+ table.insert(guard, thread);
+ log("debug", "Guarded. %d threads waiting.", #guard)
+ coroutine.yield("wait");
+ end
+ local function exit()
+ local next_waiting = table.remove(guard, 1);
+ if next_waiting then
+ log("debug", "guard: Executing next waiting thread (%d left)", #guard)
+ runner_continue(next_waiting);
+ else
+ log("debug", "Guard off duty.")
+ guards[id] = nil;
+ end
+ end
+ if func then
+ func();
+ exit();
+ return;
+ end
+ return exit;
+ end;
+end
+
local runner_mt = {};
runner_mt.__index = runner_mt;
@@ -119,4 +155,4 @@ function runner_mt:enqueue(input)
table.insert(self.queue, input);
end
-return { waiter = waiter, runner = runner };
+return { waiter = waiter, guarder = guarder, runner = runner };