Subversion Repositories liboop

Compare Revisions

Ignore whitespace Rev 11 → Rev 12

/trunk/liboop.org/oop_glib
File deleted
/trunk/liboop.org/on_fd
File deleted
/trunk/liboop.org/oop_adns_query
File deleted
/trunk/liboop.org/oop_rl
File deleted
/trunk/liboop.org/oop_sys
File deleted
/trunk/liboop.org/oop_sys_source
File deleted
/trunk/liboop.org/oop_sys_run
File deleted
/trunk/liboop.org/oop_tcl
File deleted
/trunk/liboop.org/on_signal
File deleted
/trunk/liboop.org/oop_www
File deleted
/trunk/liboop.org/how
File deleted
/trunk/liboop.org/why
File deleted
/trunk/liboop.org/on_time
File deleted
/trunk/liboop.org/alloc
File deleted
/trunk/liboop.org/ref
File deleted
/trunk/liboop.org/oop_adns
File deleted
/trunk/liboop.org/alloc.html
0,0 → 1,62
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: oop_malloc(), oop_free()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>oop_malloc(), oop_free()</h2>
 
<pre>
#include &lt;oop.h&gt;
 
extern void *(*oop_malloc)(size_t len); /* <em>Allocate memory.</em> */
extern void *(*oop_realloc<a href="#note-realloc">*</a>)(void *ptr,size_t len); /* <em>Resize memory.</em> */
extern void (*oop_free)(void *ptr); /* <em>Free allocated memory.</em> */
</pre>
 
<h3>Arguments.</h3>
 
<dl>
<dt><b>size_t len</b>
<dd>Size, in bytes, of the memory block to allocate.<p>
 
<dt><b>void *ptr</b>
<dd>Pointer to memory block to free or reallocate.<p>
</dl>
 
<h3>Description.</h3>
 
These are global function pointers, initialized by default to the standard C
library functions <em>malloc</em>, <em>realloc</em>, and <em>free</em>.
Applications using liboop may reset these pointers to allocation and
deallocation routines with a compatible interface; libraries should use
these function pointers wherever possible to allocate and release memory.
These pointers are normally set before calling any liboop code; if they
are changed during operation, the new <em>oop_free</em> and
<em>oop_realloc</em> functions should be
capable of handling memory obtained with the old <em>oop_malloc</em>.
 
<dl>
<dt><b>oop_malloc</b>
<dd>This function allocates a block of memory of size <em>len</em> and returns
a pointer to the start of the block. If allocation fails, NULL is returned.<p>
 
<dt><b>oop_realloc</b><a href="#note-realloc">*</a>
<dd>This function resizes a block of memory at <em>ptr</em> to have the new
length <em>len</em>. If <em>ptr</em> is NULL, fresh memory is allocated.
If <em>len</em> is zero, memory is freed and NULL is returned.
If <em>ptr</em> is NULL and <em>len</em> is zero, nothing is done and NULL
is returned. If reallocation fails, NULL is returned.<p>
 
<dt><b>oop_free</b>
<dd>This function releases a block of memory, designated by <em>ptr</em>,
previously allocated by <em>oop_malloc</em>. Once released, the memory may
be immediately overwritten, and/or reused by subsequent calls to
<em>oop_malloc</em>.
</dl>
 
<hr>
<p><a name="note-realloc">*</a> <b>Compatibility note:</b> oop_realloc
is only available in version 0.7 or newer.</p>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/how.html
0,0 → 1,80
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: How?</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>Overview of liboop.</h2>
 
<h4>The basic idea.</h4>
 
Liboop is primarily an <em>interface definition</em>. It defines an interface
which components may use to request notification when an <em>event</em>
(activity on a file descriptor, the real-time clock reaches a certain value,
a particular signal is received) occurs. The component which owns the event
loop -- the component whose code is active when the system is idle --
implements the interface; it is an <em>event source</em>. Components which
are interested in events register themselves with the event source; they are
<em>event sinks</em>. Event sinks may themselves source other, higher-level
events, but that is outside liboop's scope.
 
<h4>Control flow.</h4>
 
During initialization, the event source is created. At least one event sink
is also created, and registered with the event source. Once initialization
completes, control is transferred to the event source, which (at its core)
waits for events, usually using a system function like select() or poll().
When an event occurs, the event source gives a <em>callback</em> to all the
event sinks which registered interest in that event.
<p>
During callbacks, the event sinks react to the event as appropriate (usually
performing some I/O, or at least modifying internal state). Event sinks for
events which are no longer relevant may be unregistered; new event sinks may
be registered for additional events. Each event sink, when it finishes,
returns a value which tells the event source whether to continue processing
events or whether to terminate.
<p>
While the event source must be fully reentrant (registration and deregistration
may, and indeed usually are, performed within the context of an event), event
sinks need not be; no event sink will be called while another event sink is
active.
<p>
If no event sink instructs the event source to terminate, the event source
continues waiting for events. Otherwise, the event source returns to its
caller, which usually shuts down the system.
 
<h4>The system event source.</h4>
 
Liboop comes with a single "reference" implementation of an event source.
This event source uses select() to dispatch events. Most programs built
around liboop will probably use the standard system event source; legacy
programs with their own event loop, or programs with specialized needs may
implement their own event source.
 
<h4>Adapters.</h4>
 
