<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://wiki.darenet.org/skins/common/feed.css?12"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title>ircu api - events - Revision history</title>
		<link>http://wiki.darenet.org/index.php?title=ircu_api_-_events&amp;action=history</link>
		<description>Revision history for this page on the wiki</description>
		<language>en</language>
		<generator>MediaWiki 1.15.1</generator>
		<lastBuildDate>Wed, 20 May 2026 06:14:45 GMT</lastBuildDate>
		<item>
			<title>Secretagent:&amp;#32;New page: &lt;pre&gt;The IRC server is built around an event loop.  Until the u2.10.11 release, this event loop has been rather ad-hoc; timed events are hard-coded in, signals are handled inside the signa...</title>
			<link>http://wiki.darenet.org/index.php?title=ircu_api_-_events&amp;diff=2267&amp;oldid=prev</link>
			<description>&lt;p&gt;New page: &amp;lt;pre&amp;gt;The IRC server is built around an event loop.  Until the u2.10.11 release, this event loop has been rather ad-hoc; timed events are hard-coded in, signals are handled inside the signa...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre&amp;gt;The IRC server is built around an event loop.  Until the u2.10.11&lt;br /&gt;
release, this event loop has been rather ad-hoc; timed events are&lt;br /&gt;
hard-coded in, signals are handled inside the signal handler, etc.&lt;br /&gt;
All of this has changed with u2.10.11.  A new subsystem, the events&lt;br /&gt;
subsystem, has been introduced; the new subsystem contains a&lt;br /&gt;
generalization of the concept of an event.  An event is a signal, the&lt;br /&gt;
expiration of a timer, or some form of activity on a network socket.&lt;br /&gt;
This new subsystem has the potential to vastly simplify the code that&lt;br /&gt;
is arguably the core of any network program, and makes it much simpler&lt;br /&gt;
to support more exotic forms of network activity monitoring than the&lt;br /&gt;
conventional select() and poll() calls.&lt;br /&gt;
&lt;br /&gt;
The primary concepts that the events subsystem works with are the&lt;br /&gt;
&amp;quot;event,&amp;quot; represented by a struct Event, and the &amp;quot;generator.&amp;quot;  There&lt;br /&gt;
are three types of generators: sockets, represented by struct Socket;&lt;br /&gt;
signals, represented by struct Signal; and timers, represented by&lt;br /&gt;
struct Timer.  Each of these generators will be described in turn.&lt;br /&gt;
&lt;br /&gt;
Signals&lt;br /&gt;
&lt;br /&gt;
The signal is perhaps the simplest generator in the entire events&lt;br /&gt;
subsystem.  Basically, instead of setting a signal handler, the&lt;br /&gt;
function signal_add() is called, specifying a function to be called&lt;br /&gt;
when a given signal is detected.  Most importantly, that call-back&lt;br /&gt;
function is called _outside_ the context of a signal handler,&lt;br /&gt;
permitting the call-back to use more exotic functions that are&lt;br /&gt;
anathema within a signal handler, such as MyMalloc().  Once a&lt;br /&gt;
call-back for a signal has been established, it cannot be deleted;&lt;br /&gt;
this design decision was driven by the fact that ircd never changes&lt;br /&gt;
its signal handlers.&lt;br /&gt;
&lt;br /&gt;
Whenever a signal is received, an event of type ET_SIGNAL is&lt;br /&gt;
generated, and that event is passed to the event call-back function&lt;br /&gt;
specified in the signal_add() call.&lt;br /&gt;
&lt;br /&gt;
Timers&lt;br /&gt;
&lt;br /&gt;
Execution of the call-back functions for a timer occur when that timer&lt;br /&gt;
_expires_; when a timer expires depends on the type of timer and the&lt;br /&gt;
expiration time that was used for that timer.  A TT_ABSOLUTE timer,&lt;br /&gt;
for instance, expires at exactly the time given as the expiration&lt;br /&gt;
time.  This time is a standard UNIX time_t value, measuring seconds&lt;br /&gt;
since the UNIX epoch.  The TT_ABSOLUTE timer type is complemented by&lt;br /&gt;
the TT_RELATIVE timer; the time passed as its expiration time is&lt;br /&gt;
relative to the current time.  If a TT_RELATIVE timer is given an&lt;br /&gt;
expiration time of 5, for instance, it will expire 5 seconds after the&lt;br /&gt;
present time.  Internally, TT_RELATIVE timers are converted into&lt;br /&gt;
TT_ABSOLUTE timers, with the expiration time adjusted by addition of&lt;br /&gt;
the current time.&lt;br /&gt;
&lt;br /&gt;
Those two types of timers, TT_ABSOLUTE and TT_RELATIVE, are&lt;br /&gt;
single-shot timers.  Once they expire, they are removed from the timer&lt;br /&gt;
list unless re-added by the event call-back or through some other&lt;br /&gt;
mechanism.  There is another type of timer, however, the TT_PERIODIC&lt;br /&gt;
timer, that is not removed from the timer list.  TT_PERIODIC timers&lt;br /&gt;
are similar to TT_RELATIVE timers, in that one passes in the expire&lt;br /&gt;
time as a relative number of seconds, but when they expire, they are&lt;br /&gt;
re-added to the timer list with the same relative expire time.  This&lt;br /&gt;
means that a TT_PERIODIC timer with an expire time of 5 seconds that&lt;br /&gt;
is set at 11:50:00 will have its call-back called at 11:50:05,&lt;br /&gt;
11:50:10, 11:50:15, and so on.&lt;br /&gt;
&lt;br /&gt;
Timers have to be run by the event engines explicitly by calling&lt;br /&gt;
timer_run() on the generator list passed to the engine event loop.&lt;br /&gt;
In addition, engines may determine the next (absolute) time that a&lt;br /&gt;
timer needs to be run by calling the timer_next() macro; this may be&lt;br /&gt;
used to set a timeout on the engine's network activity monitoring&lt;br /&gt;
function.  Engines are described in detail below.&lt;br /&gt;
&lt;br /&gt;
When a timer expires, an event of ET_EXPIRE is generated, and the&lt;br /&gt;
call-back function is called.  When a timer is destroyed, either as&lt;br /&gt;
the result of an expiration or as a result of an explicit timer_del()&lt;br /&gt;
call, an event of ET_DESTROY is generated, notifying the call-back&lt;br /&gt;
that the struct Timer can be deallocated.&lt;br /&gt;
&lt;br /&gt;
Sockets&lt;br /&gt;
&lt;br /&gt;
Perhaps the most complicated event generator in all of the event&lt;br /&gt;
system is the socket, as described by struct Socket.  This single&lt;br /&gt;
classification covers datagram sockets and stream sockets.  To&lt;br /&gt;
differentiate the different kinds of sockets, there is a socket state&lt;br /&gt;
associated with each socket.  The available states are SS_CONNECTING,&lt;br /&gt;
which indicates that a particular socket is in the process of&lt;br /&gt;
completing a non-blocking connect(); SS_LISTENING, which indicates&lt;br /&gt;
that a particular socket is a listening socket; SS_CONNECTED, which is&lt;br /&gt;
the state of every other stream socket; SS_DATAGRAM, which is an&lt;br /&gt;
ordinary datagram socket, and SS_CONNECTDG, which describes a&lt;br /&gt;
connected datagram socket.  (The SS_NOTSOCK state is for the internal&lt;br /&gt;
use of the events system and will not be described here.)&lt;br /&gt;
&lt;br /&gt;
In addition to the socket states, there's also an event mask for each&lt;br /&gt;
socket; this set of flags is used to tell the events subsystem what&lt;br /&gt;
events the application is interested in for the socket.  For&lt;br /&gt;
SS_CONNECTING and SS_LISTENING sockets, this events mask has no&lt;br /&gt;
meaning, but on the other socket states, the event mask is used to&lt;br /&gt;
determine if the application is interested in readable&lt;br /&gt;
(SOCK_EVENT_READABLE) or writable (SOCK_EVENT_WRITABLE) indications.&lt;br /&gt;
&lt;br /&gt;
Most of the defined event types have to do with socket generators.&lt;br /&gt;
When a socket turns up readable, for instance, an event of type&lt;br /&gt;
ET_READ is generated.  Similarly, ET_WRITE is generated when a socket&lt;br /&gt;
can be written to.  The ET_ACCEPT event is generated when a listening&lt;br /&gt;
socket indicates that there is a connection to be accepted; ET_CONNECT&lt;br /&gt;
is generated when a non-blocking connect is completed.  Finally, if an&lt;br /&gt;
end-of-file indication is detected, ET_EOF is generated, whereas if an&lt;br /&gt;
error has occurred on the socket, ET_ERROR is generated.  Of course,&lt;br /&gt;
when a socket has been deleted by the socket_del() function, an event&lt;br /&gt;
of ET_DESTROY is generated when it is safe for the memory used by the&lt;br /&gt;
struct Socket to be reclaimed.&lt;br /&gt;
&lt;br /&gt;
Events&lt;br /&gt;
&lt;br /&gt;
An event, represented by a struct Event, describes in detail all of&lt;br /&gt;
the particulars of an event.  Each event has a type, and an optional&lt;br /&gt;
integer piece of data may be passed with some events--in particular,&lt;br /&gt;
ET_SIGNAL events pass the signal number, and ET_ERROR events pass the&lt;br /&gt;
errno value.  The struct Event also contains a pointer to the&lt;br /&gt;
structure describing the generated event--although it should be noted&lt;br /&gt;
that the only way to disambiguate which type of generator is contained&lt;br /&gt;
within the struct Event is by which call-back function has been&lt;br /&gt;
called.&lt;br /&gt;
&lt;br /&gt;
All generators have a void pointer which can be used to pass important&lt;br /&gt;
information to the call-back, such as a pointer to a struct Client.&lt;br /&gt;
Additionally, generators have a reference count, and a union of a void&lt;br /&gt;
pointer and an integer that should only be utilized by the event&lt;br /&gt;
engine.  Finally, there is also a field for flags, although the only&lt;br /&gt;
flag of concern to the application (or the engine) is the active flag,&lt;br /&gt;
which may be tested using the test macros described below.&lt;br /&gt;
&lt;br /&gt;
Whatever the generator, the call-back function is a function returning&lt;br /&gt;
nothing (void) and taking as its sole argument a pointer to struct&lt;br /&gt;
Event.  This call-back function may be implemented as a single switch&lt;br /&gt;
statement that calls out to appropriate external functions as needed.&lt;br /&gt;
&lt;br /&gt;
Engines&lt;br /&gt;
&lt;br /&gt;
Engines implement the actual socket event loop, and may also have some&lt;br /&gt;
means of receiving signal events.  Each engine has a name, which&lt;br /&gt;
should describe what its core function is; for instance, the engine&lt;br /&gt;
based on the standard select() function is named, simply, &amp;quot;select().&amp;quot;&lt;br /&gt;
Each engine must implement several call-backs which are used to&lt;br /&gt;
initialize the engine, notify the engine of sockets the application is&lt;br /&gt;
interested in, etc.  All of this data is described by a single struct&lt;br /&gt;
Engine, which should be the only non-static variable or function in&lt;br /&gt;
the engine's source file.&lt;br /&gt;
&lt;br /&gt;
The engine's event loop, pointed to by the eng_loop field of the&lt;br /&gt;
struct Engine, must consist of a single while loop predicated on the&lt;br /&gt;
global variable _running_.  Additionally, this loop's final statement&lt;br /&gt;
must be a call to timer_run(), to execute all timers that have become&lt;br /&gt;
due.  Ideally, this construction should be pulled out of each engine's&lt;br /&gt;
eng_loop and put in the event_loop() function of the events&lt;br /&gt;
subsystem.&lt;br /&gt;
&lt;br /&gt;
Reference Counts&lt;br /&gt;
&lt;br /&gt;
As mentioned previously, all generators keep a reference count.&lt;br /&gt;
Should timer_del() or socket_del() be called on a generator with a&lt;br /&gt;
non-zero reference count, for whatever reason, the actual destruction&lt;br /&gt;
of the generator will be delayed until the reference count again&lt;br /&gt;
reaches zero.  This is used by the event loop to keep sockets that it&lt;br /&gt;
is currently referencing from being deallocated before it is done&lt;br /&gt;
checking all pending events on them.  To increment the reference count&lt;br /&gt;
by one, call gen_ref_inc() on the generator; the corresponding macro&lt;br /&gt;
gen_ref_dec() decrements the reference counts, and will automatically&lt;br /&gt;
destroy the generator if the appropriate conditions are met.&lt;br /&gt;
&lt;br /&gt;
Debugging Functions&lt;br /&gt;
&lt;br /&gt;
It can be difficult to debug an engines if, say, a socket state can&lt;br /&gt;
only be expressed as a meaningless number.  Therefore, when DEBUGMODE&lt;br /&gt;
is #define'd, five number-to-name functions are also defined to make&lt;br /&gt;
the debugging data more meaningful.  These functions must only be&lt;br /&gt;
called when DEBUGMODE is #define'd.  Calling them from within Debug()&lt;br /&gt;
macro calls is safe; calling them from log_write() calls is not.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;typedef&amp;gt;&lt;br /&gt;
typedef void (*EventCallBack)(struct Event*);&lt;br /&gt;
&lt;br /&gt;
The _EventCallBack_ type is used to simplify declaration of event&lt;br /&gt;
call-back functions.  It is used in timer_add(), signal_add(), and&lt;br /&gt;
socket_add().  The event call-back should process the event, taking&lt;br /&gt;
whatever actions are necessary.  The function should be declared as&lt;br /&gt;
returning void.&lt;br /&gt;
&amp;lt;/typedef&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;typedef&amp;gt;&lt;br /&gt;
typedef int (*EngineInit)(int);&lt;br /&gt;
&lt;br /&gt;
The _EngineInit_ function takes an integer specifying the maximum&lt;br /&gt;
number of sockets the event system is expecting to handle.  This&lt;br /&gt;
number may be used by the engine initialization function for memory&lt;br /&gt;
allocation computations.  If initialization succeeds, this function&lt;br /&gt;
must return 1.  If initialization fails, the function should clean up&lt;br /&gt;
after itself and return 0.  The events subsystem has the ability to&lt;br /&gt;
fall back upon another engine, should an engine initialization fail.&lt;br /&gt;
Needless to say, the engines based upon poll() and select() should&lt;br /&gt;
never fail in this way.&lt;br /&gt;
&amp;lt;/typedef&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;typedef&amp;gt;&lt;br /&gt;
typedef void (*EngineSignal)(struct Signal*);&lt;br /&gt;
&lt;br /&gt;
If an engine has the capability to directly detect signals, it should&lt;br /&gt;
set the eng_signal field of struct Engine non-zero.  When the&lt;br /&gt;
application indicates interest in a particular signal, the&lt;br /&gt;
_EngineSignal_ function will be called with the filled-in struct&lt;br /&gt;
Signal, in order to register interest in that signal with the engine.&lt;br /&gt;
&amp;lt;/typedef&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;typedef&amp;gt;&lt;br /&gt;
typedef int (*EngineAdd)(struct Socket*);&lt;br /&gt;
&lt;br /&gt;
All engines must define an _EngineAdd_ function, which is used to&lt;br /&gt;
inform the engine of the application's interest in the socket.  If the&lt;br /&gt;
new socket cannot be accommodated by the engine for whatever reason,&lt;br /&gt;
this function must return 0.  Otherwise, the function must return 1,&lt;br /&gt;
informing the events subsystem that the interest has been noted.&lt;br /&gt;
&amp;lt;/typedef&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;typedef&amp;gt;&lt;br /&gt;
typedef void (*EngineState)(struct Socket*, enum SocketState new_state);&lt;br /&gt;
&lt;br /&gt;
Sockets can change state.  SS_CONNECTING sockets, for instance, can&lt;br /&gt;
become SS_CONNECTED.  Whenever a socket state changes, the engine is&lt;br /&gt;
informed, since some states require different notification procedures&lt;br /&gt;
than others.  This is accomplished by calling the _EngineState_&lt;br /&gt;
function with the new state.  The struct Socket passed to the engine&lt;br /&gt;
will still have the old state, if the engine must reference that.&lt;br /&gt;
&amp;lt;/typedef&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;typedef&amp;gt;&lt;br /&gt;
typedef void (*EngineEvents)(struct Socket*, unsigned int new_events);&lt;br /&gt;
&lt;br /&gt;
Applications may only be interested in given events on a socket for a&lt;br /&gt;
limited time.  When the application's interest shifts, a new events&lt;br /&gt;
mask is set for the socket.  The engine is informed of this change by&lt;br /&gt;
a call to its _EngineEvents_ function.&lt;br /&gt;
&amp;lt;/typedef&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;typedef&amp;gt;&lt;br /&gt;
typedef void (*EngineDelete)(struct Socket*);&lt;br /&gt;
&lt;br /&gt;
Eventually, an application will close all the sockets it has opened.&lt;br /&gt;
When a socket is closed, and the corresponding struct Socket deleted&lt;br /&gt;
with a call to socket_del(), the _EngineDelete_ function will be&lt;br /&gt;
called to notify the engine of the change.&lt;br /&gt;
&amp;lt;/typedef&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;typedef&amp;gt;&lt;br /&gt;
typedef void (*EngineLoop)(struct Generators*);&lt;br /&gt;
&lt;br /&gt;
The workhorse of the entire events subsystem is the event loop,&lt;br /&gt;
implemented by each engine as the _EngineLoop_ function.  This&lt;br /&gt;
function is called with a single argument that may be passed to&lt;br /&gt;
timer_next() to calculate the next time a timer will expire.&lt;br /&gt;
&amp;lt;/typedef&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;enum&amp;gt;&lt;br /&gt;
enum SocketState {&lt;br /&gt;
  SS_CONNECTING,	/* Connection in progress on socket */&lt;br /&gt;
  SS_LISTENING,		/* Socket is a listening socket */&lt;br /&gt;
  SS_CONNECTED,		/* Socket is a connected socket */&lt;br /&gt;
  SS_DATAGRAM,		/* Socket is a datagram socket */&lt;br /&gt;
  SS_CONNECTDG,		/* Socket is a connected datagram socket */&lt;br /&gt;
  SS_NOTSOCK		/* Socket isn't a socket at all */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
This enumeration contains a list of all possible states a socket can&lt;br /&gt;
be in.  Applications should not use SS_NOTSOCK; engines should treat&lt;br /&gt;
it as a special socket state for non-sockets.  The only event that&lt;br /&gt;
should be watched for on a struct Socket in the SS_NOTSOCK state is&lt;br /&gt;
readability.  This socket state is used to implement the fall-back&lt;br /&gt;
signal event generation.&lt;br /&gt;
&amp;lt;/enum&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;enum&amp;gt;&lt;br /&gt;
enum TimerType {&lt;br /&gt;
  TT_ABSOLUTE,		/* timer that runs at a specific time */&lt;br /&gt;
  TT_RELATIVE,		/* timer that runs so many seconds in the future */&lt;br /&gt;
  TT_PERIODIC		/* timer that runs periodically */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
The three possible timer types are defined by the TimerType&lt;br /&gt;
enumeration.  More details can be found in the &amp;quot;Timers&amp;quot; sub-section.&lt;br /&gt;
&amp;lt;/enum&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;enum&amp;gt;&lt;br /&gt;
enum EventType {&lt;br /&gt;
  ET_READ,		/* Readable event detected */&lt;br /&gt;
  ET_WRITE,		/* Writable event detected */&lt;br /&gt;
  ET_ACCEPT,		/* Connection can be accepted */&lt;br /&gt;
  ET_CONNECT,		/* Connection completed */&lt;br /&gt;
  ET_EOF,		/* End-of-file on connection */&lt;br /&gt;
  ET_ERROR,		/* Error condition detected */&lt;br /&gt;
  ET_SIGNAL,		/* A signal was received */&lt;br /&gt;
  ET_EXPIRE,		/* A timer expired */&lt;br /&gt;
  ET_DESTROY		/* The generator is being destroyed */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
This enumeration contains all the types of events that can be&lt;br /&gt;
generated by the events subsystem.  The first 6 are generated by&lt;br /&gt;
socket generators, the next by signal generators, and the next by&lt;br /&gt;
timer generators.  ET_DESTROY is generated by both socket and timer&lt;br /&gt;
generators when the events subsystem is finished with the memory&lt;br /&gt;
allocated by both.&lt;br /&gt;
&amp;lt;/enum&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;struct&amp;gt;&lt;br /&gt;
struct Socket;&lt;br /&gt;
&lt;br /&gt;
This structure describes everything the events subsystem knows about a&lt;br /&gt;
given socket.  All of its fields may be accessed through the s_*&lt;br /&gt;
macros described below.&lt;br /&gt;
&amp;lt;/struct&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;struct&amp;gt;&lt;br /&gt;
struct Timer;&lt;br /&gt;
&lt;br /&gt;
The struct Timer structure describes everything the events subsystem&lt;br /&gt;
knows about a given timer.  Again, all of its fields may be accessed&lt;br /&gt;
through the t_* macros described below.&lt;br /&gt;
&amp;lt;/struct&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;struct&amp;gt;&lt;br /&gt;
struct Signal;&lt;br /&gt;
&lt;br /&gt;
Signal generators are described by a struct Signal.  All of the fields&lt;br /&gt;
of a struct Signal may be accessed by the sig_* macros described&lt;br /&gt;
below.&lt;br /&gt;
&amp;lt;/struct&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;struct&amp;gt;&lt;br /&gt;
struct Event;&lt;br /&gt;
&lt;br /&gt;
Each event is described by a struct Event.  Its fields may be examined&lt;br /&gt;
using the ev_* macros described below.&lt;br /&gt;
&amp;lt;/struct&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;struct&amp;gt;&lt;br /&gt;
struct Generators;&lt;br /&gt;
&lt;br /&gt;
Each engine is passed a list of all generators when the engine's&lt;br /&gt;
_EngineLoop_ function is called.  The only valid way to access this&lt;br /&gt;
structure is via the timer_next() function described below.&lt;br /&gt;
&amp;lt;/struct&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;struct&amp;gt;&lt;br /&gt;
struct Engine {&lt;br /&gt;
  const char*	eng_name;	/* a name for the engine */&lt;br /&gt;
  EngineInit	eng_init;	/* initialize engine */&lt;br /&gt;
  EngineSignal	eng_signal;	/* express interest in a signal */&lt;br /&gt;
  EngineAdd	eng_add;	/* express interest in a socket */&lt;br /&gt;
  EngineState	eng_state;	/* mention a change in state to engine */&lt;br /&gt;
  EngineEvents	eng_events;	/* express interest in socket events */&lt;br /&gt;
  EngineDelete	eng_closing;	/* socket is being closed */&lt;br /&gt;
  EngineLoop	eng_loop;	/* actual event loop */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
Each engine is described by the struct Engine structure.  Each engine&lt;br /&gt;
must define all of the functions described above except for the&lt;br /&gt;
_EngineSignal_ function, which is optional.&lt;br /&gt;
&amp;lt;/struct&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;macro&amp;gt;&lt;br /&gt;
#define SOCK_EVENT_READABLE	0x0001	/* interested in readable */&lt;br /&gt;
&lt;br /&gt;
The SOCK_EVENT_READABLE flag indicates to the engine that the&lt;br /&gt;
application is interested in readability on this particular socket.&lt;br /&gt;
&amp;lt;/macro&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;macro&amp;gt;&lt;br /&gt;
#define SOCK_EVENT_WRITABLE	0x0002	/* interested in writable */&lt;br /&gt;
&lt;br /&gt;
The SOCK_EVENT_WRITABLE flag indicates to the engine that the&lt;br /&gt;
application is interested in this socket being writable.&lt;br /&gt;
&amp;lt;/macro&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;macro&amp;gt;&lt;br /&gt;
#define SOCK_EVENT_MASK		(SOCK_EVENT_READABLE | SOCK_EVENT_WRITABLE)&lt;br /&gt;
&lt;br /&gt;
SOCK_EVENT_MASK may be used to extract only the event interest flags&lt;br /&gt;
from an event interest set.&lt;br /&gt;
&amp;lt;/macro&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;macro&amp;gt;&lt;br /&gt;
#define SOCK_ACTION_SET		0x0000	/* set interest set as follows */&lt;br /&gt;
&lt;br /&gt;
When socket_events() is called with a set of event interest flags and&lt;br /&gt;
SOCK_ACTION_SET, the socket's event interest flags are set to those&lt;br /&gt;
passed into socket_events().&lt;br /&gt;
&amp;lt;/macro&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;macro&amp;gt;&lt;br /&gt;
#define SOCK_ACTION_ADD		0x1000	/* add to interest set */&lt;br /&gt;
&lt;br /&gt;
When SOCK_ACTION_ADD is used in a call to socket_events(), the event&lt;br /&gt;
interest flags passed in are added to the existing event interest&lt;br /&gt;
flags for the socket.&lt;br /&gt;
&amp;lt;/macro&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;macro&amp;gt;&lt;br /&gt;
#define SOCK_ACTION_DEL		0x2000	/* remove from interest set */&lt;br /&gt;
&lt;br /&gt;
When SOCK_ACTION_DEL is used in a call to socket_events(), the event&lt;br /&gt;
interest flags passed in are removed from the existing event interest&lt;br /&gt;
flags for the socket.&lt;br /&gt;
&amp;lt;/macro&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;macro&amp;gt;&lt;br /&gt;
#define SOCK_ACTION_MASK	0x3000	/* mask out the actions */&lt;br /&gt;
&lt;br /&gt;
SOCK_ACTION_MASK is used to isolate the socket action desired.&lt;br /&gt;
&amp;lt;/macro&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
enum SocketState s_state(struct Socket* sock);&lt;br /&gt;
&lt;br /&gt;
This macro returns the state of the given socket.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
unsigned int s_events(struct Socket* sock);&lt;br /&gt;
&lt;br /&gt;
This macro returns the current event interest mask for a given&lt;br /&gt;
socket.  Note that if the socket is in the SS_CONNECTING or&lt;br /&gt;
SS_LISTENING states, this mask has no meaning.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
int s_fd(struct Socket* sock);&lt;br /&gt;
&lt;br /&gt;
This macro simply returns the file descriptor for the given socket.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void* s_data(struct Socket* sock);&lt;br /&gt;
&lt;br /&gt;
When a struct Socket is initialized, data that the call-back function&lt;br /&gt;
may find useful, such as a pointer to a struct Connection, is stored&lt;br /&gt;
in the struct Socket.  This macro returns that pointer.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
int s_ed_int(struct Socket* sock);&lt;br /&gt;
&lt;br /&gt;
Engines may find it convenient to associate an integer with a struct&lt;br /&gt;
Socket.  This macro may be used to retrieve that integer or, when used&lt;br /&gt;
as an lvalue, to assign a value to it.  Engine data must be either an&lt;br /&gt;
int or a void*; use of both is prohibited.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void* s_ed_ptr(struct Socket* sock);&lt;br /&gt;
&lt;br /&gt;
Engines may find it convenient to associate a void* pointer with a&lt;br /&gt;
struct Socket.  This macro may be used to retrieve that pointer or,&lt;br /&gt;
when used as an lvalue, to assign a value to it.  Engine data must be&lt;br /&gt;
either an int or a void*; use of both is prohibited.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
int s_active(struct Socket* sock);&lt;br /&gt;
&lt;br /&gt;
A socket's active flag is set when initialized by socket_add(), and is&lt;br /&gt;
cleared immediately prior to generating an event of type ET_DESTROY.&lt;br /&gt;
This may be used by the application to determine whether or not the&lt;br /&gt;
socket is still in use by the events subsystem.  If it is, s_active()&lt;br /&gt;
returns a non-zero value; otherwise, its value is 0.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
int socket_add(struct Socket* sock, EventCallBack call, void* data,&lt;br /&gt;
	       enum SocketState state, unsigned int events, int fd);&lt;br /&gt;
&lt;br /&gt;
This function is called to add a socket to the list of sockets to be&lt;br /&gt;
monitored.  The _sock_ parameter is a pointer to a struct Socket that&lt;br /&gt;
is allocated by the application.  The _call_ parameter is a pointer to&lt;br /&gt;
a function to process any events on the socket.  The _data_ parameter&lt;br /&gt;
is for use of the socket call-back and may be zero.  The _state_&lt;br /&gt;
parameter must be one of the valid socket states.  The _events_&lt;br /&gt;
parameter must be a valid events interest mask--0, or the binary OR of&lt;br /&gt;
SOCK_EVENT_READABLE or SOCK_EVENT_WRITABLE.  Finally, the _fd_&lt;br /&gt;
parameter specifies the socket's file descriptor.  This function&lt;br /&gt;
returns 1 if successful or 0 otherwise.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void socket_del(struct Socket* sock);&lt;br /&gt;
&lt;br /&gt;
When the application is no longer interested in a particular socket,&lt;br /&gt;
it should call the socket_del() function.  This function must be&lt;br /&gt;
called no later than when the socket has been closed, to avoid&lt;br /&gt;
attempting to call select() or similar functions on closed sockets.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void socket_state(struct Socket* sock, enum SocketState state);&lt;br /&gt;
&lt;br /&gt;
Occasionally, a socket's state will change.  This function is used to&lt;br /&gt;
inform the events subsystem of that change.  Only certain state&lt;br /&gt;
transitions are valid--a socket in the SS_LISTENING or SS_CONNECTED&lt;br /&gt;
states cannot change states, nor can an SS_CONNECTING socket change to&lt;br /&gt;
some state other than SS_CONNECTED.  Of course, SS_DATAGRAM sockets&lt;br /&gt;
may change state only to SS_CONNECTDG, and SS_CONNECTDG sockets may&lt;br /&gt;
only change states to SS_DATAGRAM.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void socket_events(struct Socket* sock, unsigned int events);&lt;br /&gt;
&lt;br /&gt;
When the application changes the events it is interested in, it uses&lt;br /&gt;
socket_events() to notify the events subsystem of that change.  The&lt;br /&gt;
_events_ parameter is the binary OR of one of SOCK_ACTION_SET,&lt;br /&gt;
SOCK_ACTION_ADD, or SOCK_ACTION_DEL with an events mask.  See the&lt;br /&gt;
documentation for the SOCK_* macros for more information.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
const char* state_to_name(enum SocketState state);&lt;br /&gt;
&lt;br /&gt;
This function is defined only when DEBUGMODE is #define'd.  It takes&lt;br /&gt;
the given _state_ and returns a string giving that state's name.  This&lt;br /&gt;
function may safely be called from Debug() macros.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
const char* sock_flags(unsigned int flags);&lt;br /&gt;
&lt;br /&gt;
This function is defined only when DEBUGMODE is #define'd.  It takes&lt;br /&gt;
the given event interest flags and returns a string naming each of&lt;br /&gt;
those flags.  This function may safely be called from Debug() macros,&lt;br /&gt;
but may only be called once, since it uses function static storage to&lt;br /&gt;
store the flag strings.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
int sig_signal(struct Signal* sig);&lt;br /&gt;
&lt;br /&gt;
This macro returns the signal number for the given struct Signal.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void* sig_data(struct Signal* sig);&lt;br /&gt;
&lt;br /&gt;
When a struct Signal is initialized, data that the call-back function&lt;br /&gt;
may find useful is stored in the struct Signal.  This macro returns&lt;br /&gt;
that pointer.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
int sig_ed_int(struct Signal* sig);&lt;br /&gt;
&lt;br /&gt;
Engines may find it convenient to associate an integer with a struct&lt;br /&gt;
Signal.  This macro may be used to retrieve that integer or, when used&lt;br /&gt;
as an lvalue, to assign a value to it.  Engine data must be either an&lt;br /&gt;
int or a void*; use of both is prohibited.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void* sig_ed_ptr(struct Signal* sig);&lt;br /&gt;
&lt;br /&gt;
Engines may find it convenient to associate a void* pointer with a&lt;br /&gt;
struct Signal.  This macro may be used to retrieve that pointer or,&lt;br /&gt;
when used as an lvalue, to assign a value to it.  Engine data must be&lt;br /&gt;
either an int or a void*; use of both is prohibited.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
int sig_active(struct Signal* sig);&lt;br /&gt;
&lt;br /&gt;
A signal's active flag is set when initialized by signal_add().  This&lt;br /&gt;
may be used by the application to determine whether or not the signal&lt;br /&gt;
has been initialized yet.  If it is, sig_active() returns a non-zero&lt;br /&gt;
value; otherwise, its value is 0.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void signal_add(struct Signal* signal, EventCallBack call, void* data,&lt;br /&gt;
		int sig);&lt;br /&gt;
&lt;br /&gt;
This function is called to add a signal to the list of signals to be&lt;br /&gt;
monitored.  The _signal_ parameter is a pointer is a pointer to a&lt;br /&gt;
struct Signal that is allocated by the application.  The _call_&lt;br /&gt;
parameter is a pointer to a function to process any signal events.&lt;br /&gt;
The _data_ parameter is for use of the signal call-back and may be&lt;br /&gt;
zero.  The _sig_ parameter is the integer value of the signal to be&lt;br /&gt;
monitored.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
enum TimerType t_type(struct Timer* tim);&lt;br /&gt;
&lt;br /&gt;
This macro returns the type of the given timer.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
time_t t_value(struct Timer* tim);&lt;br /&gt;
&lt;br /&gt;
This macro returns the value that was used when the given timer was&lt;br /&gt;
initialized by the events subsystem.  It will contain an absolute time&lt;br /&gt;
if the timer type is TT_ABSOLUTE, and a relative time otherwise.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
time_t t_expire(struct Timer* tim);&lt;br /&gt;
&lt;br /&gt;
This macro returns the absolute time at which the timer will next&lt;br /&gt;
expire.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void* t_data(struct Timer* tim);&lt;br /&gt;
&lt;br /&gt;
When a struct Timer is initialized, data that the call-back function&lt;br /&gt;
may find useful is stored in the struct Socket.  This macro returns&lt;br /&gt;
that pointer.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
int t_ed_int(struct Timer *tim);&lt;br /&gt;
&lt;br /&gt;
Engines may find it convenient to associate an integer with a struct&lt;br /&gt;
Timer.  This macro may be used to retrieve that integer or, when used&lt;br /&gt;
as an lvalue, to assign a value to it.  Engine data must be either an&lt;br /&gt;
int or a void*; use of both is prohibited.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void* t_ed_ptr(struct Timer *tim);&lt;br /&gt;
&lt;br /&gt;
Engines may find it convenient to associate a void* pointer with a&lt;br /&gt;
struct Timer.  This macro may be used to retrieve that pointer or,&lt;br /&gt;
when used as an lvalue, to assign a value to it.  Engine data must be&lt;br /&gt;
either an int or a void*; use of both is prohibited.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
int t_active(struct Timer *tim);&lt;br /&gt;
&lt;br /&gt;
A timer's active flag is set when initialized by timer_add(), and is&lt;br /&gt;
cleared immediately prior to generating an event of type ET_DESTROY.&lt;br /&gt;
This may be used by the application to determine whether or not the&lt;br /&gt;
timer is still in use by the events subsystem.  If it is, s_active()&lt;br /&gt;
returns a non-zero value; otherwise, its value is 0.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void timer_add(struct Timer* timer, EventCallBack call, void* data,&lt;br /&gt;
	       enum TimerType type, time_t value);&lt;br /&gt;
&lt;br /&gt;
This function is called to initialize and queue a timer.  The _timer_&lt;br /&gt;
parameter is a pointer to a struct Timer that is allocated by the&lt;br /&gt;
application.  The _call_ parameter is a pointer to a function to&lt;br /&gt;
process the timer's expiration.  The _data_ parameter is for use of&lt;br /&gt;
the timer call-back and may be zero.  The _type_ parameter must be one&lt;br /&gt;
of the valid timer types--TT_ABSOLUTE, TT_RELATIVE, or TT_PERIODIC.&lt;br /&gt;
Finally, _value_ is the value for the timer's expiration.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void timer_del(struct Timer* timer);&lt;br /&gt;
&lt;br /&gt;
When the application no longer needs a TT_PERIODIC timer, or when it&lt;br /&gt;
wishes to stop a TT_ABSOLUTE or TT_RELATIVE timer before its&lt;br /&gt;
expiration, it should call the timer_del() function.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void timer_chg(struct Timer* timer, enum TimerType type, time_t value);&lt;br /&gt;
&lt;br /&gt;
Occasionally, an application may wish to delay an existing TT_ABSOLUTE&lt;br /&gt;
or TT_RELATIVE timer; this may be done with the timer_chg() function.&lt;br /&gt;
The _type_ parameter must be one of TT_ABSOLUTE or&lt;br /&gt;
TT_RELATIVE--changing the values of TT_PERIODIC timers is not&lt;br /&gt;
supported.  The _value_ parameter is the same as would be given to&lt;br /&gt;
timer_add() for that particular type of timer.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void timer_run(void);&lt;br /&gt;
&lt;br /&gt;
When an engine has finished processing the results of its socket and&lt;br /&gt;
signal checks--just before it loops around to test for more events--it&lt;br /&gt;
should call the timer_run() function to expire any waiting timers.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
time_t timer_next(struct Generators* gen);&lt;br /&gt;
&lt;br /&gt;
Most engines will use a blocking call with a timeout to check for&lt;br /&gt;
socket activity.  To determine when the next timer needs to be run,&lt;br /&gt;
and thus to calculate how long the call should block, the engine&lt;br /&gt;
should call timer_next() with the _gen_ parameter passed to the&lt;br /&gt;
_EngineLoop_ function.  The timer_next() function returns an absolute&lt;br /&gt;
time, which may have to be massaged into a relative time before the&lt;br /&gt;
engine may use it.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
const char* timer_to_name(enum TimerType type);&lt;br /&gt;
&lt;br /&gt;
This function is defined only when DEBUGMODE is #define'd.  It takes&lt;br /&gt;
the given _type_ and returns a string giving that type's name.  This&lt;br /&gt;
function may safely be called from Debug() macros.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
enum EventType ev_type(struct Event* ev);&lt;br /&gt;
&lt;br /&gt;
This macro simply returns the type of the event _ev_.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
int ev_data(struct Event* ev);&lt;br /&gt;
&lt;br /&gt;
When an event is generated, a single integer can be passed along as a&lt;br /&gt;
piece of extra information.  This can be used, for instance, to carry&lt;br /&gt;
an errno value when an ET_ERROR is generated.  This macro simply&lt;br /&gt;
returns that integer.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
struct Socket* ev_socket(struct Event* ev);&lt;br /&gt;
&lt;br /&gt;
If the event was generated by a socket, this macro returns a pointer&lt;br /&gt;
to the struct Socket that generated the event.  The results are&lt;br /&gt;
undefined if the event was not generated by a socket.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
struct Signal* ev_signal(struct Event* ev);&lt;br /&gt;
&lt;br /&gt;
If the event was generated by a signal, this macro returns a pointer&lt;br /&gt;
to the struct Signal that generated the event.  The results are&lt;br /&gt;
undefined if the event was not generated by a signal.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
struct Timer* ev_timer(struct Event* ev);&lt;br /&gt;
&lt;br /&gt;
If the event was generated by a timer, this macro returns a pointer to&lt;br /&gt;
the struct Timer that generated the event.  The results are undefined&lt;br /&gt;
if the event was not generated by a timer.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void event_init(int max_sockets);&lt;br /&gt;
&lt;br /&gt;
Before any of the functions or macros described here can be called,&lt;br /&gt;
the events subsystem must be initialized by calling event_init().  The&lt;br /&gt;
_max_sockets_ parameter specifies to the events subsystem how many&lt;br /&gt;
sockets it must be able to support; this figure may be used for memory&lt;br /&gt;
allocation by the engines.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void event_loop(void);&lt;br /&gt;
&lt;br /&gt;
Once the initial sockets are open, signals added, and timers queued,&lt;br /&gt;
the application must call the event_loop() function in order to&lt;br /&gt;
actually begin monitoring those sockets, signals, and timers.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void event_generate(enum EventType type, void* arg, int data);&lt;br /&gt;
&lt;br /&gt;
This is the function called by the events subsystem to generate&lt;br /&gt;
particular events.  The _type_ parameter specifies the type of event&lt;br /&gt;
to generate, and the _arg_ parameter must be a pointer to the event's&lt;br /&gt;
generator.  The _data_ parameter may be used for passing such things&lt;br /&gt;
as signal numbers or errno values.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
const char* event_to_name(enum EventType type);&lt;br /&gt;
&lt;br /&gt;
This function is defined only when DEBUGMODE is #define'd.  It takes&lt;br /&gt;
the given _type_ and returns a string giving that event type's name.&lt;br /&gt;
This function may safely be called from Debug() macros.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
const char* engine_name(void);&lt;br /&gt;
&lt;br /&gt;
This function is used to retrieve the name of the engine presently&lt;br /&gt;
being used by the events subsystem.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void gen_ref_inc(void* gen);&lt;br /&gt;
&lt;br /&gt;
This macro increments the reference count of the generator _gen_,&lt;br /&gt;
preventing it from simply disappearing without warning.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;function&amp;gt;&lt;br /&gt;
void gen_ref_dec(void* gen);&lt;br /&gt;
&lt;br /&gt;
This macro decrements the reference count of the generator _gen_, and&lt;br /&gt;
releases the memory associated with it by generating at ET_DESTROY&lt;br /&gt;
event if the reference count falls to zero and the generator is marked&lt;br /&gt;
for destruction.  No references should be made to the generator after&lt;br /&gt;
calling this macro.&lt;br /&gt;
&amp;lt;/function&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;authors&amp;gt;&lt;br /&gt;
Kev &amp;lt;klmitch@mit.edu&amp;gt;&lt;br /&gt;
&amp;lt;/authors&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;changelog&amp;gt;&lt;br /&gt;
[2001-6-14 Kev] Finished initial description of the events subsystem.&lt;br /&gt;
&lt;br /&gt;
[2001-6-13 Kev] Initial description of the events subsystem.&lt;br /&gt;
&amp;lt;/changelog&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:IRCu API|Events]]&lt;/div&gt;</description>
			<pubDate>Fri, 25 Apr 2008 03:59:01 GMT</pubDate>			<dc:creator>Secretagent</dc:creator>			<comments>http://wiki.darenet.org/Talk:ircu_api_-_events</comments>		</item>
	</channel>
</rss>