remove history from TODO
[wmiirc-lua.git] / doc / event-loop
blobc902080c9e4c9a0df26c8b9e2336228cbc776ee7
1 About
2 ======
4 The problem is that the libixp interface does not permit a select() loop to
5 be ran against the ixp socket w/o a major rewrite of the ixp library.  I
6 am not interested in this.
8 The eventloop library
9 ======================
11 The cleanest way to handle multiple event sources is via a select() or
12 poll() loop.  However the blocking nature of libixp is still a problem.
13 Fortunately, there is only one file in wmii's ixp filesystem that would
14 cause blocking... the /event file.  This is a magic file that never
15 stops generating content; at least not while wmii is running.
17 To handle IO on all wmii files we use the libixp.so library.  It's
18 already good at what it does... accessing readily available content.
19 For handling the read of the /event file we fork off a wmiir process to
20 read it.  This process is connected to the main program via a pipe(2).
21 One side of the pipe is fed by wmiir, and the other is used on the lua
22 side in a select() loop.
24 The select loop is implemented in C, and exported to lua as an eventloop
25 module.  wmii.lua creates an eventloop instance and adds a wmiir process
26 to it via an api call.  It then calls a run_loop() function with a
27 duration which causes the select loop to run for that much time, or less
28 if data is generated by the wmiir process.  On return from the
29 run_loop() function, wmii.lua executes the next timer that's queued up.
31 Here is what it looks like:
33         el = eventloop.new()
34         el.add_exec ("wmiir read /events",
35                         function (line)
36                                 ... process event ...
37                         end)
38         ...
39         while true do
40                 local next_timer = handle_timers()
41                 el.run_loop(next_timer)
42         end
44 The nice thing about this is that plugins can use this to generate
45 output on the bar:
47         widget = wmii.widget:new ("990_load")
48         el.add_exec ("dstat --load --nocolor --noheaders --noupdate",
49                         function (line)
50                                 widget:show (line)
51                         end)
53 This makes it really clean to get events from other sources.  We can
54 fork off netcat or tail to get other events.  Best of all no threads or
55 alarm hacks.
57 And the ASCII diagram looks like this.
59     (1)                (3)                      (4)
60   +------+  (ixp) +--------+   read/write() +------------+
61   | wmii | <----- | ixp.so | <------------- | wmiirc.lua |
62   +------+        +--------+                +------------+
63         ^                                         |
64         |                                         v 
65         | (ixp)       (6)                  +--------------+
66      +-------------------+     (fifo)      | eventloop.so | (5)
67      | wmiir read /event | --------------> |   select()   |
68      +-------------------+                 +--------------+
69                                                   |
70                                                   | (fifo)
71                                                   v
72                                            +-------------+
73                                            |  other data | (7)
74                                            |   sources   |
75                                            +-------------+
79 vim: set ts=8 et sw=8 tw=72