There are four integral components to the Network Events Library. The core component is the event interface itself, which handles initializing the engine(s) and providing an event queue. The other three components are the timer interface, defined in <event/tim.h>; the signal interface, defined in <event/sig.h>; and of course the socket interface, defined in <event/sock.h>. A fifth component is the engine modules themselves, but the library user need not worry about these.
The core event interface can run in one of two modes. In event loop mode, the application programmer passes control of the program to the event_loop() function, which calls various callbacks designated by the user. In event poll mode, the application programmer calls the event_poll() function, which sleeps for the specified period of time or until an event is available on the event queue, at which point it returns an event for the user to process. Note: In this mode, all events for which callbacks are declared will be processed by the callback, not by the application programmer's event loop.
A library user may also generate arbitrary, user-defined events. This allows add-on libraries, such as, say, resolver libraries, to use the event system to communicate with the application.
Each event in the library MUST be attached to a "generator," an abstract structure describing an object which generates an event. For instance, a socket generator will generate readable and writable events. All generators must begin with a generic header, defined by the ev_genhdr_t structure. An application should treat the structure as an opaque object to be initialized with the EV_GENHDR_INIT() initializer or with the ev_genhdr_init() function. Additionally, users should take care when selecting magic numbers. The technique used for the magic numbers in the library is to take the name of the preprocessor symbol which will be used and run an md5 sum over it. The result of that is then split into 4 32-bit numbers, which are exclusive-or'd together to yield the final magic number for the structure. The convention used for the name of the preprocessor symbol is to take the structure name, minus the "_t," convert it to upper case, and append "_MAGIC" to it. For instance, an ev_genhdr_t, if it had a unique magic number, would name that magic number EV_GENHDR_MAGIC.