Software /
code /
prosody
Annotate
util/async.lua @ 13073:9e5802b45b9e
mod_tokenauth: Only check if expiry of expiring tokens
Some tokens, e.g. OAuth2 refresh tokens, might not have their lifetime
explicitly bounded here, but rather be bounded by the lifetime of
something else, like the OAuth2 client.
Open question: Would it be better to enforce a lifetime on all tokens?
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Wed, 12 Apr 2023 10:21:32 +0200 |
parent | 12975:d10957394a3c |
rev | line source |
---|---|
12975
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12310
diff
changeset
|
1 local logger = require "prosody.util.logger"; |
8788
7a9b680a79fb
util.async: Move runner id into log tag
Kim Alvefur <zash@zash.se>
parents:
8766
diff
changeset
|
2 local log = logger.init("util.async"); |
12975
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12310
diff
changeset
|
3 local new_id = require "prosody.util.id".short; |
d10957394a3c
util: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents:
12310
diff
changeset
|
4 local xpcall = require "prosody.util.xpcall".xpcall; |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
5 |
8407
f652e1ea2f69
util.async: Factor out thread check into a function
Kim Alvefur <zash@zash.se>
parents:
8237
diff
changeset
|
6 local function checkthread() |
8408
b751bee6a829
util.async: Fix thread check to work correctly in Lua 5.2
Kim Alvefur <zash@zash.se>
parents:
8407
diff
changeset
|
7 local thread, main = coroutine.running(); |
b751bee6a829
util.async: Fix thread check to work correctly in Lua 5.2
Kim Alvefur <zash@zash.se>
parents:
8407
diff
changeset
|
8 if not thread or main then |
8407
f652e1ea2f69
util.async: Factor out thread check into a function
Kim Alvefur <zash@zash.se>
parents:
8237
diff
changeset
|
9 error("Not running in an async context, see https://prosody.im/doc/developers/util/async"); |
f652e1ea2f69
util.async: Factor out thread check into a function
Kim Alvefur <zash@zash.se>
parents:
8237
diff
changeset
|
10 end |
f652e1ea2f69
util.async: Factor out thread check into a function
Kim Alvefur <zash@zash.se>
parents:
8237
diff
changeset
|
11 return thread; |
f652e1ea2f69
util.async: Factor out thread check into a function
Kim Alvefur <zash@zash.se>
parents:
8237
diff
changeset
|
12 end |
f652e1ea2f69
util.async: Factor out thread check into a function
Kim Alvefur <zash@zash.se>
parents:
8237
diff
changeset
|
13 |
11961
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
14 -- Configurable functions |
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
15 local schedule_task = nil; -- schedule_task(seconds, callback) |
11962
9a70a543c727
util.async: Add next-tick configuration
Matthew Wild <mwild1@gmail.com>
parents:
11961
diff
changeset
|
16 local next_tick = function (f) |
9a70a543c727
util.async: Add next-tick configuration
Matthew Wild <mwild1@gmail.com>
parents:
11961
diff
changeset
|
17 f(); |
9a70a543c727
util.async: Add next-tick configuration
Matthew Wild <mwild1@gmail.com>
parents:
11961
diff
changeset
|
18 end |
11961
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
19 |
8627
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
20 local function runner_from_thread(thread) |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
21 local level = 0; |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
22 -- Find the 'level' of the top-most function (0 == current level, 1 == caller, ...) |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
23 while debug.getinfo(thread, level, "") do level = level + 1; end |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
24 local name, runner = debug.getlocal(thread, level-1, 1); |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
25 if name ~= "self" or type(runner) ~= "table" or runner.thread ~= thread then |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
26 return nil; |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
27 end |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
28 return runner; |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
29 end |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
30 |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
31 local function call_watcher(runner, watcher_name, ...) |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
32 local watcher = runner.watchers[watcher_name]; |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
33 if not watcher then |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
34 return false; |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
35 end |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
36 runner:log("debug", "Calling '%s' watcher", watcher_name); |
9562
acf74ad0b795
Many things: switch from hacky multi-arg xpcall implementations to a standard util.xpcall
Matthew Wild <mwild1@gmail.com>
parents:
9177
diff
changeset
|
37 local ok, err = xpcall(watcher, debug.traceback, runner, ...); |
8627
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
38 if not ok then |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
39 runner:log("error", "Error in '%s' watcher: %s", watcher_name, err); |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
40 return nil, err; |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
41 end |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
42 return true; |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
43 end |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
44 |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
45 local function runner_continue(thread) |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
46 -- ASSUMPTION: runner is in 'waiting' state (but we don't have the runner to know for sure) |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
47 if coroutine.status(thread) ~= "suspended" then -- This should suffice |
8629
ddb04cacb8b1
util.async: Bump log warnings to error level
Matthew Wild <mwild1@gmail.com>
parents:
8627
diff
changeset
|
48 log("error", "unexpected async state: thread not suspended"); |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
49 return false; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
50 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
51 local ok, state, runner = coroutine.resume(thread); |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
52 if not ok then |
8609
9f6ab206d741
util.async: Ensure runner is left in correct state after out-of-main-loop error (+tests)
Matthew Wild <mwild1@gmail.com>
parents:
8604
diff
changeset
|
53 local err = state; |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
54 -- Running the coroutine failed, which means we have to find the runner manually, |
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
55 -- in order to inform the error handler |
8627
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
56 runner = runner_from_thread(thread); |
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
57 if not runner then |
8629
ddb04cacb8b1
util.async: Bump log warnings to error level
Matthew Wild <mwild1@gmail.com>
parents:
8627
diff
changeset
|
58 log("error", "unexpected async state: unable to locate runner during error handling"); |
8613
dbb4788db8e3
util.async: Convert asserts to a return false (same as other unexpected behaviour)
Matthew Wild <mwild1@gmail.com>
parents:
8611
diff
changeset
|
59 return false; |
dbb4788db8e3
util.async: Convert asserts to a return false (same as other unexpected behaviour)
Matthew Wild <mwild1@gmail.com>
parents:
8611
diff
changeset
|
60 end |
8627
24b59a62acce
util.async: Split runner_continue into smaller functions for easier testing and safety
Matthew Wild <mwild1@gmail.com>
parents:
8625
diff
changeset
|
61 call_watcher(runner, "error", debug.traceback(thread, err)); |
10930
69a4b0e3565f
util.async: Call coroutine.close() on dead threads (Lua 5.4)
Matthew Wild <mwild1@gmail.com>
parents:
10928
diff
changeset
|
62 runner.state = "ready"; |
8616
a15c891c6232
util.async: ensure change in e77b37de482e applies after out-of-loop resume also
Matthew Wild <mwild1@gmail.com>
parents:
8615
diff
changeset
|
63 return runner:run(); |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
64 elseif state == "ready" then |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
65 -- If state is 'ready', it is our responsibility to update runner.state from 'waiting'. |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
66 -- We also have to :run(), because the queue might have further items that will not be |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
67 -- processed otherwise. FIXME: It's probably best to do this in a nexttick (0 timer). |
11962
9a70a543c727
util.async: Add next-tick configuration
Matthew Wild <mwild1@gmail.com>
parents:
11961
diff
changeset
|
68 next_tick(function () |
9a70a543c727
util.async: Add next-tick configuration
Matthew Wild <mwild1@gmail.com>
parents:
11961
diff
changeset
|
69 runner.state = "ready"; |
9a70a543c727
util.async: Add next-tick configuration
Matthew Wild <mwild1@gmail.com>
parents:
11961
diff
changeset
|
70 runner:run(); |
9a70a543c727
util.async: Add next-tick configuration
Matthew Wild <mwild1@gmail.com>
parents:
11961
diff
changeset
|
71 end); |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
72 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
73 return true; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
74 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
75 |
12310
91af1697ddd8
util.async: Optionally allow too many 'done' callbacks
Kim Alvefur <zash@zash.se>
parents:
11962
diff
changeset
|
76 local function waiter(num, allow_many) |
8407
f652e1ea2f69
util.async: Factor out thread check into a function
Kim Alvefur <zash@zash.se>
parents:
8237
diff
changeset
|
77 local thread = checkthread(); |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
78 num = num or 1; |
5792
aac4c6147647
util.async: waiter: Remove restriction about wait() being called before done()
Matthew Wild <mwild1@gmail.com>
parents:
5791
diff
changeset
|
79 local waiting; |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
80 return function () |
5792
aac4c6147647
util.async: waiter: Remove restriction about wait() being called before done()
Matthew Wild <mwild1@gmail.com>
parents:
5791
diff
changeset
|
81 if num == 0 then return; end -- already done |
aac4c6147647
util.async: waiter: Remove restriction about wait() being called before done()
Matthew Wild <mwild1@gmail.com>
parents:
5791
diff
changeset
|
82 waiting = true; |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
83 coroutine.yield("wait"); |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
84 end, function () |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
85 num = num - 1; |
5792
aac4c6147647
util.async: waiter: Remove restriction about wait() being called before done()
Matthew Wild <mwild1@gmail.com>
parents:
5791
diff
changeset
|
86 if num == 0 and waiting then |
aac4c6147647
util.async: waiter: Remove restriction about wait() being called before done()
Matthew Wild <mwild1@gmail.com>
parents:
5791
diff
changeset
|
87 runner_continue(thread); |
12310
91af1697ddd8
util.async: Optionally allow too many 'done' callbacks
Kim Alvefur <zash@zash.se>
parents:
11962
diff
changeset
|
88 elseif not allow_many and num < 0 then |
5793
e8c79796ead9
util.async: waiter: Throw error if done() called too many times
Kim Alvefur <zash@zash.se>
parents:
5792
diff
changeset
|
89 error("done() called too many times"); |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
90 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
91 end; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
92 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
93 |
5797
a493b79cfad0
util.async: Make guarder() local
Matthew Wild <mwild1@gmail.com>
parents:
5796
diff
changeset
|
94 local function guarder() |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
95 local guards = {}; |
8655
ba6a6a04b46c
util.async: Allow nil as a guard key
Matthew Wild <mwild1@gmail.com>
parents:
8651
diff
changeset
|
96 local default_id = {}; |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
97 return function (id, func) |
8655
ba6a6a04b46c
util.async: Allow nil as a guard key
Matthew Wild <mwild1@gmail.com>
parents:
8651
diff
changeset
|
98 id = id or default_id; |
8407
f652e1ea2f69
util.async: Factor out thread check into a function
Kim Alvefur <zash@zash.se>
parents:
8237
diff
changeset
|
99 local thread = checkthread(); |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
100 local guard = guards[id]; |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
101 if not guard then |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
102 guard = {}; |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
103 guards[id] = guard; |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
104 log("debug", "New guard!"); |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
105 else |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
106 table.insert(guard, thread); |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
107 log("debug", "Guarded. %d threads waiting.", #guard) |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
108 coroutine.yield("wait"); |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
109 end |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
110 local function exit() |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
111 local next_waiting = table.remove(guard, 1); |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
112 if next_waiting then |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
113 log("debug", "guard: Executing next waiting thread (%d left)", #guard) |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
114 runner_continue(next_waiting); |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
115 else |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
116 log("debug", "Guard off duty.") |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
117 guards[id] = nil; |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
118 end |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
119 end |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
120 if func then |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
121 func(); |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
122 exit(); |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
123 return; |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
124 end |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
125 return exit; |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
126 end; |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
127 end |
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
Matthew Wild <mwild1@gmail.com>
parents:
5794
diff
changeset
|
128 |
11961
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
129 local function sleep(seconds) |
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
130 if not schedule_task then |
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
131 error("async.sleep() is not available - configure schedule function"); |
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
132 end |
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
133 local wait, done = waiter(); |
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
134 schedule_task(seconds, done); |
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
135 wait(); |
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
136 end |
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
137 |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
138 local runner_mt = {}; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
139 runner_mt.__index = runner_mt; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
140 |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
141 local function runner_create_thread(func, self) |
7725
f928695a2af1
util.async: Add annotation to ignore warning [luacheck]
Kim Alvefur <zash@zash.se>
parents:
7724
diff
changeset
|
142 local thread = coroutine.create(function (self) -- luacheck: ignore 432/self |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
143 while true do |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
144 func(coroutine.yield("ready", self)); |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
145 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
146 end); |
8927
ed0891383e78
util.async: Copy hooks from main thread into coroutines
Matthew Wild <mwild1@gmail.com>
parents:
8788
diff
changeset
|
147 debug.sethook(thread, debug.gethook()); |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
148 assert(coroutine.resume(thread, self)); -- Start it up, it will return instantly to wait for the first input |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
149 return thread; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
150 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
151 |
8681
0c077800cd70
util.async: Make parameters to async.runner() optional
Matthew Wild <mwild1@gmail.com>
parents:
8669
diff
changeset
|
152 local function default_error_watcher(runner, err) |
0c077800cd70
util.async: Make parameters to async.runner() optional
Matthew Wild <mwild1@gmail.com>
parents:
8669
diff
changeset
|
153 runner:log("error", "Encountered error: %s", err); |
0c077800cd70
util.async: Make parameters to async.runner() optional
Matthew Wild <mwild1@gmail.com>
parents:
8669
diff
changeset
|
154 error(err); |
0c077800cd70
util.async: Make parameters to async.runner() optional
Matthew Wild <mwild1@gmail.com>
parents:
8669
diff
changeset
|
155 end |
0c077800cd70
util.async: Make parameters to async.runner() optional
Matthew Wild <mwild1@gmail.com>
parents:
8669
diff
changeset
|
156 local function default_func(f) f(); end |
5790
959163e4d631
util.async: Make functions local
Matthew Wild <mwild1@gmail.com>
parents:
5788
diff
changeset
|
157 local function runner(func, watchers, data) |
8788
7a9b680a79fb
util.async: Move runner id into log tag
Kim Alvefur <zash@zash.se>
parents:
8766
diff
changeset
|
158 local id = new_id(); |
7a9b680a79fb
util.async: Move runner id into log tag
Kim Alvefur <zash@zash.se>
parents:
8766
diff
changeset
|
159 local _log = logger.init("runner" .. id); |
8681
0c077800cd70
util.async: Make parameters to async.runner() optional
Matthew Wild <mwild1@gmail.com>
parents:
8669
diff
changeset
|
160 return setmetatable({ func = func or default_func, thread = false, state = "ready", notified_state = "ready", |
8788
7a9b680a79fb
util.async: Move runner id into log tag
Kim Alvefur <zash@zash.se>
parents:
8766
diff
changeset
|
161 queue = {}, watchers = watchers or { error = default_error_watcher }, data = data, id = id, _log = _log; } |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
162 , runner_mt); |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
163 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
164 |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
165 -- Add a task item for the runner to process |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
166 function runner_mt:run(input) |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
167 if input ~= nil then |
8602
9901deadc068
util.async: Fix order of statements so queue count makes more sense
Matthew Wild <mwild1@gmail.com>
parents:
8601
diff
changeset
|
168 table.insert(self.queue, input); |
8976
92f0876b9230
MUC: Add config option to allow members to invite other members to the room (previously only owners/admins could do this)
Matthew Wild <mwild1@gmail.com>
parents:
8927
diff
changeset
|
169 --self:log("debug", "queued new work item, %d items queued", #self.queue); |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
170 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
171 if self.state ~= "ready" then |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
172 -- The runner is busy. Indicate that the task item has been |
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
173 -- queued, and return information about the current runner state |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
174 return true, self.state, #self.queue; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
175 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
176 |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
177 local q, thread = self.queue, self.thread; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
178 if not thread or coroutine.status(thread) == "dead" then |
10930
69a4b0e3565f
util.async: Call coroutine.close() on dead threads (Lua 5.4)
Matthew Wild <mwild1@gmail.com>
parents:
10928
diff
changeset
|
179 --luacheck: ignore 143/coroutine |
10931
558f0555ba02
util.async: Don't attempt to close thread if not created yet
Matthew Wild <mwild1@gmail.com>
parents:
10930
diff
changeset
|
180 if thread and coroutine.close then |
10930
69a4b0e3565f
util.async: Call coroutine.close() on dead threads (Lua 5.4)
Matthew Wild <mwild1@gmail.com>
parents:
10928
diff
changeset
|
181 coroutine.close(thread); |
69a4b0e3565f
util.async: Call coroutine.close() on dead threads (Lua 5.4)
Matthew Wild <mwild1@gmail.com>
parents:
10928
diff
changeset
|
182 end |
8600
96f20cf92b84
util.async: Add per-runner ids and add runner:log() method
Matthew Wild <mwild1@gmail.com>
parents:
8408
diff
changeset
|
183 self:log("debug", "creating new coroutine"); |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
184 -- Create a new coroutine for this runner |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
185 thread = runner_create_thread(self.func, self); |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
186 self.thread = thread; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
187 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
188 |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
189 -- Process task item(s) while the queue is not empty, and we're not blocked |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
190 local n, state, err = #q, self.state, nil; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
191 self.state = "running"; |
8976
92f0876b9230
MUC: Add config option to allow members to invite other members to the room (previously only owners/admins could do this)
Matthew Wild <mwild1@gmail.com>
parents:
8927
diff
changeset
|
192 --self:log("debug", "running main loop"); |
8603
dc5f3302a642
util.async: Bugfix, don't continue main loop while there is a pending error
Matthew Wild <mwild1@gmail.com>
parents:
8602
diff
changeset
|
193 while n > 0 and state == "ready" and not err do |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
194 local consumed; |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
195 -- Loop through queue items, and attempt to run them |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
196 for i = 1,n do |
7724
20a69ef5570c
util.async: Rename variable to avoid name clash [luacheck]
Kim Alvefur <zash@zash.se>
parents:
7436
diff
changeset
|
197 local queued_input = q[i]; |
20a69ef5570c
util.async: Rename variable to avoid name clash [luacheck]
Kim Alvefur <zash@zash.se>
parents:
7436
diff
changeset
|
198 local ok, new_state = coroutine.resume(thread, queued_input); |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
199 if not ok then |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
200 -- There was an error running the coroutine, save the error, mark runner as ready to begin again |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
201 consumed, state, err = i, "ready", debug.traceback(thread, new_state); |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
202 self.thread = nil; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
203 break; |
5791
2c98061b6b1e
util.async: runner: Fix check for new state to recognise transition to 'waiting'
Matthew Wild <mwild1@gmail.com>
parents:
5790
diff
changeset
|
204 elseif new_state == "wait" then |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
205 -- Runner is blocked on waiting for a task item to complete |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
206 consumed, state = i, "waiting"; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
207 break; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
208 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
209 end |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
210 -- Loop ended - either queue empty because all tasks passed without blocking (consumed == nil) |
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
211 -- or runner is blocked/errored, and consumed will contain the number of tasks processed so far |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
212 if not consumed then consumed = n; end |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
213 -- Remove consumed items from the queue array |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
214 if q[n+1] ~= nil then |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
215 n = #q; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
216 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
217 for i = 1, n do |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
218 q[i] = q[consumed+i]; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
219 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
220 n = #q; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
221 end |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
222 -- Runner processed all items it can, so save current runner state |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
223 self.state = state; |
5794
66c3ad5d29ad
util.async: Fix logic bug that prevented error watcher being called for runners
Matthew Wild <mwild1@gmail.com>
parents:
5793
diff
changeset
|
224 if err or state ~= self.notified_state then |
8604
1c8c7fd259c8
util.async: Log the non-error state as well when there is an error being processed
Matthew Wild <mwild1@gmail.com>
parents:
8603
diff
changeset
|
225 self:log("debug", "changed state from %s to %s", self.notified_state, err and ("error ("..state..")") or state); |
5794
66c3ad5d29ad
util.async: Fix logic bug that prevented error watcher being called for runners
Matthew Wild <mwild1@gmail.com>
parents:
5793
diff
changeset
|
226 if err then |
66c3ad5d29ad
util.async: Fix logic bug that prevented error watcher being called for runners
Matthew Wild <mwild1@gmail.com>
parents:
5793
diff
changeset
|
227 state = "error" |
66c3ad5d29ad
util.async: Fix logic bug that prevented error watcher being called for runners
Matthew Wild <mwild1@gmail.com>
parents:
5793
diff
changeset
|
228 else |
66c3ad5d29ad
util.async: Fix logic bug that prevented error watcher being called for runners
Matthew Wild <mwild1@gmail.com>
parents:
5793
diff
changeset
|
229 self.notified_state = state; |
66c3ad5d29ad
util.async: Fix logic bug that prevented error watcher being called for runners
Matthew Wild <mwild1@gmail.com>
parents:
5793
diff
changeset
|
230 end |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
231 local handler = self.watchers[state]; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
232 if handler then handler(self, err); end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
233 end |
8615
e77b37de482e
util.async: Behaviour change: continue to process queued items after errors
Matthew Wild <mwild1@gmail.com>
parents:
8613
diff
changeset
|
234 if n > 0 then |
e77b37de482e
util.async: Behaviour change: continue to process queued items after errors
Matthew Wild <mwild1@gmail.com>
parents:
8613
diff
changeset
|
235 return self:run(); |
e77b37de482e
util.async: Behaviour change: continue to process queued items after errors
Matthew Wild <mwild1@gmail.com>
parents:
8613
diff
changeset
|
236 end |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
237 return true, state, n; |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
238 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
239 |
7436
649b89b2c840
util.async: Add some more comments for clarity
Matthew Wild <mwild1@gmail.com>
parents:
7359
diff
changeset
|
240 -- Add a task item to the queue without invoking the runner, even if it is idle |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
241 function runner_mt:enqueue(input) |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
242 table.insert(self.queue, input); |
8602
9901deadc068
util.async: Fix order of statements so queue count makes more sense
Matthew Wild <mwild1@gmail.com>
parents:
8601
diff
changeset
|
243 self:log("debug", "queued new work item, %d items queued", #self.queue); |
8766
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
244 return self; |
5788
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
245 end |
3556f338caa3
util.async: New library to provide support around coroutine-based non-blocking functions
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
246 |
8600
96f20cf92b84
util.async: Add per-runner ids and add runner:log() method
Matthew Wild <mwild1@gmail.com>
parents:
8408
diff
changeset
|
247 function runner_mt:log(level, fmt, ...) |
8788
7a9b680a79fb
util.async: Move runner id into log tag
Kim Alvefur <zash@zash.se>
parents:
8766
diff
changeset
|
248 return self._log(level, fmt, ...); |
8600
96f20cf92b84
util.async: Add per-runner ids and add runner:log() method
Matthew Wild <mwild1@gmail.com>
parents:
8408
diff
changeset
|
249 end |
96f20cf92b84
util.async: Add per-runner ids and add runner:log() method
Matthew Wild <mwild1@gmail.com>
parents:
8408
diff
changeset
|
250 |
8766
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
251 function runner_mt:onready(f) |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
252 self.watchers.ready = f; |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
253 return self; |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
254 end |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
255 |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
256 function runner_mt:onwaiting(f) |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
257 self.watchers.waiting = f; |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
258 return self; |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
259 end |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
260 |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
261 function runner_mt:onerror(f) |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
262 self.watchers.error = f; |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
263 return self; |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
264 end |
01264bc60c2b
util.async: Add helper methods for setting watchers
Matthew Wild <mwild1@gmail.com>
parents:
8685
diff
changeset
|
265 |
8648
ca710a71d730
util.async: Add ready() to check whether running in async context
Matthew Wild <mwild1@gmail.com>
parents:
8629
diff
changeset
|
266 local function ready() |
ca710a71d730
util.async: Add ready() to check whether running in async context
Matthew Wild <mwild1@gmail.com>
parents:
8629
diff
changeset
|
267 return pcall(checkthread); |
ca710a71d730
util.async: Add ready() to check whether running in async context
Matthew Wild <mwild1@gmail.com>
parents:
8629
diff
changeset
|
268 end |
ca710a71d730
util.async: Add ready() to check whether running in async context
Matthew Wild <mwild1@gmail.com>
parents:
8629
diff
changeset
|
269 |
10928
79faf5b98395
util.async: Rename wait -> wait_for (w/compat)
Matthew Wild <mwild1@gmail.com>
parents:
10291
diff
changeset
|
270 local function wait_for(promise) |
10291
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
271 local async_wait, async_done = waiter(); |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
272 local ret, err = nil, nil; |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
273 promise:next( |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
274 function (r) ret = r; end, |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
275 function (e) err = e; end) |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
276 :finally(async_done); |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
277 async_wait(); |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
278 if ret then |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
279 return ret; |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
280 else |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
281 return nil, err; |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
282 end |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
283 end |
7b48b620164c
util.async: Add function for waiting on promises and unpacking the results
Kim Alvefur <zash@zash.se>
parents:
9562
diff
changeset
|
284 |
8649
9246f64d6f1e
util.async: Add once() to create temporary runners
Matthew Wild <mwild1@gmail.com>
parents:
8648
diff
changeset
|
285 return { |
9246f64d6f1e
util.async: Add once() to create temporary runners
Matthew Wild <mwild1@gmail.com>
parents:
8648
diff
changeset
|
286 ready = ready; |
9246f64d6f1e
util.async: Add once() to create temporary runners
Matthew Wild <mwild1@gmail.com>
parents:
8648
diff
changeset
|
287 waiter = waiter; |
9246f64d6f1e
util.async: Add once() to create temporary runners
Matthew Wild <mwild1@gmail.com>
parents:
8648
diff
changeset
|
288 guarder = guarder; |
8651
1b7c5933b215
util.async: Add sleep() method
Matthew Wild <mwild1@gmail.com>
parents:
8649
diff
changeset
|
289 runner = runner; |
10928
79faf5b98395
util.async: Rename wait -> wait_for (w/compat)
Matthew Wild <mwild1@gmail.com>
parents:
10291
diff
changeset
|
290 wait = wait_for; -- COMPAT w/trunk pre-0.12 |
79faf5b98395
util.async: Rename wait -> wait_for (w/compat)
Matthew Wild <mwild1@gmail.com>
parents:
10291
diff
changeset
|
291 wait_for = wait_for; |
11961
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
292 sleep = sleep; |
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
293 |
11962
9a70a543c727
util.async: Add next-tick configuration
Matthew Wild <mwild1@gmail.com>
parents:
11961
diff
changeset
|
294 set_nexttick = function(new_next_tick) next_tick = new_next_tick; end; |
11961
542a9a503073
util.async: Add sleep() method with configurable scheduling backend
Matthew Wild <mwild1@gmail.com>
parents:
10931
diff
changeset
|
295 set_schedule_function = function (new_schedule_function) schedule_task = new_schedule_function; end; |
8649
9246f64d6f1e
util.async: Add once() to create temporary runners
Matthew Wild <mwild1@gmail.com>
parents:
8648
diff
changeset
|
296 }; |