1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
.. SPDX-License-Identifier: GPL-3.0-or-later
Timers and events reference
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The timer represents exactly the thing described in the examples - it allows you to execute closures_
after specified time, or event recurrent events. Time is always described in milliseconds,
but there are convenient variables that you can use - ``sec, minute, hour``.
For example, ``5 * hour`` represents five hours, or 5*60*60*100 milliseconds.
.. function:: event.after(time, function)
:return: event id
Execute function after the specified time has passed.
The first parameter of the callback is the event itself.
Example:
.. code-block:: lua
event.after(1 * minute, function() print('Hi!') end)
.. function:: event.recurrent(interval, function)
:return: event id
Execute function immediately and then periodically after each ``interval``.
Example:
.. code-block:: lua
msg_count = 0
event.recurrent(5 * sec, function(e)
msg_count = msg_count + 1
print('Hi #'..msg_count)
end)
.. function:: event.reschedule(event_id, timeout)
Reschedule a running event, it has no effect on canceled events.
New events may reuse the event_id, so the behaviour is undefined if the function
is called after another event is started.
Example:
.. code-block:: lua
local interval = 1 * minute
event.after(1 * minute, function (ev)
print('Good morning!')
-- Halve the interval for each iteration
interval = interval / 2
event.reschedule(ev, interval)
end)
.. function:: event.cancel(event_id)
Cancel running event, it has no effect on already canceled events.
New events may reuse the event_id, so the behaviour is undefined if the function
is called after another event is started.
Example:
.. code-block:: lua
e = event.after(1 * minute, function() print('Hi!') end)
event.cancel(e)
Watch for file descriptor activity. This allows embedding other event loops or simply
firing events when a pipe endpoint becomes active. In another words, asynchronous
notifications for daemon.
.. function:: event.socket(fd, cb)
:param number fd: file descriptor to watch
:param cb: closure or callback to execute when fd becomes active
:return: event id
Execute function when there is activity on the file descriptor and calls a closure
with event id as the first parameter, status as second and number of events as third.
Example:
.. code-block:: lua
e = event.socket(0, function(e, status, nevents)
print('activity detected')
end)
e.cancel(e)
Asynchronous function execution
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The `event` package provides a very basic mean for non-blocking execution - it allows running code when activity on a file descriptor is detected, and when a certain amount of time passes. It doesn't however provide an easy to use abstraction for non-blocking I/O. This is instead exposed through the `worker` package (if `cqueues` Lua package is installed in the system).
.. function:: worker.coroutine(function)
Start a new coroutine with given function (closure). The function can do I/O or run timers without blocking the main thread. See cqueues_ for documentation of possible operations and synchronization primitives. The main limitation is that you can't wait for a finish of a coroutine from processing layers, because it's not currently possible to suspend and resume execution of processing layers.
Example:
.. code-block:: lua
worker.coroutine(function ()
for i = 0, 10 do
print('executing', i)
worker.sleep(1)
end
end)
.. function:: worker.sleep(seconds)
Pause execution of current function (asynchronously if running inside a worker coroutine).
Example:
.. code-block:: lua
function async_print(testname, sleep)
log(testname .. ': system time before sleep' .. tostring(os.time())
worker.sleep(sleep) -- other coroutines continue execution now
log(testname .. ': system time AFTER sleep' .. tostring(os.time())
end
worker.coroutine(function() async_print('call #1', 5) end)
worker.coroutine(function() async_print('call #2', 3) end)
Output from this example demonstrates that both calls to function ``async_print`` were executed asynchronously:
.. code-block:: none
call #2: system time before sleep 1578065073
call #1: system time before sleep 1578065073
call #2: system time AFTER sleep 1578065076
call #1: system time AFTER sleep 1578065078
|