Rev 3 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3 | magnus | 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
2 | <html><head> |
||
3 | <title>liboop: Why?</title> |
||
4 | <link rel="stylesheet" type="text/css" href="style.css"> |
||
5 | </head><body> |
||
6 | |||
7 | <h2>Why use liboop?</h2> |
||
8 | |||
9 | <h4>The problem.</h4> |
||
10 | |||
11 | Developers often wish to write applications which serve as a mediator between |
||
12 | several logical interfaces simultaneously; in fact, most applications work |
||
13 | this way. For example, a browser application might wish to maintain a user |
||
14 | interface while also managing a network connection and occasionally exchanging |
||
15 | data with the local filesystem. A server application might be communicating |
||
16 | with several clients at once while also occasionally receiving a signal from |
||
17 | the administrator directing it to reload its configuration. A multiplayer game |
||
18 | might want to maintain several active user interfaces at once. |
||
19 | <p> |
||
20 | Furthermore, each of these interfaces may be quite complex, sufficiently so to |
||
21 | merit shared code modules which specialize in managing the interface. |
||
22 | Widget sets deal with the details of the X protocol and graphical user |
||
23 | interface management; "curses" deals with the arcana of character-based |
||
24 | terminals; WWW libraries offer high-level access to whole families of Internet |
||
25 | transfer protocols; standard I/O and database routines manage filesystem data. |
||
26 | <p> |
||
27 | However, the existing techniques available for multiplexing interface code are |
||
28 | very poor. Most of these libraries work in "blocking" fashion; once |
||
29 | instructed to complete a task (such as downloading a file, or presenting a |
||
30 | dialog to the user), they do not return until the task is complete (or failed), |
||
31 | even though this may mean waiting an arbitrary amount of time for some external |
||
32 | agent (such as the user or the network) to respond. Some of the better systems |
||
33 | are able to manage several concurrent tasks internally, but cannot work with |
||
34 | other components. |
||
35 | <p> |
||
36 | Developers are thus left with several unpalatable choices: |
||
37 | <ol> |
||
38 | <li>Accept "blocking" operation. User interfaces stop functioning while the |
||
39 | application waits for the network; one network client's access is stalled |
||
40 | while another client performs a transaction. As more data moves from local |
||
41 | storage (where access is fast enough that blocking is acceptable) to |
||
42 | delay-prone networked media, this is becoming less and less acceptable. |
||
43 | <li>Use multiple threads for concurrency. While this is a good solution for |
||
44 | some problems, developers who choose this route must struggle with relatively |
||
45 | immature and unportable threading models, and deal with the many libraries |
||
46 | which are not thread-safe; furthermore, threaded programming requires |
||
47 | thought-intensive and error-prone synchronization. |
||
48 | <li>Use multiple processes ("forking") for concurrency. This can also work, |
||
49 | but requires all communication between modules to use some form of |
||
50 | inter-process communication, which increases complexity and decreases |
||
51 | performance. Forking itself is a slow operation, leading to complex |
||
52 | "pre-forking" schemes for better performance. Worst of all, each process |
||
53 | must somehow multiplex IPC from other processes with whatever I/O task it had |
||
54 | to accomplish in the first place; this brings back the very problem forking |
||
55 | was designed to address. |
||
56 | <li>Attempt to multiplex each library's I/O operations directly in a master |
||
57 | "select loop". This requires the developer to understand intimately the |
||
58 | exact details of each library's I/O interactions, thus breaking modularity, |
||
59 | fostering unhealthy dependency and leading to a single central snarl through |
||
60 | which all I/O must pass. |
||
61 | </ol> |
||
62 | The paucity of options is reflected in the quality of applications. How many |
||
63 | programs hang unpleasantly while performing simple network operations like |
||
64 | hostname resolution? How many user interfaces are unnecessarily "modal"? |
||
65 | How many simple servers fork for no good reason? How many network applications |
||
66 | simply don't exist because it's so difficult to write them? |
||
67 | |||
68 | <h4>The solution.</h4> |
||
69 | |||
70 | Liboop offers a single, simple, central event loop. Modules wishing to perform |
||
71 | I/O without blocking request <em>callbacks</em> from the central <em>event |
||
72 | source</em>. These callbacks may be tied to file-descriptor activity, the |
||
73 | system time, or process signals. Liboop is responsible for invoking these |
||
74 | callbacks as appropriate. |
||
75 | <p> |
||
76 | With this system, each module "owns" its own I/O; it can perform arbitrarily |
||
77 | complex operations without blocking anything else in the program. But since |
||
78 | callbacks are executed purely sequentially, there is no complex concurrent code |
||
79 | to manage. From the application developer's point of view, working with liboop |
||
80 | is very simple; the developer simply makes calls to libraries which work their |
||
81 | magic and call the application back when they finish. Applications can easily |
||
82 | manage an arbitrary amount of multiplexed I/O operations using as many |
||
83 | interface libraries as they like without blocking. |
||
84 | <p> |
||
85 | To work with this system, libraries and applications must be liboop-aware. |
||
86 | Development with legacy code uses <em>adapters</em> which translate the I/O |
||
87 | model of an application or library into liboop's model. This does require |
||
88 | knowledge of the code's I/O structure, but can at least keep the modules in |
||
89 | an application independent of each other. |
||
90 | <p> |
||
12 | magnus | 91 | For more about liboop, see the <a href="how.html">documentation</a>. |
3 | magnus | 92 | |
93 | <h4>Q&A</h4> |
||
94 | |||
95 | <dl> |
||
96 | <dt><em>Why don't you just use (favorite widget set), which lets you register |
||
97 | callbacks on file descriptors and all that good stuff?</em> |
||
98 | <dd>Because not everyone might want to be tied to that widget set. In |
||
99 | particular, the developer of a general-purpose I/O library would want to |
||
100 | allow everyone to use it, without requiring a particular widget set. |
||
101 | Liboop lets the library developer write to a standard interface, |
||
102 | which can then be used with most widget sets and other event loops.<p> |
||
103 | |||
104 | <a name="glib"></a> |
||
105 | <dt><em>Doesn't GLib's <a |
||
106 | href="http://developer.gnome.org/doc/API/glib/glib-the-main-event-loop.html">Main |
||
107 | Event Loop</a> do all this, and more?</em> |
||
108 | <dd>Not quite. GLib is a fine implementation of an event loop (with |
||
109 | bells and whistles) that supports some extensibility (such as the ability to |
||
110 | add extra sources). However, I'm doubtful that it extends far enough that |
||
111 | it could run on top of someone else's event loop (such as the Tk event loop). |
||
112 | Furthermore, the GLib event loop doesn't manage signals; synchronous handling |
||
113 | of asynchronous signals is very difficult to do properly and safely in most |
||
114 | existing systems (without kludges like polling). |
||
115 | |||
116 | <p>In any case, we do have a |
||
12 | magnus | 117 | <a href="oop_glib.html">GLib source adapter</a> so you can use the GLib event loop |
3 | magnus | 118 | with the liboop interface.</p> |
119 | |||
120 | <dt><em>How does liboop compare to Niels Provos' <a |
||
121 | href="http://www.monkey.org/~provos/libevent/">libevent</a>?</em> |
||
122 | <dd>Like GLib, libevent is a concrete implementation of an event loop, not |
||
123 | an abstract interface for many event loops; also like GLib, libevent does not |
||
124 | manage signals. Libevent is smaller and simpler than either liboop or Glib. |
||
125 | While liboop and GLib are both licensed under the |
||
126 | <a href="http://www.fsf.org/copyleft/lesser.html">Lesser GPL</a>, libevent |
||
127 | appears to be licensed under the original BSD license, including the |
||
128 | advertising clause. Note that the advertising clause renders libevent |
||
129 | incompatible with GPL software! |
||
130 | |||
131 | <p>It is entirely possible to imagine a libevent source adapter for liboop. |
||
132 | If anyone is interested in such an adapter, please contact me.</p> |
||
133 | |||
134 | </dl> |
||
135 | |||
136 | <hr><a href="">liboop home</a></body></html> |