liboop.org/000755 001750 001750 00000000000 11424552217 013761 5ustar00magnusmagnus000000 000000 liboop.org/why.html000644 001750 001750 00000016515 11030416547 015464 0ustar00magnusmagnus000000 000000 liboop: Why?

Why use liboop?

The problem.

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.

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.

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.

Developers are thus left with several unpalatable choices:

  1. 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.
  2. 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.
  3. 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.
  4. 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.
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?

The solution.

Liboop offers a single, simple, central event loop. Modules wishing to perform I/O without blocking request callbacks from the central event source. These callbacks may be tied to file-descriptor activity, the system time, or process signals. Liboop is responsible for invoking these callbacks as appropriate.

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.

To work with this system, libraries and applications must be liboop-aware. Development with legacy code uses adapters 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.

For more about liboop, see the documentation.

Q&A

Why don't you just use (favorite widget set), which lets you register callbacks on file descriptors and all that good stuff?
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.

Doesn't GLib's Main Event Loop do all this, and more?
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).

In any case, we do have a GLib source adapter so you can use the GLib event loop with the liboop interface.

How does liboop compare to Niels Provos' libevent?
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 Lesser GPL, 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!

It is entirely possible to imagine a libevent source adapter for liboop. If anyone is interested in such an adapter, please contact me.


liboop home liboop.org/oop_www.html000644 001750 001750 00000004252 11030416547 016351 0ustar00magnusmagnus000000 000000 liboop: oop_www_register(), oop_www_cancel(), oop_www_memory()

oop_www_register(), oop_www_cancel(), oop_www_memory()

#include <oop.h>
#include <HTEvent.h>
#include <oop-www.h>

void oop_www_register(oop_source *source);
void oop_www_cancel();
void oop_www_memory();

Arguments.

oop_source *source
The event source to use. The adapter will use this event source to wait asynchronously for network communication.

Description.

oop_www_register
Register a liboop source with the W3C Protocol Library (libwww). The adapter acts as an event manager for the libwww HTEvent module, replacing the default event manager; it relies on the supplied source for actual event handling. Refer to the libwww documentation for the details of its event architecture.

oop_www_cancel
Unregister liboop with libwww. This frees resources associated with the adapter, and leaves libwww with no event manager. You may use HTEventInit in the HTInit module 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.)

oop_www_memory
Set oop_malloc, oop_realloc, and oop_free to HTMemory_malloc and HTMemory_free, 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.

liboop reference liboop.org/alloc.html000644 001750 001750 00000004600 11030416547 015737 0ustar00magnusmagnus000000 000000 liboop: oop_malloc(), oop_free()

oop_malloc(), oop_free()

#include <oop.h>

extern void *(*oop_malloc)(size_t len); /* Allocate memory. */
extern void *(*oop_realloc*)(void *ptr,size_t len); /* Resize memory. */
extern void (*oop_free)(void *ptr);     /* Free allocated memory. */

Arguments.

size_t len
Size, in bytes, of the memory block to allocate.

void *ptr
Pointer to memory block to free or reallocate.

Description.

These are global function pointers, initialized by default to the standard C library functions malloc, realloc, and free. 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 oop_free and oop_realloc functions should be capable of handling memory obtained with the old oop_malloc.
oop_malloc
This function allocates a block of memory of size len and returns a pointer to the start of the block. If allocation fails, NULL is returned.

oop_realloc*
This function resizes a block of memory at ptr to have the new length len. If ptr is NULL, fresh memory is allocated. If len is zero, memory is freed and NULL is returned. If ptr is NULL and len is zero, nothing is done and NULL is returned. If reallocation fails, NULL is returned.

oop_free
This function releases a block of memory, designated by ptr, previously allocated by oop_malloc. Once released, the memory may be immediately overwritten, and/or reused by subsequent calls to oop_malloc.

* Compatibility note: oop_realloc is only available in version 0.7 or newer.


liboop reference liboop.org/oop_sys_run.html000644 001750 001750 00000003267 11030416547 017234 0ustar00magnusmagnus000000 000000 liboop: oop_sys_run()

oop_sys_run(), oop_sys_run_once()

#include <oop.h>