Liboop supports <em>adapters</em> to enable legacy components to use the liboop
interface. For example, many widget sets have their own event loop and their
own mechanism for registering callbacks on timeouts and file descriptor
activity; liboop uses <em>source adapters</em> that accept registration,
register corresponding callbacks with the widget set's event loop, and route
events appropriately. Such adapters let general-purpose liboop-based
components work in an application based on that widget set.
<p>
Similarly, some components are designed to work in a non-blocking fashion, and
they might be used with a <em>sink adapter</em> to work with liboop. An
asynchronous DNS query package, for example, could work as a liboop sink that
ultimately generates a higher-level "success" or "failure" callback to the
invoking routine.
 
<h4>Code.</h4>
 
Liboop's abstract event source interface is implemented as a structure
containing C function pointers. These functions accept a pointer to the
structure as their first argument; sources are expected to include their
own data (in whatever format) with the core function pointers. Callbacks
are also C function pointers, with "void *" arguments to pass data.
<p>
For more about the liboop interface, see the <a href="ref.html">reference</a>.
 
<hr><a href="">liboop home</a></body></html>
/trunk/liboop.org/on_fd.html
0,0 → 1,84
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: on_fd(), cancel_fd()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>on_fd(), cancel_fd()</h2>
 
<pre>
#include &lt;oop.h&gt;
 
/* <em>Types of file descriptor activity.</em> */
typedef enum {
OOP_READ,
OOP_WRITE,
OOP_EXCEPTION<a href="#note-exception">*</a>,
} oop_event;
 
/* <em>Callback function prototype.</em> */
typedef void *oop_call_fd(oop_source *source,int fd,oop_event event,void *user);
 
/* <em>Register and unregister file descriptor activity event sinks.</em> */
void (*on_fd)(oop_source *source,int fd,oop_event event,oop_call_fd *call,void *user);
void (*cancel_fd)(oop_source *source,int fd,oop_event event);
</pre>
 
<h3>Arguments.</h3>
 
<dl>
<dt><b>oop_source *source</b>
<dd>The event source to register or unregister the event sink with. This must
be the same event source you got the function pointer from:
"src-&gt;on_fd(src,...);".<p>
 
<dt><b>int fd</b>
<dd>The file descriptor to watch (or stop watching).<p>
 
<dt><b>oop_event event</b>
<dd>The kind of activity to watch for (or stop watching for). Must be one of
OOP_READ (triggered when data is available for reading on the specified file
descriptor), OOP_WRITE (triggered when buffer space is available to write on
the specified file descriptor), or OOP_EXCEPTION<a href="#note-exception">*</a>
(triggered on any number of "exceptional" events, such as TCP urgent data
or system error).<p>
 
<dt><b>oop_call_fd *call</b>
<dd>The callback function (event sink) to add (or remove).<p>
 
<dt><b>void *user</b>
<dd>User data passed through to the callback function.<p>
</dl>
 
<h3>Description.</h3>
 
Note that these are not global functions, but function pointers supplied
by the event source (in the <em>oop_source</em> structure) or by the user.
 
<dl>
<dt><b>on_fd</b>
<dd>After this function is called, whenever the source's event loop detects
the condition indicated by <em>event</em> (OOP_READ, OOP_WRITE, or
OOP_EXCEPTION<a href="#note-exception">*</a>) on the file descriptor
<em>fd</em>, it will call the function
<em>call</em>, passing it a pointer to the event source, the file descriptor,
the event type, and the same opaque <em>user</em> pointer passed to on_fd.
This callback will be called repeatedly as long as the condition persists and
it is not deactivated (see below). Only one callback may be registered per
(event,fd) pair.<p>
 
<dt><b>cancel_fd</b>
<dd>Deactivate an event sink callback registered using on_fd (above).
Any callback associated with the (event,fd) pair in question is removed.<p>
 
<dt><b>oop_call_fd</b>
<dd>Called when the event is triggered. Performs a user_specific action.
Should return OOP_CONTINUE if the event loop should continue operating; any
other value (including OOP_HALT) will cause termination of the event loop.
</dl>
 
<hr>
<p><a name="note-exception">*</a> <b>Compatibility note:</b> OOP_EXCEPTION
is only available in version 0.7 or newer.</p>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/on_signal.html
0,0 → 1,67
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: on_signal(), cancel_signal()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>on_signal(), cancel_signal()</h2>
 
<pre>
#include &lt;oop.h&gt;
#include &lt;signal.h&gt;
 
/* <em>Callback function prototype.</em> */
typedef void *oop_call_signal(oop_source *source,int sig,void *user);
 
/* <em>Register and unregister UNIX signal event sinks.</em> */
void (*on_signal)(oop_source *source,int sig,oop_call_signal *call,void *user);
void (*cancel_signal)(oop_source *source,int sig,oop_call_signal *call,void *user);
</pre>
 
<h3>Arguments.</h3>
 
<dl>
<dt><b>oop_source *source</b>
<dd>The event source to register or unregister the event sink with. This must
be the same event source you got the function pointer from:
"src-&gt;on_signal(src,...);".<p>
 
<dt><b>int sig</b>
<dd>The UNIX signal to monitor (SIGINT, SIGHUP, etc.).<p>
 
<dt><b>oop_call_signal *call</b>
<dd>The callback function (event sink) to add (or remove).<p>
 
<dt><b>void *user</b>
<dd>User data passed through to the callback function.<p>
</dl>
 
<h3>Description.</h3>
 
Note that these are not global functions, but function pointers supplied
by the event source (in the <em>oop_source</em> structure) or by the user.
 
