Mercurial > prosody-hg
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 |
| parents | 66c3ad5d29ad |
| children | 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 }; |