/* Run the event loop. */
oop_source *oop_sys_run(oop_source_sys *sys);
oop_source *oop_sys_run_once(oop_source_sys *sys);

Arguments.

oop_source_sys *sys
The event source to operate.

Description.

The oop_sys_run() function starts waiting for events registered with the system event source sys. 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.

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.

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.

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.


liboop reference liboop.org/on_fd.html000644 001750 001750 00000006077 11030416547 015744 0ustar00magnusmagnus000000 000000 liboop: on_fd(), cancel_fd()

on_fd(), cancel_fd()

#include <oop.h>

/* Types of file descriptor activity. */
typedef enum {
        OOP_READ,
        OOP_WRITE,
        OOP_EXCEPTION*,
} oop_event;

/* Callback function prototype. */
typedef void *oop_call_fd(oop_source *source,int fd,oop_event event,void *user);

/* Register and unregister file descriptor activity event sinks. */
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);

Arguments.

oop_source *source
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->on_fd(src,...);".

int fd
The file descriptor to watch (or stop watching).

oop_event event
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* (triggered on any number of "exceptional" events, such as TCP urgent data or system error).

oop_call_fd *call
The callback function (event sink) to add (or remove).

void *user
User data passed through to the callback function.

Description.

Note that these are not global functions, but function pointers supplied by the event source (in the oop_source structure) or by the user.
on_fd
After this function is called, whenever the source's event loop detects the condition indicated by event (OOP_READ, OOP_WRITE, or OOP_EXCEPTION*) on the file descriptor fd, it will call the function call, passing it a pointer to the event source, the file descriptor, the event type, and the same opaque user 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.

cancel_fd
Deactivate an event sink callback registered using on_fd (above). Any callback associated with the (event,fd) pair in question is removed.

oop_call_fd
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.

* Compatibility note: OOP_EXCEPTION is only available in version 0.7 or newer.


liboop reference liboop.org/oop_tcl.html000644 001750 001750 00000002430 11030416547 016303 0ustar00magnusmagnus000000 000000 liboop: oop_tcl_new(), oop_tcl_delete()

oop_tcl_new(), oop_tcl_delete()

#include <oop.h>
#include <oop-tcl.h>

oop_source *oop_tcl_new();
void oop_tcl_delete();

Description.

oop_tcl_new
Create a liboop source which uses the Tcl event loop 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.

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.

oop_tcl_delete
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.


liboop reference liboop.org/how.html000644 001750 001750 00000007616 11030416547 015454 0ustar00magnusmagnus000000 000000 liboop: How?

Overview of liboop.

The basic idea.