<dl>
<dt><b>on_signal</b>
<dd>After this function is called, if the signal <em>sig</em> is received,
when the event loop next runs (immediately, if it is currently waiting for
events), the event source will call the function <em>call</em>, passing it a
pointer to the event source, the signal received, and the same opaque
<em>user</em> pointer passed to on_signal. This callback will be called
again if the signal occurs again, but if the signal is received multiple times
in quick succession the event sink may only receive a single callback.
Many callbacks may be registered for the same signal.<p>
 
<dt><b>cancel_signal</b>
<dd>Deactivate an event sink callback registered using on_signal (above). If
the passed <em>sig</em>, <em>call</em> and <em>user</em> match a previously
registered callback, it will be removed; if they match more than one, one of
them will be removed; otherwise, no action is taken.<p>
 
<dt><b>oop_call_fd</b>
<dd>Called when the event is triggered. Performs a user_specific action.
Should return OOP_CONTINUE if the event loop should continue operating; any
other value (including OOP_HALT) will cause termination of the event loop.
</dl>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/on_time.html
0,0 → 1,70
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: on_time(), cancel_time()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>on_time(), cancel_time()</h2>
 
<pre>
#include &lt;oop.h&gt;
#include &lt;sys/time.h&gt;
 
/* <em>Zero time, for scheduling an event immediately.</em> */
static const struct timeval OOP_TIME_NOW = { 0, 0 };
 
/* <em>Callback function prototype.</em> */
typedef void *oop_call_time(oop_source *source,struct timeval tv,void *user);
 
/* <em>Register and unregister time-triggered event sinks.</em> */
void (*on_time)(oop_source *source,struct timeval tv,oop_call_time *call,void *user);
void (*cancel_time)(oop_source *source,struct timeval tv,oop_call_time *call,void *user);
</pre>
 
<h3>Arguments.</h3>
 
<dl>
<dt><b>oop_source *source</b>
<dd>The event source to register or unregister the event sink with. This must
be the same event source you got the function pointer from:
"src-&gt;on_time(src,...);".<p>
 
<dt><b>struct timeval tv</b>
<dd>The time to wait for. OOP_TIME_NOW (or any time in the past) will cause
immediate scheduling.<p>
 
<dt><b>oop_call_time *call</b>
<dd>The callback function (event sink) to add (or remove).<p>
 
<dt><b>void *user</b>
<dd>User data passed through to the callback function.<p>
</dl>
 
<h3>Description.</h3>
 
Note that these are not global functions, but function pointers supplied
by the event source (in the <em>oop_source</em> structure) or by the user.
 
<dl>
<dt><b>on_time</b>
<dd>After this function is called, when the event loop is running and the
time <em>tv</em> is reached (or immediately upon entry to the event loop, if
the specified time occurs in the past), the event source will call the function
<em>call</em>, passing it a pointer to the event source, the scheduled time,
and the same opaque <em>user</em> pointer passed to on_time. This callback
will only be called once. Many callbacks may be registered for the same
time.<p>
 
<dt><b>cancel_time</b>
<dd>Deactivate an event sink callback registered using on_time (above). If the
passed <em>tv</em>, <em>call</em> and <em>user</em> match a previously
registered callback, it will be removed; if they match more than one, one of
them will be removed; otherwise, no action is taken.<p>
 
<dt><b>oop_call_time</b>
<dd>Called when the event is triggered. Performs a user_specific action.
Should return OOP_CONTINUE if the event loop should continue operating; any
other value (including OOP_HALT) will cause termination of the event loop.
</dl>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/oop_adns.html
0,0 → 1,58
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: oop_adns_new(), oop_adns_delete()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>oop_adns_new(), oop_adns_delete()</h2>
 
<pre>
#include &lt;oop.h&gt;
#include &lt;adns.h&gt;
#include &lt;oop-adns.h&gt;
 
oop_adapter_adns *oop_adns_new(oop_source *source,adns_initflags flags,FILE *diag);
void oop_adns_delete(oop_adapter_adns *adapter);
</pre>
 
<h3>Arguments.</h3>
 
<dl>
<dt><b>oop_source *source</b>
<dd>The event source to use. The adapter will use this event source to wait
asynchronously for network communication.<p>
 
<dt><b>adns_initflags flags</b>
<dd>Any initialization flags used to create the instance of adns. Refer to the
adns documentation for details.<p>
 
<dt><b>FILE *diag</b>
<dd>The file to send adns diagnostics to. Refer to the adns documentation for
details.<p>
 
<dt><b>oop_adapter_adns *adapter</b>
<dd>An adns adapter to delete, with no outstanding
<a href="oop_adns_query.html">queries</a>.<p>
</dl>
 
<h3>Description.</h3>
 
<dl>
<dt><b>oop_adns_new</b>
<dd>Create a new liboop adns adapter. This adapter manages an instance of
<a href="http://www.chiark.greenend.org.uk/~ian/adns/">Ian Jackson's
asychronous DNS resolver</a> and supplies it with events from <em>source</em>.
The adns instance is initialized with the supplied <em>flags</em> and
<em>diag</em> file; refer to the adns documentation for details.<p>
 
If a malloc failure or other catastrophic system error occurs creating the
adapter, NULL is returned. The caller must handle this failure.<p>
 
