Comparison

util/async.lua @ 5796:0b66cb959161

util.async: Add guarder method, to create guards to ensure only a single runner can pass through a section of code at a time
author Matthew Wild <mwild1@gmail.com>
date Tue, 13 Aug 2013 21:26:53 +0100
parent 5794:66c3ad5d29ad
child 5797:a493b79cfad0
comparison
equal deleted inserted replaced
5795:47c2f71d8314 5796:0b66cb959161
38 if num == 0 and waiting then 38 if num == 0 and waiting then
39 runner_continue(thread); 39 runner_continue(thread);
40 elseif num < 0 then 40 elseif num < 0 then
41 error("done() called too many times"); 41 error("done() called too many times");
42 end 42 end
43 end;
44 end
45
46 function guarder()
47 local guards = {};
48 return function (id, func)
49 local thread = coroutine.running();
50 if not thread then
51 error("Not running in an async context, see http://prosody.im/doc/developers/async");
52 end
53 local guard = guards[id];
54 if not guard then
55 guard = {};
56 guards[id] = guard;
57 log("debug", "New guard!");
58 else
59 table.insert(guard, thread);
60 log("debug", "Guarded. %d threads waiting.", #guard)
61 coroutine.yield("wait");
62 end
63 local function exit()
64 local next_waiting = table.remove(guard, 1);
65 if next_waiting then
66 log("debug", "guard: Executing next waiting thread (%d left)", #guard)
67 runner_continue(next_waiting);
68 else
69 log("debug", "Guard off duty.")
70 guards[id] = nil;
71 end
72 end
73 if func then
74 func();
75 exit();
76 return;
77 end
78 return exit;
43 end; 79 end;
44 end 80 end
45 81
46 local runner_mt = {}; 82 local runner_mt = {};
47 runner_mt.__index = runner_mt; 83 runner_mt.__index = runner_mt;
117 153
118 function runner_mt:enqueue(input) 154 function runner_mt:enqueue(input)
119 table.insert(self.queue, input); 155 table.insert(self.queue, input);
120 end 156 end
121 157
122 return { waiter = waiter, runner = runner }; 158 return { waiter = waiter, guarder = guarder, runner = runner };