Liboop is primarily an interface definition. It defines an interface which components may use to request notification when an event (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 event source. Components which are interested in events register themselves with the event source; they are event sinks. Event sinks may themselves source other, higher-level events, but that is outside liboop's scope.

Control flow.

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 callback to all the event sinks which registered interest in that event.

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.

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.

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.

The system event source.

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.

Adapters.

Liboop supports adapters 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 source adapters 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.

Similarly, some components are designed to work in a non-blocking fashion, and they might be used with a sink adapter 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.

Code.

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.

For more about the liboop interface, see the reference.


liboop home liboop.org/oop_rl.html000644 001750 001750 00000003141 11030416547 016136 0ustar00magnusmagnus000000 000000 liboop: oop_readline_register(), oop_readline_cancel()

oop_readline_register(), oop_readline_cancel()

#include <oop.h>
#include <oop-rl.h>

void oop_readline_register(oop_source *source);
void oop_readline_cancel(oop_source *source);

Arguments.

oop_source *source
The event source to use. The adapter will use this event source to wait asynchronously for console input.

Description.

oop_readline_register
Register a liboop source with the GNU Readline Library. The adapter responds asynchronously to console input and notifies Readline when it arrives via rl_callback_read_char(). You should use the Readline alternate interface to prompt the user and receive input.

Note well that Readline will install its own signal handlers by default. Make sure to disable this behavior by setting rl_catch_signals to zero if you wish to manage signals with liboop.

oop_readline_cancel
Unregister liboop with Readline. After this is called, rl_readback_read_char() will no longer be invoked automatically.


liboop reference liboop.org/oop_glib.html000644 001750 001750 00000003464 11030416547 016446 0ustar00magnusmagnus000000 000000 liboop: oop_glib_new(), oop_glib_delete(), oop_glib_return()

oop_glib_new(), oop_glib_delete(), oop_glib_return()

#include <oop.h>
#include <glib.h>
#include <oop-glib.h>

oop_source *oop_glib_new();
void oop_glib_delete();
void *oop_glib_return();

Description.

oop_glib_new
Create a liboop source which uses the GLib Main Event Loop 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.

Events will be dispatched when the GLib event loop is run, either directly via g_main_run() or indirectly via gtk_main().

oop_glib_delete
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.

oop_glib_return
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.

This function isn't commonly used. Furthermore, GLib event loop termination does not currently work. In other words, ignore this for now.


liboop reference liboop.org/oop_adns.html000644 001750 001750 00000003744 11030416547 016457 0ustar00magnusmagnus000000 000000 liboop: oop_adns_new(), oop_adns_delete()

oop_adns_new(), oop_adns_delete()

#include <oop.h>
#include <adns.h>
#include <oop-adns.h>

oop_adapter_adns *oop_adns_new(oop_source *source,adns_initflags flags,FILE *diag);
void oop_adns_delete(oop_adapter_adns *adapter);

Arguments.

oop_source *source
The event source to use. The adapter will use this event source to wait asynchronously for network communication.

adns_initflags flags
Any initialization flags used to create the instance of adns. Refer to the adns documentation for details.

FILE *diag
The file to send adns diagnostics to. Refer to the adns documentation for details.

oop_adapter_adns *adapter
An adns adapter to delete, with no outstanding queries.

Description.

oop_adns_new
Create a new liboop adns adapter. This adapter manages an instance of Ian Jackson's asychronous DNS resolver and supplies it with events from source. The adns instance is initialized with the supplied flags and diag file; refer to the adns documentation for details.

If a malloc failure or other catastrophic system error occurs creating the adapter, NULL is returned. The caller must handle this failure.

oop_adns_delete
Destroy the liboop adns adapter adns. 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.


liboop reference liboop.org/on_time.html000644 001750 001750 00000005141 11030416547 016300 0ustar00magnusmagnus000000 000000 liboop: on_time(), cancel_time()

on_time(), cancel_time()

#include <oop.h>
#include <sys/time.h>

/* Zero time, for scheduling an event immediately. */
static const struct timeval OOP_TIME_NOW = { 0, 0 };

/* Callback function prototype. */
typedef void *oop_call_time(oop_source *source,struct timeval tv,void *user);

/* Register and unregister time-triggered event sinks. */
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);

Arguments.

oop_source *source
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->on_time(src,...);".

struct timeval tv
The time to wait for. OOP_TIME_NOW (or any time in the past) will cause immediate scheduling.

oop_call_time *call
The callback function (event sink) to add (or remove).

void *user
User data passed through to the callback function.

Description.

Note that these are not global functions, but function pointers supplied by the event source (in the oop_source structure) or by the user.
on_time
After this function is called, when the event loop is running and the time tv 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 call, passing it a pointer to the event source, the scheduled time, and the same opaque user pointer passed to on_time. This callback will only be called once. Many callbacks may be registered for the same time.

cancel_time
Deactivate an event sink callback registered using on_time (above). If the passed tv, call and user 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.

oop_call_time
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.

liboop reference liboop.org/on_signal.html000644 001750 001750 00000005035 11030416547 016621 0ustar00magnusmagnus000000 000000 liboop: on_signal(), cancel_signal()

on_signal(), cancel_signal()

#include <oop.h>
#include <signal.h>

/* Callback function prototype. */
typedef void *oop_call_signal(oop_source *source,int sig,void *user);

/* Register and unregister UNIX signal event sinks. */
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);

Arguments.

oop_source *source
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->on_signal(src,...);".

int sig
The UNIX signal to monitor (SIGINT, SIGHUP, etc.).

oop_call_signal *call
The callback function (event sink) to add (or remove).

void *user
User data passed through to the callback function.

Description.

Note that these are not global functions, but function pointers supplied by the event source (in the oop_source structure) or by the user.
on_signal
After this function is called, if the signal sig is received, when the event loop next runs (immediately, if it is currently waiting for events), the event source will call the function call, passing it a pointer to the event source, the signal received, and the same opaque user 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.