<dt><b>oop_adns_delete</b>
<dd>Destroy the liboop adns adapter <em>adns</em>. This frees all resources
associated with the adapter, including the underlying adns instance. Any
callbacks registered with the event source are cancelled. The adapter can have
no active queries when it is deleted.<p>
</dl>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/oop_adns_query.html
0,0 → 1,94
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: oop_adns_submit(), oop_adns_cancel()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>oop_adns_submit(), oop_adns_cancel()</h2>
 
<pre>
#include &lt;oop.h&gt;
#include &lt;adns.h&gt;
#include &lt;oop-adns.h&gt;
 
/* <em>Callback function prototype.</em> */
typedef void *oop_adns_call(oop_adapter_adns *adapter,adns_answer *answer,void *data);
 
/* <em>Submit an asynchronous DNS query.</em> */
oop_adns_query *oop_adns_submit(
oop_adapter_adns *adapter,
const char *owner,adns_rrtype type,adns_queryflags flags,
oop_adns_call *call,void *user);
 
/* <em>Cancel a running query.</em> */
void oop_adns_cancel(oop_adns_query *query);
</pre>
 
<h3>Arguments.</h3>
 
<dl>
<dt><b>oop_adapter_adns *adns</b>
<dd>The <a href="oop_adns.html">adns adapter</a> to use for the query.<p>
 
<dt><b>adns_answer *answer</b>
<dd>The answer to the query (status and RR data). Refer to the adns
documentation for details.<p>
 
<dt><b>const char *owner</b>
<dd>The DNS domain name to query.<p>
 
<dt><b>adns_rrtype type</b>
<dd>The DNS Resource Record type to query. Refer to the adns documentation for
the list of valid RR types.<p>
 
<dt><b>adns_queryflags flags</b>
<dd>Flags for the DNS query. Refer to the adns documentation for details.<p>
 
<dt><b>oop_call_fd *call</b>
<dd>The callback function (event sink) to use for reporting query succcess or
failure.<p>
 
<dt><b>void *user</b>
<dd>User data passed through to the callback function.<p>
 
<dt><b>oop_adns_query *query</b>
<dd>The query to cancel.
</dl>
 
<h3>Description.</h3>
 
<dl>
<dt><b>oop_adns_submit</b>
<dd>This function begins a DNS query using an adns adapter. Most of the
parameters are passed directly to adns. The query will be processed
asynchronously using the event source specified when the adapter was created;
when it completes (successfully or not), the specified callback will be
invoked.<p>
 
On malloc failure or catastrophic system error, NULL will be returned.
(Simple name resolution errors, such as not finding the name, do not result
in a NULL query; instead, the callback is invoked with an error status.)<p>
 
The returned pointer is valid (and may be used to cancel the query) until
either the query is cancelled or the callback is invoked (the query
completes).<p>
 
<dt><b>oop_adns_cancel</b>
<dd>Stop processing a query started with oop_adns_submit (above). This must
be called with a non-NULL pointer returned from oop_adns_submit before the
query has completed (and the callback function invoked). Any query may only
be cancelled once. All resources associated with the query will be
released.<p>
 
<dt><b>oop_adns_call</b>
<dd>Called when the query completes, successfully or not. Performs a
user-specific action with the results of the query. All resources associated
with the query will be released before the function is called, except for the
answer structure itself. (The user is responsible for freeing the answer
structure, as per the conventions established by adns. Note that adns does
not use oop_alloc!)
Should return OOP_CONTINUE if the event loop should continue operating;
any other value (including OOP_HALT) will cause termination of the event loop.
</dl>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/oop_glib.html
0,0 → 1,48
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: oop_glib_new(), oop_glib_delete(), oop_glib_return()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>oop_glib_new(), oop_glib_delete(), oop_glib_return()</h2>
 
<pre>
#include &lt;oop.h&gt;
#include &lt;glib.h&gt;
#include &lt;oop-glib.h&gt;
 
oop_source *oop_glib_new();
void oop_glib_delete();
void *oop_glib_return();
</pre>
 
<h3>Description.</h3>
 
<dl>
<dt><b>oop_glib_new</b>
<dd>Create a liboop source which uses the
<a href="http://www.gtk.org/rdp/glib/glib-the-main-event-loop.html">GLib
Main Event Loop</a> for events. There is only one such event loop (the
GMainLoop structure really represents a loop context, not a fully independent
event loop), so this function is global. You may call it multiple times; it
will return the same event source, but keep count of the number of users.<p>
 
Events will be dispatched when the GLib event loop is run, either directly
via g_main_run() or indirectly via gtk_main().<p>
 
<dt><b>oop_glib_delete</b>
<dd>Delete the liboop source created with oop_glib_new(). This decrements the
count of users; when oop_glib_delete has been called as many times as
oop_glib_new, the event source is removed.<p>
 
<dt><b>oop_glib_return</b>
<dd>Since the event source is run by GLib, the main program has no direct way
of retrieving a value returned by an event handler. Instead, when the loop is
terminated, the GLib event loop should return, and the caller can use this
function to request the specific termination code.<p>
 
This function isn't commonly used. <b>Furthermore, GLib event loop termination
does not currently work.</b> In other words, ignore this for now.
</dl>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/oop_rl.html
0,0 → 1,47
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: oop_readline_register(), oop_readline_cancel()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>oop_readline_register(), oop_readline_cancel()</h2>
 
<pre>
#include &lt;oop.h&gt;
#include &lt;oop-rl.h&gt;
 
void oop_readline_register(oop_source *source);
void oop_readline_cancel(oop_source *source);
</pre>
 
