summaryrefslogtreecommitdiffstats
path: root/daemon/bindings/event.rst
blob: a96f299ba1d83c8160755d1db585909057b5d9e3 (plain)
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