cancel_signal
Deactivate an event sink callback registered using on_signal (above). If the passed sig, call and user 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.

oop_call_fd
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.

liboop reference liboop.org/oop_sys_source.html000644 001750 001750 00000001736 11030416547 017727 0ustar00magnusmagnus000000 000000 liboop: oop_sys_source()

oop_sys_source()

#include <oop.h>

/* Get the source interface for a system event source. */
oop_source *oop_sys_source(oop_source_sys *sys);

Arguments.

oop_source_sys *sys
The event source from which to fetch the interface.

Description.

This function returns the standard oop_source interface for the system event source sys. 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.


liboop reference liboop.org/index.html000644 001750 001750 00000011605 11030416547 015757 0ustar00magnusmagnus000000 000000 liboop home page liboop

Liboop is a low-level event loop management library for POSIX-based operating systems. It supports the development of modular, multiplexed applications which may respond to events from several sources. It replaces the "select() loop" and allows the registration of event handlers for file and network I/O, timers and signals. Since processes use these mechanisms for almost all external communication, liboop can be used as the basis for almost any application.

Liboop is licensed under the Lesser General Public License.

Similar free software includes the GLib Main Event Loop, Niels Provos' libevent, and (for Perl) POE. Refer to the rationale for a detailed comparison.

Software which uses or supports liboop includes lsh, RULI, lyskom-server, Gale and GDN. (Let me know if I'm missing any.)

Download.

Get the latest version. Read the included INSTALL file.

You may also browse the CVS repository for source code or documentation.

Documentation.

Extended rationale
Why everyone should be using liboop.
Introduction and overview
How liboop works; basic principles of operation.
Reference
Specific functions and data structures.

News.

27 October 2003
Version 1.0 released. (The number has no special meaning, it's just the next increment.) The build is little more robust now, and you can enable and disable specific adapters in the configure script. The ADNS adapter returns error messages, the GLib adapter works with GLib 2, and there's a new oop_sys_run_once() function so you can poll an event source.

11 January 2003
Version 0.9 released. A memory leak when creating and destroying the system event source was fixed, the robustness of signal handling is improved, and some minor portability problems were fixed.

18 September 2001
Version 0.8 released, including a source adapter for Tcl/Tk. (0.7 was never announced.)

7 October 2000
Version 0.6 released, including a sink adapter for the GNU Readline Library.

5 September 1999
Version 0.4 released. Besides the usual bug fixes, the file descriptor deregistration interface changed, and we now have a source adapter for GLib, and a sink adapter for the W3C Protocol Library (libwww)! The test/sample program (test-oop) is also quite improved.

15 August 1999
Version 0.3 released. This version includes an adapter for Ian Jackson's asynchronous DNS resolver library.

Note that while liboop is covered by the lesser GPL, ADNS is covered by the full GPL, and therefore any program which uses ADNS with (or without) liboop must support distribution under the terms of the full GPL.

1 August 1999
Version 0.2 released. This release fixes several bugs, uses autoconf, automake and libtool, and includes an interface for using alternate memory allocation functions. Gale now uses liboop!

5 July 1999
Version 0.1 released. This is a very, very simple initial release that should nevertheless work as a functional event loop. No adapters are included yet. Testing is minimal, but give it a whirl!

Dan Egnor (egnor @ ofb.net) liboop.org/oop_sys.html000644 001750 001750 00000003075 11030416547 016345 0ustar00magnusmagnus000000 000000 liboop: oop_sys_new(), oop_sys_delete()

oop_sys_new(), oop_sys_delete()

#include <oop.h>

/* Create and destroy a system event source. */
oop_source_sys *oop_sys_new(void);
void oop_sys_delete(oop_source_sys *sys);

Arguments.

oop_source_sys *sys
The event source to deallocate and destroy.

Description.

oop_sys_new
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 oop_sys_source() to access the event source interface (which lets you register event sinks), and oop_sys_run() or oop_sys_run_once() 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).

If a malloc failure occurs creating the system event source, NULL is returned. It is up to the caller to handle this failure.

oop_sys_delete
Destroy the system event source sys. This frees all resources associated with the event source. The source cannot have any active callbacks (event sinks) associated with it.


liboop reference liboop.org/oop_adns_query.html000644 001750 001750 00000006513 11030416547 017701 0ustar00magnusmagnus000000 000000 liboop: oop_adns_submit(), oop_adns_cancel()

oop_adns_submit(), oop_adns_cancel()

#include <oop.h>
#include <adns.h>
#include <oop-adns.h>

/* Callback function prototype. */
typedef void *oop_adns_call(oop_adapter_adns *adapter,adns_answer *answer,void *data);

/* Submit an asynchronous DNS query. */
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);