<h3>Arguments.</h3>
 
<dl>
<dt><b>oop_source *source</b>
<dd>The event source to use. The adapter will use this event source to wait
asynchronously for console input.<p>
</dl>
 
<h3>Description.</h3>
 
<dl>
<dt><b>oop_readline_register</b>
<dd>Register a liboop <em>source</em> with the
<a href="http://cnswww.cns.cwru.edu/~chet/readline/rltop.html">GNU Readline
Library</a>. The adapter responds asynchronously to console input and notifies
Readline when it arrives via rl_callback_read_char(). You should use the
Readline <a href="http://cnswww.cns.cwru.edu/~chet/readline/readline.html#SEC38">alternate
interface</a> to prompt the user and receive input.<p>
 
Note well that Readline will
<a href="http://cnswww.cns.cwru.edu/~chet/readline/readline.html#SEC40">install
its own signal handlers</a> by default. Make sure to disable this behavior
by setting rl_catch_signals to zero if you wish to manage signals with
liboop.<p>
 
<dt><b>oop_readline_cancel</b>
<dd>Unregister liboop with Readline. After this is called,
rl_readback_read_char() will no longer be invoked automatically.<p>
</dl>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/oop_sys.html
0,0 → 1,46
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: oop_sys_new(), oop_sys_delete()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>oop_sys_new(), oop_sys_delete()</h2>
 
<pre>
#include &lt;oop.h&gt;
 
/* <em>Create and destroy a system event source.</em> */
oop_source_sys *oop_sys_new(void);
void oop_sys_delete(oop_source_sys *sys);
</pre>
 
<h3>Arguments.</h3>
 
<dl>
<dt><b>oop_source_sys *sys</b>
<dd>The event source to deallocate and destroy.
</dl>
 
<h3>Description.</h3>
 
<dl>
<dt><b>oop_sys_new</b>
<dd>Create a new system event source. The system event source implements the
event source interface and manages a select() loop. Once the system event
source is created, use <a href="oop_sys_source.html">oop_sys_source()</a> to
access the event source interface (which lets you register event sinks), and
<a href="oop_sys_run.html">oop_sys_run()</a> or
<a href="oop_sys_run.html">oop_sys_run_once()</a> to actually process events.
More than one system event source can exist, though it is rarely useful to do
so (since only one may be active at a time).<p>
 
If a malloc failure occurs creating the system event source, NULL is returned.
It is up to the caller to handle this failure.<p>
 
<dt><b>oop_sys_delete</b>
<dd>Destroy the system event source <em>sys</em>. This frees all resources
associated with the event source. The source cannot have any active callbacks
(event sinks) associated with it.<p>
</dl>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/oop_sys_run.html
0,0 → 1,45
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: oop_sys_run()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>oop_sys_run(), oop_sys_run_once()</h2>
 
<pre>
#include &lt;oop.h&gt;
 
/* <em>Run the event loop.</em> */
oop_source *oop_sys_run(oop_source_sys *sys);
oop_source *oop_sys_run_once(oop_source_sys *sys);
</pre>
 
<h3>Arguments.</h3>
<dl>
<dt><b>oop_source_sys *sys</b>
<dd>The event source to operate.
</dl>
 
<h3>Description.</h3>
 
The oop_sys_run() function starts waiting for events registered with the
system event source <em>sys</em>. As events (file descriptor activity, timed
events, and signals) occur, the appropriate event sinks are called. As long
as these callbacks return OOP_CONTINUE, the function continues running and
processing events.<p>
 
When one of the callbacks returns some other value, oop_sys_run returns this
value. You can use this technique to allow callbacks to return data to the
"owner" of the event loop (the caller of oop_sys_run). You may then decide
whether to restart the event loop (by calling oop_sys_run again) or not.<p>
 
If an error occurs waiting for events, oop_sys_run returns OOP_ERROR.
If no event sinks are registered (which would lead to an infinite delay),
oop_sys_run returns OOP_CONTINUE.<p>
 
The oop_sys_run_once() function behaves just like oop_sys_run(), but returns
immediately after processing any pending results. The return values are the
same as oop_sys_run(), except that a return of OOP_CONTINUE does not
necessarily mean that no event sinks are registered.<p>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/oop_sys_source.html
0,0 → 1,30
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: oop_sys_source()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>oop_sys_source()</h2>
 
<pre>
#include &lt;oop.h&gt;
 
/* <em>Get the source interface for a system event source.</em> */
oop_source *oop_sys_source(oop_source_sys *sys);
</pre>
 
<h3>Arguments.</h3>
<dl>
<dt><b>oop_source_sys *sys</b>
<dd>The event source from which to fetch the interface.
</dl>
 
<h3>Description.</h3>
 
This function returns the standard <em>oop_source</em> interface for the
system event source <em>sys</em>. The interface structure returned contains
function pointers for registering and unregistering callbacks with the event
source; you can pass it to modules which simply want an event source, without
needing to know that you use the system event source in particular.<p>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/oop_tcl.html
0,0 → 1,38
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: oop_tcl_new(), oop_tcl_delete()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>oop_tcl_new(), oop_tcl_delete()</h2>
 
<pre>
#include &lt;oop.h&gt;
#include &lt;oop-tcl.h&gt;
 
oop_source *oop_tcl_new();
void oop_tcl_delete();
</pre>
 
<h3>Description.</h3>
 
