Merge 0.10->trunk
[prosody.git] / util / async.lua
index 8af8730f891d0b7ee648e96c7b477f9818a6e9fd..968ec80495489b51b66a8e1e1ba6f8c201b7e14d 100644 (file)
@@ -43,6 +43,42 @@ local function waiter(num)
        end;
 end
 
+local 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 };