/* Cancel a running query. */
void oop_adns_cancel(oop_adns_query *query);

Arguments.

oop_adapter_adns *adns
The adns adapter to use for the query.

adns_answer *answer
The answer to the query (status and RR data). Refer to the adns documentation for details.

const char *owner
The DNS domain name to query.

adns_rrtype type
The DNS Resource Record type to query. Refer to the adns documentation for the list of valid RR types.

adns_queryflags flags
Flags for the DNS query. Refer to the adns documentation for details.

oop_call_fd *call
The callback function (event sink) to use for reporting query succcess or failure.

void *user
User data passed through to the callback function.

oop_adns_query *query
The query to cancel.

Description.

oop_adns_submit
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.

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.)

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).

oop_adns_cancel
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.

oop_adns_call
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.

liboop reference liboop.org/ref.html000644 001750 001750 00000013635 11030416547 015431 0ustar00magnusmagnus000000 000000 liboop: Reference

Liboop Reference.

Event Source Interface.

#include <oop.h>

/* Applications can set these; liboop libraries will use them. */
extern void *(*oop_malloc)(size_t); /* returns NULL on failure */
extern void *(*oop_realloc)(void *,size_t); /* returns NULL on failure */
extern void (*oop_free)(void *);

typedef struct oop_source oop_source;
struct oop_source {
    /* File descriptor activity events. */
    void (*on_fd)(oop_source *,int fd,oop_event,oop_call_fd *,void *);
    void (*cancel_fd)(oop_source *,int fd,oop_event);

    /* Timer events. */
    void (*on_time)(oop_source *,struct timeval,oop_call_time *,void *);
    void (*cancel_time)(oop_source *,struct timeval,oop_call_time *,void *);

    /* UNIX signal events. */
    void (*on_signal)(oop_source *,int sig,oop_call_signal *,void *);
    void (*cancel_signal)(oop_source *,int sig,oop_call_signal *,void *);
};

System Event Source.

typedef struct oop_source_sys oop_source_sys;

/* Create and destroy a system event source. */
oop_source_sys *oop_sys_new(void); /* returns NULL on failure */
void oop_sys_delete(oop_source_sys *);

/* Run the system event loop. */
void *oop_sys_run(oop_source_sys *);
void *oop_sys_run_once(oop_source_sys *);

/* Get the standard source interface for a system event source. */
oop_source *oop_sys_source(oop_source_sys *);

ADNS Event Sink Adapter.

Please note that while the core of liboop is distributed under the Lesser GPL, ADNS is covered by the full GPL.

#include <adns.h>
#include <oop-adns.h>

typedef struct oop_adapter_adns oop_adapter_adns;
typedef struct oop_adns_query oop_adns_query;

/* Create and destroy a liboop adns adapter, including an instance of adns. */
oop_adapter_adns *oop_adns_new(oop_source *,adns_initflags,FILE *diag); /* returns NULL on failure */
void oop_adns_delete(oop_adapter_adns *);

/* Submit an asynchronous DNS query. */
oop_adns_query *oop_adns_submit( /* returns NULL on failure */
        oop_adapter_adns *,
        const char *owner,adns_rrtype type,adns_queryflags flags,
        oop_adns_call *,void *);

/* Cancel a running query. */
void oop_adns_cancel(oop_adns_query *);

GLib Event Source Adapter.

GLib is copyrighted by Peter Mattis, Spencer Kimball and Josh MacDonald, and licensed under the terms of the GNU Library GPL.

#include <glib.h>
#include <oop-glib.h>

/* Create and destroy a liboop GLib adapter. */
oop_source *oop_glib_new();
void oop_glib_delete();

