diff options
author | Matthew Wild <mwild1@gmail.com> | 2013-08-13 21:26:53 +0100 |
---|---|---|
committer | Matthew Wild <mwild1@gmail.com> | 2013-08-13 21:26:53 +0100 |
commit | 14f85f2f4e06a46fd46bd33bbfb23ad642ec01fd (patch) | |
tree | d14734ff92907666cfa2897b4ee6982e9b6f5003 | |
parent | de0f19e1af3ce580229dfad3ab15bf5600369d38 (diff) | |
download | prosody-14f85f2f4e06a46fd46bd33bbfb23ad642ec01fd.tar.gz prosody-14f85f2f4e06a46fd46bd33bbfb23ad642ec01fd.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.lua | 38 |
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 }; |