]> mj.ucw.cz Git - libucw.git/blob - ucw/doc/mainloop.txt
Main: Update documentation
[libucw.git] / ucw / doc / mainloop.txt
1 Mainloop
2 ========
3
4 Not every program is strictly sequential. Sometimes, an event-driven
5 model is much easier to grasp. A fine example of such a program could
6 be a railway server. It has a separate connection to each station
7 and also to each train, so that it knows where each of them is (and
8 that neither a train nor a station have got missing). So it has to wait
9 for events coming from these connections and handle them appropriately.
10 It also processes other events that it has itself generated -- for
11 example various timers telling that a train is scheduled to depart
12 from some station.
13
14 The mainloop module takes care of the low-level part of event-driven
15 programs: it calls the OS to monitor file activity, to interrupt
16 the program at the right moment to serve a timer, and so on. The
17 programmer only defines hooks that should be called to handle
18 the events and calls mainloop functions to schedule them.
19
20 - <<simple,Simple use>>
21 - <<contexts,Using multiple contexts>>
22 - <<threads,Forking and threading>>
23 - <<basic,Basic operations>>
24 - <<time,Time and timers>>
25 - <<file,Activity on file descriptors>>
26 - <<blockio,Asynchronous block I/O>>
27 - <<hooks,Loop hooks>>
28 - <<process,Child processes>>
29 - <<control,Control of the mainloop>>
30
31 [[contexts]]
32 Simple use
33 ----------
34
35 Simple programs usually employ the main loop in a straightforward way:
36
37 - Call @main_init() to initialize the main loop machinery.
38 - Add an initial set of event hooks (@file_add(), @timer_add(), etc.).
39 - Enter the event loop by calling @main_loop(). This function runs for
40   the rest of the lifetime of the program. It watches for events and
41   handles them by calling the appropriate hook functions. These functions
42   can of course add new events or modify/delete the existing ones.
43 - When the program decides it wants to stop, it calls @main_shut_down(),
44   or alternatively it returns `HOOK_SHUTDOWN` from some hook callback.
45   Soon after that, @main_loop() returns.
46 - Remove all event hooks and call @main_cleanup().
47
48 The event structures (like <<struct_main_file,`struct main_file`>>) are
49 always allocated by the user, but please touch only the fields marked
50 in this documentation with `[*]'. The other fields are used internally;
51 you should initialize them to zeroes before adding the event and avoid
52 accessing them afterwards.
53
54 [[contexts]]
55 Using multiple contexts
56 -----------------------
57
58 In a more complex program, it can be useful to keep several sets of events
59 and run a separate instance of the event loop for each such set. A typical
60 example would be a multi-threaded program or a function which needs to
61 communicate with a network server locally, ignoring all other events
62 before the operation is finished.
63
64 For such cases, you can create multiple instances of <<struct_main_context,`struct main_context`>>
65 by calling @main_new(). Each thread then keeps its own current context,
66 which can be changed by @main_switch_context(). All mainloop functions
67 then either take an explicit pointer to a context or (more typically)
68 they operate on the current context. When you no longer need the context, you
69 can delete it by @main_delete().
70
71 It is even possible to use nested main loops: in a hook called by the
72 top-level instance of @main_loop(), you can switch to a different context,
73 call @main_loop() recursively and when you are done, switch back and return
74 to the top-level loop.
75
76 *CAVEAT:* In the present implementation, only a single context per process
77 can handle process exit events. If you use @process_add() in multiple contexts,
78 it can happen that the current context catches the `SIGCHLD` signal and obtains
79 information about a child process associated with another context, which it does
80 not know how to handle. If you ever need this, please let us know.
81
82 [[threads]]
83 Forking and threading
84 ---------------------
85
86 Using the event loop in a multi-threaded or multi-process program is possible,
87 but it should be done very carefully.
88
89 Multiple threads can use the main loop, but each of them must use a separate
90 context (or contexts).
91
92 When you fork() a child process, either the parent or the child must give up
93 use of each main loop context. The @main_teardown() and @main_destroy() functions
94 can be useful for that. (The reason is that some parts of the main loop context,
95 like file descriptors used internally, become shared between the processes, so
96 the processes could influence each other in crazy ways. You do not want to hunt
97 for such bugs.)
98
99
100
101 !!ucw/mainloop.h