<dl>
<dt><b>oop_tcl_new</b>
<dd>Create a liboop source which uses the
<a href="http://www.purl.org/tcl/home/man/tcl8.3.2/TclLib/DoOneEvent.htm">Tcl
event loop</a> for events. There is only one such event loop, so this
function is global. You may call it multiple times; it will return the same
event source, but keep count of the number of users.<p>
 
Events will be dispatched when the Tcl event loop is run, either directly
via Tcl_DoOneEvent() or indirectly via Tk_MainLoop(). Unfortunately, there
is no way to stop the Tcl event loop, so return values from event handlers
are ignored.<p>
 
<dt><b>oop_tcl_delete</b>
<dd>Delete the liboop source created with oop_tcl_new(). This decrements the
count of users; when oop_tcl_delete has been called as many times as
oop_tcl_new, the event source is removed.<p>
</dl>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/oop_www.html
0,0 → 1,58
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: oop_www_register(), oop_www_cancel(), oop_www_memory()</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>oop_www_register(), oop_www_cancel(), oop_www_memory()</h2>
 
<pre>
#include &lt;oop.h&gt;
#include &lt;HTEvent.h&gt;
#include &lt;oop-www.h&gt;
 
void oop_www_register(oop_source *source);
void oop_www_cancel();
void oop_www_memory();
</pre>
 
<h3>Arguments.</h3>
 
<dl>
<dt><b>oop_source *source</b>
<dd>The event source to use. The adapter will use this event source to wait
asynchronously for network communication.<p>
</dl>
 
<h3>Description.</h3>
 
<dl>
<dt><b>oop_www_register</b>
<dd>Register a liboop <em>source</em> with the
<a href="http://www.w3.org/Library/">W3C Protocol Library</a> (libwww).
The adapter acts as an event manager for the libwww
<a href="http://www.w3.org/Library/src/HTEvent.html">HTEvent module</a>,
replacing the
<a href="http://www.w3.org/Library/src/HTEvtLst.html">default event
manager</a>; it relies on the supplied source for actual event handling.
Refer to the libwww documentation for the details of its event architecture.<p>
 
<dt><b>oop_www_cancel</b>
<dd>Unregister liboop with libwww. This frees resources associated with the
adapter, and leaves libwww with no event manager. You may use
<b>HTEventInit</b> in the
<a href="http://www.w3.org/Library/src/HTInit.html">HTInit module</a> to
reinstate the libwww default event manager. The adapter can have no active
events when it is deleted. (Take care; libwww tends to cache persistent
connections to Web servers, which may cause events to be registered even if
there are no open requests.)<p>
 
<dt><b>oop_www_memory</b>
<dd>Set <a href="alloc.html">oop_malloc, oop_realloc, and oop_free</a> to
<a href="http://www.w3.org/Library/src/HTMemory.html">HTMemory_malloc
and HTMemory_free</a>, respectively. You do not need to do this, but it
may help to keep your memory allocations consistent with the libwww
framework. If you do this, do so before calling any other liboop functions.
</dl>
 
<hr><a href="ref.html">liboop reference</a></body></html>
/trunk/liboop.org/ref.html
0,0 → 1,160
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: Reference</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>Liboop Reference.</h2>
 
<h4>Event Source Interface.</h4>
 
<pre>
#include &lt;oop.h&gt;
 
/* <em>Applications can set these; liboop libraries will use them.</em> */
extern void *(*<a href="alloc.html">oop_malloc</a>)(size_t); /* <em>returns NULL on failure</em> */
extern void *(*<a href="alloc.html">oop_realloc</a>)(void *,size_t); /* <em>returns NULL on failure</em> */
extern void (*<a href="alloc.html">oop_free</a>)(void *);
 
typedef struct oop_source oop_source;
struct oop_source {
/* <em>File descriptor activity events.</em> */
void (*<a href="on_fd.html">on_fd</a>)(oop_source *,int fd,oop_event,oop_call_fd *,void *);
void (*<a href="on_fd.html">cancel_fd</a>)(oop_source *,int fd,oop_event);
 
/* <em>Timer events.</em> */
void (*<a href="on_time.html">on_time</a>)(oop_source *,struct timeval,oop_call_time *,void *);
void (*<a href="on_time.html">cancel_time</a>)(oop_source *,struct timeval,oop_call_time *,void *);
 
/* <em>UNIX signal events.</em> */
void (*<a href="on_signal.html">on_signal</a>)(oop_source *,int sig,oop_call_signal *,void *);
void (*<a href="on_signal.html">cancel_signal</a>)(oop_source *,int sig,oop_call_signal *,void *);
};
</pre>
 
<h4>System Event Source.</h4>
 
<pre>
typedef struct oop_source_sys oop_source_sys;
 
/* <em>Create and destroy a system event source.</em> */
oop_source_sys *<a href="oop_sys.html">oop_sys_new</a>(void); /* <em>returns NULL on failure</em> */
void <a href="oop_sys.html">oop_sys_delete</a>(oop_source_sys *);
 
/* <em>Run the system event loop.</em> */
void *<a href="oop_sys_run.html">oop_sys_run</a>(oop_source_sys *);
void *<a href="oop_sys_run.html">oop_sys_run_once</a>(oop_source_sys *);
 
/* <em>Get the standard source interface for a system event source.</em> */
oop_source *<a href="oop_sys_source.html">oop_sys_source</a>(oop_source_sys *);
</pre>
 
