| .\" $OpenBSD: event.3,v 1.4 2002/07/12 18:50:48 provos Exp $ | |
| .\" | |
| .\" Copyright (c) 2000 Artur Grabowski <art@openbsd.org> | |
| .\" All rights reserved. | |
| .\" | |
| .\" Redistribution and use in source and binary forms, with or without | |
| .\" modification, are permitted provided that the following conditions | |
| .\" are met: | |
| .\" | |
| .\" 1. Redistributions of source code must retain the above copyright | |
| .\" notice, this list of conditions and the following disclaimer. | |
| .\" 2. Redistributions in binary form must reproduce the above copyright | |
| .\" notice, this list of conditions and the following disclaimer in the | |
| .\" documentation and/or other materials provided with the distribution. | |
| .\" 3. The name of the author may not be used to endorse or promote products | |
| .\" derived from this software without specific prior written permission. | |
| .\" | |
| .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, | |
| .\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |
| .\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |
| .\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| .\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| .\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
| .\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
| .\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
| .\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
| .\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| .\" | |
| .Dd August 8, 2000 | |
| .Dt EVENT 3 | |
| .Os | |
| .Sh NAME | |
| .Nm event_init , | |
| .Nm event_dispatch , | |
| .Nm event_loop , | |
| .Nm event_loopexit , | |
| .Nm event_loopbreak , | |
| .Nm event_set , | |
| .Nm event_base_dispatch , | |
| .Nm event_base_loop , | |
| .Nm event_base_loopexit , | |
| .Nm event_base_loopbreak , | |
| .Nm event_base_set , | |
| .Nm event_base_free , | |
| .Nm event_add , | |
| .Nm event_del , | |
| .Nm event_once , | |
| .Nm event_base_once , | |
| .Nm event_pending , | |
| .Nm event_initialized , | |
| .Nm event_priority_init , | |
| .Nm event_priority_set , | |
| .Nm evtimer_set , | |
| .Nm evtimer_add , | |
| .Nm evtimer_del , | |
| .Nm evtimer_pending , | |
| .Nm evtimer_initialized , | |
| .Nm signal_set , | |
| .Nm signal_add , | |
| .Nm signal_del , | |
| .Nm signal_pending , | |
| .Nm signal_initialized , | |
| .Nm bufferevent_new , | |
| .Nm bufferevent_free , | |
| .Nm bufferevent_write , | |
| .Nm bufferevent_write_buffer , | |
| .Nm bufferevent_read , | |
| .Nm bufferevent_enable , | |
| .Nm bufferevent_disable , | |
| .Nm bufferevent_settimeout , | |
| .Nm bufferevent_base_set , | |
| .Nm evbuffer_new , | |
| .Nm evbuffer_free , | |
| .Nm evbuffer_add , | |
| .Nm evbuffer_add_buffer , | |
| .Nm evbuffer_add_printf , | |
| .Nm evbuffer_add_vprintf , | |
| .Nm evbuffer_drain , | |
| .Nm evbuffer_write , | |
| .Nm evbuffer_read , | |
| .Nm evbuffer_find , | |
| .Nm evbuffer_readline , | |
| .Nm evhttp_new , | |
| .Nm evhttp_bind_socket , | |
| .Nm evhttp_free | |
| .Nd execute a function when a specific event occurs | |
| .Sh SYNOPSIS | |
| .Fd #include <sys/time.h> | |
| .Fd #include <event.h> | |
| .Ft "struct event_base *" | |
| .Fn "event_init" "void" | |
| .Ft int | |
| .Fn "event_dispatch" "void" | |
| .Ft int | |
| .Fn "event_loop" "int flags" | |
| .Ft int | |
| .Fn "event_loopexit" "struct timeval *tv" | |
| .Ft int | |
| .Fn "event_loopbreak" "void" | |
| .Ft void | |
| .Fn "event_set" "struct event *ev" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" | |
| .Ft int | |
| .Fn "event_base_dispatch" "struct event_base *base" | |
| .Ft int | |
| .Fn "event_base_loop" "struct event_base *base" "int flags" | |
| .Ft int | |
| .Fn "event_base_loopexit" "struct event_base *base" "struct timeval *tv" | |
| .Ft int | |
| .Fn "event_base_loopbreak" "struct event_base *base" | |
| .Ft int | |
| .Fn "event_base_set" "struct event_base *base" "struct event *" | |
| .Ft void | |
| .Fn "event_base_free" "struct event_base *base" | |
| .Ft int | |
| .Fn "event_add" "struct event *ev" "struct timeval *tv" | |
| .Ft int | |
| .Fn "event_del" "struct event *ev" | |
| .Ft int | |
| .Fn "event_once" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv" | |
| .Ft int | |
| .Fn "event_base_once" "struct event_base *base" "int fd" "short event" "void (*fn)(int, short, void *)" "void *arg" "struct timeval *tv" | |
| .Ft int | |
| .Fn "event_pending" "struct event *ev" "short event" "struct timeval *tv" | |
| .Ft int | |
| .Fn "event_initialized" "struct event *ev" | |
| .Ft int | |
| .Fn "event_priority_init" "int npriorities" | |
| .Ft int | |
| .Fn "event_priority_set" "struct event *ev" "int priority" | |
| .Ft void | |
| .Fn "evtimer_set" "struct event *ev" "void (*fn)(int, short, void *)" "void *arg" | |
| .Ft void | |
| .Fn "evtimer_add" "struct event *ev" "struct timeval *" | |
| .Ft void | |
| .Fn "evtimer_del" "struct event *ev" | |
| .Ft int | |
| .Fn "evtimer_pending" "struct event *ev" "struct timeval *tv" | |
| .Ft int | |
| .Fn "evtimer_initialized" "struct event *ev" | |
| .Ft void | |
| .Fn "signal_set" "struct event *ev" "int signal" "void (*fn)(int, short, void *)" "void *arg" | |
| .Ft void | |
| .Fn "signal_add" "struct event *ev" "struct timeval *" | |
| .Ft void | |
| .Fn "signal_del" "struct event *ev" | |
| .Ft int | |
| .Fn "signal_pending" "struct event *ev" "struct timeval *tv" | |
| .Ft int | |
| .Fn "signal_initialized" "struct event *ev" | |
| .Ft "struct bufferevent *" | |
| .Fn "bufferevent_new" "int fd" "evbuffercb readcb" "evbuffercb writecb" "everrorcb" "void *cbarg" | |
| .Ft void | |
| .Fn "bufferevent_free" "struct bufferevent *bufev" | |
| .Ft int | |
| .Fn "bufferevent_write" "struct bufferevent *bufev" "void *data" "size_t size" | |
| .Ft int | |
| .Fn "bufferevent_write_buffer" "struct bufferevent *bufev" "struct evbuffer *buf" | |
| .Ft size_t | |
| .Fn "bufferevent_read" "struct bufferevent *bufev" "void *data" "size_t size" | |
| .Ft int | |
| .Fn "bufferevent_enable" "struct bufferevent *bufev" "short event" | |
| .Ft int | |
| .Fn "bufferevent_disable" "struct bufferevent *bufev" "short event" | |
| .Ft void | |
| .Fn "bufferevent_settimeout" "struct bufferevent *bufev" "int timeout_read" "int timeout_write" | |
| .Ft int | |
| .Fn "bufferevent_base_set" "struct event_base *base" "struct bufferevent *bufev" | |
| .Ft "struct evbuffer *" | |
| .Fn "evbuffer_new" "void" | |
| .Ft void | |
| .Fn "evbuffer_free" "struct evbuffer *buf" | |
| .Ft int | |
| .Fn "evbuffer_add" "struct evbuffer *buf" "const void *data" "size_t size" | |
| .Ft int | |
| .Fn "evbuffer_add_buffer" "struct evbuffer *dst" "struct evbuffer *src" | |
| .Ft int | |
| .Fn "evbuffer_add_printf" "struct evbuffer *buf" "const char *fmt" "..." | |
| .Ft int | |
| .Fn "evbuffer_add_vprintf" "struct evbuffer *buf" "const char *fmt" "va_list ap" | |
| .Ft void | |
| .Fn "evbuffer_drain" "struct evbuffer *buf" "size_t size" | |
| .Ft int | |
| .Fn "evbuffer_write" "struct evbuffer *buf" "int fd" | |
| .Ft int | |
| .Fn "evbuffer_read" "struct evbuffer *buf" "int fd" "int size" | |
| .Ft "u_char *" | |
| .Fn "evbuffer_find" "struct evbuffer *buf" "const u_char *data" "size_t size" | |
| .Ft "char *" | |
| .Fn "evbuffer_readline" "struct evbuffer *buf" | |
| .Ft "struct evhttp *" | |
| .Fn "evhttp_new" "struct event_base *base" | |
| .Ft int | |
| .Fn "evhttp_bind_socket" "struct evhttp *http" "const char *address" "u_short port" | |
| .Ft "void" | |
| .Fn "evhttp_free" "struct evhttp *http" | |
| .Ft int | |
| .Fa (*event_sigcb)(void) ; | |
| .Ft volatile sig_atomic_t | |
| .Fa event_gotsig ; | |
| .Sh DESCRIPTION | |
| The | |
| .Nm event | |
| API provides a mechanism to execute a function when a specific event | |
| on a file descriptor occurs or after a given time has passed. | |
| .Pp | |
| The | |
| .Nm event | |
| API needs to be initialized with | |
| .Fn event_init | |
| before it can be used. | |
| .Pp | |
| In order to process events, an application needs to call | |
| .Fn event_dispatch . | |
| This function only returns on error, and should replace the event core | |
| of the application program. | |
| .Pp | |
| The function | |
| .Fn event_set | |
| prepares the event structure | |
| .Fa ev | |
| to be used in future calls to | |
| .Fn event_add | |
| and | |
| .Fn event_del . | |
| The event will be prepared to call the function specified by the | |
| .Fa fn | |
| argument with an | |
| .Fa int | |
| argument indicating the file descriptor, a | |
| .Fa short | |
| argument indicating the type of event, and a | |
| .Fa void * | |
| argument given in the | |
| .Fa arg | |
| argument. | |
| The | |
| .Fa fd | |
| indicates the file descriptor that should be monitored for events. | |
| The events can be either | |
| .Va EV_READ , | |
| .Va EV_WRITE , | |
| or both, | |
| indicating that an application can read or write from the file descriptor | |
| respectively without blocking. | |
| .Pp | |
| The function | |
| .Fa fn | |
| will be called with the file descriptor that triggered the event and | |
| the type of event which will be either | |
| .Va EV_TIMEOUT , | |
| .Va EV_SIGNAL , | |
| .Va EV_READ , | |
| or | |
| .Va EV_WRITE . | |
| Additionally, an event which has registered interest in more than one of the | |
| preceeding events, via bitwise-OR to | |
| .Fn event_set , | |
| can provide its callback function with a bitwise-OR of more than one triggered | |
| event. | |
| The additional flag | |
| .Va EV_PERSIST | |
| makes an | |
| .Fn event_add | |
| persistent until | |
| .Fn event_del | |
| has been called. | |
| .Pp | |
| Once initialized, the | |
| .Fa ev | |
| structure can be used repeatedly with | |
| .Fn event_add | |
| and | |
| .Fn event_del | |
| and does not need to be reinitialized unless the function called and/or | |
| the argument to it are to be changed. | |
| However, when an | |
| .Fa ev | |
| structure has been added to libevent using | |
| .Fn event_add | |
| the structure must persist until the event occurs (assuming | |
| .Fa EV_PERSIST | |
| is not set) or is removed | |
| using | |
| .Fn event_del . | |
| You may not reuse the same | |
| .Fa ev | |
| structure for multiple monitored descriptors; each descriptor | |
| needs its own | |
| .Fa ev . | |
| .Pp | |
| The function | |
| .Fn event_add | |
| schedules the execution of the | |
| .Fa ev | |
| event when the event specified in | |
| .Fn event_set | |
| occurs or in at least the time specified in the | |
| .Fa tv . | |
| If | |
| .Fa tv | |
| is | |
| .Dv NULL , | |
| no timeout occurs and the function will only be called | |
| if a matching event occurs on the file descriptor. | |
| The event in the | |
| .Fa ev | |
| argument must be already initialized by | |
| .Fn event_set | |
| and may not be used in calls to | |
| .Fn event_set | |
| until it has timed out or been removed with | |
| .Fn event_del . | |
| If the event in the | |
| .Fa ev | |
| argument already has a scheduled timeout, the old timeout will be | |
| replaced by the new one. | |
| .Pp | |
| The function | |
| .Fn event_del | |
| will cancel the event in the argument | |
| .Fa ev . | |
| If the event has already executed or has never been added | |
| the call will have no effect. | |
| .Pp | |
| The functions | |
| .Fn evtimer_set , | |
| .Fn evtimer_add , | |
| .Fn evtimer_del , | |
| .Fn evtimer_initialized , | |
| and | |
| .Fn evtimer_pending | |
| are abbreviations for common situations where only a timeout is required. | |
| The file descriptor passed will be \-1, and the event type will be | |
| .Va EV_TIMEOUT . | |
| .Pp | |
| The functions | |
| .Fn signal_set , | |
| .Fn signal_add , | |
| .Fn signal_del , | |
| .Fn signal_initialized , | |
| and | |
| .Fn signal_pending | |
| are abbreviations. | |
| The event type will be a persistent | |
| .Va EV_SIGNAL . | |
| That means | |
| .Fn signal_set | |
| adds | |
| .Va EV_PERSIST . | |
| .Pp | |
| In order to avoid races in signal handlers, the | |
| .Nm event | |
| API provides two variables: | |
| .Va event_sigcb | |
| and | |
| .Va event_gotsig . | |
| A signal handler | |
| sets | |
| .Va event_gotsig | |
| to indicate that a signal has been received. | |
| The application sets | |
| .Va event_sigcb | |
| to a callback function. | |
| After the signal handler sets | |
| .Va event_gotsig , | |
| .Nm event_dispatch | |
| will execute the callback function to process received signals. | |
| The callback returns 1 when no events are registered any more. | |
| It can return \-1 to indicate an error to the | |
| .Nm event | |
| library, causing | |
| .Fn event_dispatch | |
| to terminate with | |
| .Va errno | |
| set to | |
| .Er EINTR . | |
| .Pp | |
| The function | |
| .Fn event_once | |
| is similar to | |
| .Fn event_set . | |
| However, it schedules a callback to be called exactly once and does not | |
| require the caller to prepare an | |
| .Fa event | |
| structure. | |
| This function supports | |
| .Fa EV_TIMEOUT , | |
| .Fa EV_READ , | |
| and | |
| .Fa EV_WRITE . | |
| .Pp | |
| The | |
| .Fn event_pending | |
| function can be used to check if the event specified by | |
| .Fa event | |
| is pending to run. | |
| If | |
| .Va EV_TIMEOUT | |
| was specified and | |
| .Fa tv | |
| is not | |
| .Dv NULL , | |
| the expiration time of the event will be returned in | |
| .Fa tv . | |
| .Pp | |
| The | |
| .Fn event_initialized | |
| macro can be used to check if an event has been initialized. | |
| .Pp | |
| The | |
| .Nm event_loop | |
| function provides an interface for single pass execution of pending | |
| events. | |
| The flags | |
| .Va EVLOOP_ONCE | |
| and | |
| .Va EVLOOP_NONBLOCK | |
| are recognized. | |
| The | |
| .Nm event_loopexit | |
| function exits from the event loop. The next | |
| .Fn event_loop | |
| iteration after the | |
| given timer expires will complete normally (handling all queued events) then | |
| exit without blocking for events again. Subsequent invocations of | |
| .Fn event_loop | |
| will proceed normally. | |
| The | |
| .Nm event_loopbreak | |
| function exits from the event loop immediately. | |
| .Fn event_loop | |
| will abort after the next event is completed; | |
| .Fn event_loopbreak | |
| is typically invoked from this event's callback. This behavior is analogous | |
| to the "break;" statement. Subsequent invocations of | |
| .Fn event_loop | |
| will proceed normally. | |
| .Pp | |
| It is the responsibility of the caller to provide these functions with | |
| pre-allocated event structures. | |
| .Pp | |
| .Sh EVENT PRIORITIES | |
| By default | |
| .Nm libevent | |
| schedules all active events with the same priority. | |
| However, sometimes it is desirable to process some events with a higher | |
| priority than others. | |
| For that reason, | |
| .Nm libevent | |
| supports strict priority queues. | |
| Active events with a lower priority are always processed before events | |
| with a higher priority. | |
| .Pp | |
| The number of different priorities can be set initially with the | |
| .Fn event_priority_init | |
| function. | |
| This function should be called before the first call to | |
| .Fn event_dispatch . | |
| The | |
| .Fn event_priority_set | |
| function can be used to assign a priority to an event. | |
| By default, | |
| .Nm libevent | |
| assigns the middle priority to all events unless their priority | |
| is explicitly set. | |
| .Sh THREAD SAFE EVENTS | |
| .Nm Libevent | |
| has experimental support for thread-safe events. | |
| When initializing the library via | |
| .Fn event_init , | |
| an event base is returned. | |
| This event base can be used in conjunction with calls to | |
| .Fn event_base_set , | |
| .Fn event_base_dispatch , | |
| .Fn event_base_loop , | |
| .Fn event_base_loopexit , | |
| .Fn bufferevent_base_set | |
| and | |
| .Fn event_base_free . | |
| .Fn event_base_set | |
| should be called after preparing an event with | |
| .Fn event_set , | |
| as | |
| .Fn event_set | |
| assigns the provided event to the most recently created event base. | |
| .Fn bufferevent_base_set | |
| should be called after preparing a bufferevent with | |
| .Fn bufferevent_new . | |
| .Fn event_base_free | |
| should be used to free memory associated with the event base | |
| when it is no longer needed. | |
| .Sh BUFFERED EVENTS | |
| .Nm libevent | |
| provides an abstraction on top of the regular event callbacks. | |
| This abstraction is called a | |
| .Va "buffered event" . | |
| A buffered event provides input and output buffers that get filled | |
| and drained automatically. | |
| The user of a buffered event no longer deals directly with the IO, | |
| but instead is reading from input and writing to output buffers. | |
| .Pp | |
| A new bufferevent is created by | |
| .Fn bufferevent_new . | |
| The parameter | |
| .Fa fd | |
| specifies the file descriptor from which data is read and written to. | |
| This file descriptor is not allowed to be a | |
| .Xr pipe 2 . | |
| The next three parameters are callbacks. | |
| The read and write callback have the following form: | |
| .Ft void | |
| .Fn "(*cb)" "struct bufferevent *bufev" "void *arg" . | |
| The error callback has the following form: | |
| .Ft void | |
| .Fn "(*cb)" "struct bufferevent *bufev" "short what" "void *arg" . | |
| The argument is specified by the fourth parameter | |
| .Fa "cbarg" . | |
| A | |
| .Fa bufferevent struct | |
| pointer is returned on success, NULL on error. | |
| Both the read and the write callback may be NULL. | |
| The error callback has to be always provided. | |
| .Pp | |
| Once initialized, the bufferevent structure can be used repeatedly with | |
| bufferevent_enable() and bufferevent_disable(). | |
| The flags parameter can be a combination of | |
| .Va EV_READ | |
| and | |
| .Va EV_WRITE . | |
| When read enabled the bufferevent will try to read from the file | |
| descriptor and call the read callback. | |
| The write callback is executed | |
| whenever the output buffer is drained below the write low watermark, | |
| which is | |
| .Va 0 | |
| by default. | |
| .Pp | |
| The | |
| .Fn bufferevent_write | |
| function can be used to write data to the file descriptor. | |
| The data is appended to the output buffer and written to the descriptor | |
| automatically as it becomes available for writing. | |
| .Fn bufferevent_write | |
| returns 0 on success or \-1 on failure. | |
| The | |
| .Fn bufferevent_read | |
| function is used to read data from the input buffer, | |
| returning the amount of data read. | |
| .Pp | |
| If multiple bases are in use, bufferevent_base_set() must be called before | |
| enabling the bufferevent for the first time. | |
| .Sh NON-BLOCKING HTTP SUPPORT | |
| .Nm libevent | |
| provides a very thin HTTP layer that can be used both to host an HTTP | |
| server and also to make HTTP requests. | |
| An HTTP server can be created by calling | |
| .Fn evhttp_new . | |
| It can be bound to any port and address with the | |
| .Fn evhttp_bind_socket | |
| function. | |
| When the HTTP server is no longer used, it can be freed via | |
| .Fn evhttp_free . | |
| .Pp | |
| To be notified of HTTP requests, a user needs to register callbacks with the | |
| HTTP server. | |
| This can be done by calling | |
| .Fn evhttp_set_cb . | |
| The second argument is the URI for which a callback is being registered. | |
| The corresponding callback will receive an | |
| .Va struct evhttp_request | |
| object that contains all information about the request. | |
| .Pp | |
| This section does not document all the possible function calls; please | |
| check | |
| .Va event.h | |
| for the public interfaces. | |
| .Sh ADDITIONAL NOTES | |
| It is possible to disable support for | |
| .Va epoll , kqueue , devpoll , poll | |
| or | |
| .Va select | |
| by setting the environment variable | |
| .Va EVENT_NOEPOLL , EVENT_NOKQUEUE , EVENT_NODEVPOLL , EVENT_NOPOLL | |
| or | |
| .Va EVENT_NOSELECT , | |
| respectively. | |
| By setting the environment variable | |
| .Va EVENT_SHOW_METHOD , | |
| .Nm libevent | |
| displays the kernel notification method that it uses. | |
| .Sh RETURN VALUES | |
| Upon successful completion | |
| .Fn event_add | |
| and | |
| .Fn event_del | |
| return 0. | |
| Otherwise, \-1 is returned and the global variable errno is | |
| set to indicate the error. | |
| .Sh SEE ALSO | |
| .Xr kqueue 2 , | |
| .Xr poll 2 , | |
| .Xr select 2 , | |
| .Xr evdns 3 , | |
| .Xr timeout 9 | |
| .Sh HISTORY | |
| The | |
| .Nm event | |
| API manpage is based on the | |
| .Xr timeout 9 | |
| manpage by Artur Grabowski. | |
| The port of | |
| .Nm libevent | |
| to Windows is due to Michael A. Davis. | |
| Support for real-time signals is due to Taral. | |
| .Sh AUTHORS | |
| The | |
| .Nm event | |
| library was written by Niels Provos. | |
| .Sh BUGS | |
| This documentation is neither complete nor authoritative. | |
| If you are in doubt about the usage of this API then | |
| check the source code to find out how it works, write | |
| up the missing piece of documentation and send it to | |
| me for inclusion in this man page. |