/* Get the value used to terminate the event loop (e.g. OOP_HALT). */
void *oop_glib_return();

Tcl/Tk Event Source Adapter.

Tcl is copyrighted by the Regents of the University of California, Sun Microsystems, Inc., and other parties.

#include <oop-tcl.h>

/* Create and destroy a liboop Tcl adapter. */
oop_source *oop_tcl_new();
void oop_tcl_delete();

Libwww Event Sink Adapter.

Libwww is covered by this copyright notice and distributed under the terms of the W3C Software License.

#include <HTEvent.h>
#include <oop-www.h>

/* Register a liboop event source as a libwww "event manager". */
void oop_www_register(oop_source *);

/* Unregister the event source, leaving libwww with no event manager.
   This function cannot be executed with outstanding event requests. */
void oop_www_cancel();

/* Use libwww for liboop's oop_malloc, oop_realloc, and oop_free.
   If you use this, you must call it before any other liboop function! */
void oop_www_memory();

GNU Readline Library Event Sink Adapter.

Please note that while the core of liboop is distributed under the Lesser GPL, Readline is covered by the full GPL.

#include <oop-rl.h>

/* 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(). */
void oop_readline_register(oop_source *);

/* Stop notifying readline of input characters. */
void oop_readline_cancel(oop_source *);

liboop home liboop.org/logo000644 001750 001750 00000004466 07174561405 014664 0ustar00magnusmagnus000000 000000 PNG  IHDR28IDATx՚{pT?7,!@HBI7)(AhQT`"t|@igP P2Ag HBI6{O{7Mh"4=WtHNp f%SMr͢%!f˂G}Tm\i ڕ LA %w;S` p !{mB`A0"}S ]?쏼_σ fʛ%:sĄsli59h!:DJfF0y+B]m%j,ԁ513u[MPaIazn;1юƫsK5@CgddǮ`ŏ}&5lPʷJw*3n6O9mX%#ts}=F=#~d17ߵ.C3uUY!9BӕQo,K%U:JW"67)SԶ~˒,˄op]2ZoD Nq{:ۡHY"0{SB ^|}Ikb}"n@r9oP~w8-y4@C w߱O:aTchOhY{^=7jO'[KxMP*^')} )5@=\lTȑ9\iE^?bL B8J /+ yk8yfuLP &9E^ BTUUuTٍ['Gqn{caW敩-s?Vŵdq?@EYBl[7GFa P Ż&.1j PiG_/O9Jf^TWDz '8R T2qZU narAtePo1h)w-cjk-@{J"-hu u1<2"At%ݠ˔p 04]|mӬ{, M$@Rwk)d${7oR X W4}'CL9 HّAtp,Wvt|8ʼn- E<e RkK5Z} 0e^`v&oꔞ,`gG[ 7~スt3/t$3h֧6ڥݨp9'vv! 393V@B&m$? Hm)I@q^_Q^ t ]@tZNZ5iږZ|ˣ guc$UYzo5:J¥@rR8͢[uZ=Qc|ĵR}+ j"?`@S\y˦򔆲,BVWnHBPp>*>`Ymr|p8r:)%ۙ7? rCN_gV|m֩B|+/Tu4 -%--t#~4Ƨ%*4ZQꑈ4]ѕImKR5 pVFY+6avHhQ20:S!r(=]tWG}?sjmʔՎ+(OKز?~cUN4D9uо9/6{u{J\҂T;O+?_ʖ nj;t.k-.|@~wO_g,RڑG7pKR1И2u `uX96>7"=Ƈ]!ZBJd]!VjcE" ySIENDB`liboop.org/style.css000644 001750 001750 00000000711 11030416337 015625 0ustar00magnusmagnus000000 000000 BODY { color: black; background-color: white; background-image: none; } H1 { color: #0000FF; } H2 { color: #0000BF; } H3 { color: #00009F; } H4 { color: #00009F; } # A:link { color: #004080; } # A:visited { color: #804080; } .heading { color: #00009F; font-weight: bold; } .divider { margin-top: 6pt; font-weight: bold; } .items { margin-left: 10pt; } TH { background: lightgrey; font-weight: bold; text-align: center; } TD { vertical-align: top; }