<hr>
<h4><a href="http://www.chiark.greenend.org.uk/~ian/adns/">ADNS</a> Event Sink
Adapter.</h4>
 
<p><em>Please note that while the core of liboop is distributed under the
Lesser GPL, ADNS is covered by the
<a href="http://www.fsf.org/copyleft/gpl.html">full GPL</a>.</em></p>
 
<pre>
#include &lt;adns.h&gt;
#include &lt;oop-adns.h&gt;
 
typedef struct oop_adapter_adns oop_adapter_adns;
typedef struct oop_adns_query oop_adns_query;
 
/* <em>Create and destroy a liboop adns adapter, including an instance of adns.</em> */
oop_adapter_adns *<a href="oop_adns.html">oop_adns_new</a>(oop_source *,adns_initflags,FILE *diag); /* <em>returns NULL on failure</em> */
void <a href="oop_adns.html">oop_adns_delete</a>(oop_adapter_adns *);
 
/* <em>Submit an asynchronous DNS query.</em> */
oop_adns_query *<a href="oop_adns_query.html">oop_adns_submit</a>( /* <em>returns NULL on failure</em> */
oop_adapter_adns *,
const char *owner,adns_rrtype type,adns_queryflags flags,
oop_adns_call *,void *);
 
/* <em>Cancel a running query.</em> */
void <a href="oop_adns_query.html">oop_adns_cancel</a>(oop_adns_query *);
</pre>
 
<hr>
<h4><a href="http://gtk.org/">GLib</a> Event Source Adapter.</h4>
 
<p><em>GLib is copyrighted by Peter Mattis, Spencer Kimball and Josh MacDonald,
and licensed under the terms of the
<a href="http://www.fsf.org/copyleft/lgpl.html">GNU Library GPL</a>.</em></p>
 
<pre>
#include &lt;glib.h&gt;
#include &lt;oop-glib.h&gt;
 
/* <em>Create and destroy a liboop GLib adapter.</em> */
oop_source *<a href="oop_glib.html">oop_glib_new</a>();
void <a href="oop_glib.html">oop_glib_delete</a>();
 
/* <em>Get the value used to terminate the event loop (e.g. OOP_HALT)</em>. */
void *<a href="oop_glib.html">oop_glib_return</a>();
</pre>
 
<hr>
<h4><a href="http://www.purl.org/tcl/home/">Tcl/Tk</a>
Event Source Adapter.</h4>
 
<p><em>Tcl is copyrighted by the Regents of the University of California,
Sun Microsystems, Inc., and other parties.</em></p>
 
<pre>
#include &lt;oop-tcl.h&gt;
 
/* <em>Create and destroy a liboop Tcl adapter.</em> */
oop_source *<a href="oop_tcl.html">oop_tcl_new</a>();
void <a href="oop_tcl.html">oop_tcl_delete</a>();
</pre>
 
<hr>
<h4><a href="http://www.w3.org/Library/">Libwww</a> Event Sink Adapter.</h4>
 
<p><em>Libwww is covered by this <a
href="http://www.w3.org/Consortium/Legal/libwww-copyright-notice-19980720.html"
>copyright notice</a> and distributed under the terms of the
<a href="http://www.w3.org/Consortium/Legal/copyright-software.html">W3C
Software License</a>.</em></p>
 
<pre>
#include &lt;HTEvent.h&gt;
#include &lt;oop-www.h&gt;
 
/* <em>Register a liboop event source as a libwww "event manager".</em> */
void <a href="oop_www.html">oop_www_register</a>(oop_source *);
 
/* <em>Unregister the event source, leaving libwww with no event manager.
This function cannot be executed with outstanding event requests.</em> */
void <a href="oop_www.html">oop_www_cancel</a>();
 
/* <em>Use libwww for liboop's oop_malloc, oop_realloc, and oop_free.
<b>If you use this, you must call it before any other liboop function!</b></em> */
void <a href="oop_www.html">oop_www_memory</a>();
</pre>
 
<hr>
<h4><a href="http://cnswww.cns.cwru.edu/~chet/readline/rltop.html">GNU
Readline Library</a> Event Sink Adapter.</h4>
 
<p><em>Please note that while the core of liboop is distributed under the
Lesser GPL, Readline is covered by the
<a href="http://www.fsf.org/copyleft/gpl.html">full GPL</a>.</em></p>
 
<pre>
#include &lt;oop-rl.h&gt;
 
/* <em>Use a liboop event source to call rl_callback_read_char().
It is up to you to call rl_callback_handler_install().
Note well that Readline uses malloc(), not oop_malloc().</em> */
void <a href="oop_rl.html">oop_readline_register</a>(oop_source *);
 
/* <em>Stop notifying readline of input characters.</em> */
void <a href="oop_rl.html">oop_readline_cancel</a>(oop_source *);
</pre>
 
<hr><a href="">liboop home</a></body></html>
/trunk/liboop.org/why.html
0,0 → 1,136
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<title>liboop: Why?</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head><body>
 
<h2>Why use liboop?</h2>
 
<h4>The problem.</h4>
 
