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