Developers often wish to write applications which serve as a mediator between
several logical interfaces simultaneously; in fact, most applications work
this way. For example, a browser application might wish to maintain a user
interface while also managing a network connection and occasionally exchanging
data with the local filesystem. A server application might be communicating
with several clients at once while also occasionally receiving a signal from
the administrator directing it to reload its configuration. A multiplayer game
might want to maintain several active user interfaces at once.
<p>
Furthermore, each of these interfaces may be quite complex, sufficiently so to
merit shared code modules which specialize in managing the interface.
Widget sets deal with the details of the X protocol and graphical user
interface management; "curses" deals with the arcana of character-based
terminals; WWW libraries offer high-level access to whole families of Internet
transfer protocols; standard I/O and database routines manage filesystem data.
<p>
However, the existing techniques available for multiplexing interface code are
very poor. Most of these libraries work in "blocking" fashion; once
instructed to complete a task (such as downloading a file, or presenting a
dialog to the user), they do not return until the task is complete (or failed),
even though this may mean waiting an arbitrary amount of time for some external
agent (such as the user or the network) to respond. Some of the better systems
are able to manage several concurrent tasks internally, but cannot work with
other components.
<p>
Developers are thus left with several unpalatable choices:
<ol>
<li>Accept "blocking" operation. User interfaces stop functioning while the
application waits for the network; one network client's access is stalled
while another client performs a transaction. As more data moves from local
storage (where access is fast enough that blocking is acceptable) to
delay-prone networked media, this is becoming less and less acceptable.
<li>Use multiple threads for concurrency. While this is a good solution for
some problems, developers who choose this route must struggle with relatively
immature and unportable threading models, and deal with the many libraries
which are not thread-safe; furthermore, threaded programming requires
thought-intensive and error-prone synchronization.
<li>Use multiple processes ("forking") for concurrency. This can also work,
but requires all communication between modules to use some form of
inter-process communication, which increases complexity and decreases
performance. Forking itself is a slow operation, leading to complex
"pre-forking" schemes for better performance. Worst of all, each process
must somehow multiplex IPC from other processes with whatever I/O task it had
to accomplish in the first place; this brings back the very problem forking
was designed to address.
<li>Attempt to multiplex each library's I/O operations directly in a master
"select loop". This requires the developer to understand intimately the
exact details of each library's I/O interactions, thus breaking modularity,
fostering unhealthy dependency and leading to a single central snarl through
which all I/O must pass.
</ol>
The paucity of options is reflected in the quality of applications. How many
programs hang unpleasantly while performing simple network operations like
hostname resolution? How many user interfaces are unnecessarily "modal"?
How many simple servers fork for no good reason? How many network applications
simply don't exist because it's so difficult to write them?
 
<h4>The solution.</h4>
 
Liboop offers a single, simple, central event loop. Modules wishing to perform
I/O without blocking request <em>callbacks</em> from the central <em>event
source</em>. These callbacks may be tied to file-descriptor activity, the
system time, or process signals. Liboop is responsible for invoking these
callbacks as appropriate.
<p>
With this system, each module "owns" its own I/O; it can perform arbitrarily
complex operations without blocking anything else in the program. But since
callbacks are executed purely sequentially, there is no complex concurrent code
to manage. From the application developer's point of view, working with liboop
is very simple; the developer simply makes calls to libraries which work their
magic and call the application back when they finish. Applications can easily
manage an arbitrary amount of multiplexed I/O operations using as many
interface libraries as they like without blocking.
<p>
To work with this system, libraries and applications must be liboop-aware.
Development with legacy code uses <em>adapters</em> which translate the I/O
model of an application or library into liboop's model. This does require
knowledge of the code's I/O structure, but can at least keep the modules in
an application independent of each other.
<p>
For more about liboop, see the <a href="how.html">documentation</a>.
 
<h4>Q&amp;A</h4>
 
<dl>
<dt><em>Why don't you just use (favorite widget set), which lets you register
callbacks on file descriptors and all that good stuff?</em>
<dd>Because not everyone might want to be tied to that widget set. In
particular, the developer of a general-purpose I/O library would want to
allow everyone to use it, without requiring a particular widget set.
Liboop lets the library developer write to a standard interface,
which can then be used with most widget sets and other event loops.<p>
 
<a name="glib"></a>
<dt><em>Doesn't GLib's <a
href="http://developer.gnome.org/doc/API/glib/glib-the-main-event-loop.html">Main
Event Loop</a> do all this, and more?</em>
<dd>Not quite. GLib is a fine implementation of an event loop (with
bells and whistles) that supports some extensibility (such as the ability to
add extra sources). However, I'm doubtful that it extends far enough that
it could run on top of someone else's event loop (such as the Tk event loop).
Furthermore, the GLib event loop doesn't manage signals; synchronous handling
of asynchronous signals is very difficult to do properly and safely in most
existing systems (without kludges like polling).
 
<p>In any case, we do have a
<a href="oop_glib.html">GLib source adapter</a> so you can use the GLib event loop
with the liboop interface.</p>
 
<dt><em>How does liboop compare to Niels Provos' <a
href="http://www.monkey.org/~provos/libevent/">libevent</a>?</em>
<dd>Like GLib, libevent is a concrete implementation of an event loop, not
an abstract interface for many event loops; also like GLib, libevent does not
manage signals. Libevent is smaller and simpler than either liboop or Glib.
While liboop and GLib are both licensed under the
<a href="http://www.fsf.org/copyleft/lesser.html">Lesser GPL</a>, libevent
appears to be licensed under the original BSD license, including the
advertising clause. Note that the advertising clause renders libevent
incompatible with GPL software!
 
<p>It is entirely possible to imagine a libevent source adapter for liboop.
If anyone is interested in such an adapter, please contact me.</p>
 
</dl>
 
<hr><a href="">liboop home</a></body></html>