File: event.3

package info (click to toggle)
proxycheck 0.49a-6
  • links: PTS
  • area: main
  • in suites: bullseye
  • size: 320 kB
  • sloc: ansic: 4,461; sh: 472; makefile: 134
file content (458 lines) | stat: -rw-r--r-- 18,841 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
.\" $Id: event.3,v 1.7 2004/05/29 14:58:45 mjt Exp $
.\" manpage for event library
.TH event 3
.SH NAME
event \- timer and I/O event manager

.SH SYNOPSYS
.nf
#include <event.h>

struct \fBev_ct\fR;
struct \fBev_tm\fR;

struct ev_ct *\fBev_ct_new\fR(int \fImaxfdhint\fR, int \fItypeflags\fR)
int \fBev_init\fR(int \fImaxfdhint\fR, int \fItypeflags\fR)
void \fBev_ct_free\fR(struct ev_ct *\fIct\fR)
void \fBev_free\fR(void)

int \fBev_method\fR(const struct ev_ct *\fIct\fR)
const char *\fBev_method_name\fR(const struct ev_ct *\fIct\fR)
int \fBev_fdlimit\fR(void)

typedef void \fBev_io_cbck_f\fR(void *\fIdata\fR, int \fIrevents\fR,
                          int \fIfd\fR, struct ev_ct *\fIct\fR)
int \fBev_io_add\fR(struct ev_ct *\fIct\fR, int \fIfd\fR, int \fIevents\fR,
              ev_io_cbck_f *\fRcbck\fR, void *\fIdata\fR)
int \fBev_io_mod\fR(struct ev_ct *\fIct\fR, int \fIfd\fR, int \fIevents\fR,
              ev_io_cbck_f *\fRcbck\fR, void *\fIdata\fR)
int \fBev_io_del\fR(struct ev_ct *\fIct\fR, int \fIfd\fR)
int \fBev_io_count\fR(const struct ev_ct *\fIct\fR)

typedef void \fBev_tm_cbck_f\fR(void *\fIdata\fR,
    struct ev_tm *\fItmr\fR, struct ev_ct *\fIct\fR)
extern ev_time_t \fBev_now\fR
extern time_t \fBev_time\fR
ev_time_t \fBev_gettime\fR(void)
struct ev_tm *\fBev_tm_add\fR(struct ev_ct *\fIct\fR, int \fImstimeout\fR,
   struct ev_tm *\fItmr\fR, ev_tm_cbck_f *\fIcbck\fR, void *\fIdata\fR)
struct ev_tm *\fBev_ts_add\fR(struct ev_ct *\fIct\fR, int \fIstimeout\fR,
   struct ev_tm *\fItmr\fR, ev_tm_cbck_f *\fIcbck\fR, void *\fIdata\fR)
int \fBev_tm_del\fR(struct ev_ct *\fIct\fR, struct ev_tm *\fItmr\fR)
int \fBev_tm_count\fR(const struct ev_ct *\fIct\fR)
ev_time_t \fBev_tm_first\fR(const struct ev_ct *\fIct\fR)
int \fBev_tm_timeout\fR(const struct ev_ct *\fIct\fR)

int \fBev_wait\fR(struct ev_ct *\fIct\fR, int \fImstimeout\fR)
.fi

.SH DESCRIPTION
.PP
The event module implements a simple threading core that allows a process
to wait for multiple I/O and/or timer events.  Multiple I/O streams and
timers can be monitored simultaneously.  Events are delivered via callback
routines provided by the application.  When requesting an event, application
provides private context that is passed back to the callback routine when the
routine is executed, together with some more information about the event.
.PP
There are two main types of events recognized by the module, and two types
of callback routines are defined: I/O events, i.e. when a filedescriptor
becomes readable or writable, and timer events, which gets executed once
at a given time (specified as an offset from current time).  Timers have
millisecond resolution.
.PP
The module uses one of several different underlying mechanisms for event
monitoring, including traditional \fBselect\fR(2) and \fBpoll\fR(2),
and more advanced methods available for a given operating system, such
as \fBepoll\fR(4), \fBkqueue\fR(2) and devpoll (\fBpoll\fR(7d)).
.PP
There are several sets of routines provided by the module, for the
following tasks: initialisation, adding/modifying/removing I/O watchers
(keyed by a filedescriptor), adding/removing timers, and performing
actual event waiting and dispatching.  The following subsections
describes each group of routines in turn.


.SS Initialisation
.PP
Every routine in this module requires an \fIevent context\fR
of type \fIstruct ev_ct\fR (opaquie to the application), that
holds internal state of the module, to be passed as a first
argument \fIet\fR.  This argument may be NULL pointer, in which
case a default event context is used (which should be initialized
too).  This way, it is possible to use several "contexts", or
instances, of the module (for example when an application itself
is multi-threaded, with it's own event context in every thread).
To initialize and free event context, the following routines
are provided:
.PP
.nf
struct ev_ct *\fBev_ct_new\fR(int \fImaxfdhint\fR, int \fItypeflags\fR)
int \fBev_init\fR(int \fImaxfdhint\fR, int \fItypeflags\fR)
.fi
.RS
creates and initializes new event context \- either specific,
or global default that will be used when no context is provided
(when \fIct\fR argument for other routines described below is NULL).
One of this routines (or both, to initialize either as many specific
or single global context) should be called before any other routine
in this module.
.PP
\fBev_ct_new\fR() return either pointer to newly allocated
and initialized event context, or NULL in case of error; \fBev_init\fR()
return 0 on success or negative value on error.  In case of error, global
variable \fIerrno\fR will hold specific error information.
.PP
Parameter \fImaxfdhint\fR specifies maximum filedescriptor that
application expects to monitor (only as a hint, to allocate enouth
resources in one go instead of reallocating new memory on demand).
If \fImaxfdhint\fR is <= 0, the module will determine maximum number
of files a process may open, using \fBev_fdlimit\fR() routine (see below).
.PP
The \fItypeflags\fR parameter (a bitmask) specifies which underlying method
the module should use for event monitoring.  Module will choose the "best"
method that matches \fItypeflags\fR from ones which are available on a
given system.  \fItypeflags\fR may be 0, in which case any method may
be used.  Currently, the following methods are recognized (some are
platform-specific):
.IP \fBEV_EPOLL\fR
epoll, available on Linux 2.6 and above, or with patch on 2.4.
.IP \fBEV_KQUEUE\fR
kqueue, available on FreeBSD, OpenBSD and some others.
.IP \fBEV_DEVPOLL\fR
/dev/poll interface with \fBioctl\fR(), available on Solaris.
.IP \fBEV_POLL\fR
traditional \fBpoll\fR(2) interface, problematic to use when number of
filedescriptors being monitored is large.
.IP \fBEV_SELECT\fR
traditional \fRselect\fR(2) interface, most portable, also problematic
when number of filedescriptors is large, and usually have upper limit
of 1024 filedescriptors (which may be avoided on some systems).
.IP \fBEV_ADVANCED\fR
a shortcut for all the more "advanced" methods, the module will choose
one available on a given platform if any.
.PP
Another way to specify which method to use is to set \fB$EV_METHOD\fR
environment variable to one of the following values: epoll, kqueue,
devpoll, poll, select.
.PP
The following error conditions are possible:
.IP "ENOTSUP or ENOSYS"
method(s) requested by \fItypeflags\fR (or by \fB$EV_METHOD\fR variable)
isn't supported
.IP ENOMEM
there is no memory available to initialize structure
.RE
.PP
.nf
void \fBev_ct_free\fR(struct ev_ct *\fIct\fR)
void \fBev_free\fR(void)
.fi
.RS
deallocates resources assotiated with the given specific event context
\fIct\fR or global default context.  Calling \fBev_ct_free\fR() with NULL
\fIct\fR argument is the same as calling \fBev_free\fR().  Note that
these routines does \fInot\fR close opened files or frees timer structures
which may be assotiated with the event context, this is the responsibility
of an application.  Usually, freeing an event context that still have some
timers or I/O watchers assotiated with it is an error.
.RE
.PP
.nf
int \fBev_method\fR(const struct ev_ct *\fIct\fR)
const char *\fBev_method_name\fR(const struct ev_ct *\fIct\fR)
.fi
.RS
return the code (described near \fBev_init\fR() above) or name of underlying
operating system mechanism used for monitoring.
.RE
.PP
.nf
int \fBev_fdlimit\fR(void)
.fi
.RS
return number of filedescriptors a process may open, according to
\fBgetrlimit\fR(2) system call.
.RE

.SS "Monitoring I/O availability"
.PP
The module may monitor a set of filedescriptors and call
application\-supplied callback routine (of type \fBev_io_cbck_f\fR)
when a filedescriptor becomes readable, writable or have an
exceptional condition.  An application registers a filedescriptor
to be monitored, together with a set of conditions of interest,
a pointer to callback routine and a pointer to application-specific
data.  When any of conditions becomes available, module will
execute callback routine, passing it the data pointer, a bitmask
indicating which conditions become true, and a filedescriptor in question,
together with a pointer to assotiated event context.
Available conditions are:
.IP \fBEV_IN\fR
filedescriptor is readable (there's some input data to be read), or for
end of file.
.IP \fBEV_OUT\fR
filedescriptor is writable, usually for sockets when underlying network stack
sent buffered data to a peer and more buffer space become available.
.IP \fBEV_PRI\fR
there's urgent data to be read.
.PP
The following types and routines are defined:
.PP
.nf
typedef void \fBev_io_cbck_f\fR(void *\fIdata\fR, int \fIrevents\fR,
                          int \fIfd\fR, struct ev_ct *\fIct\fR)
.fi
.RS
The type of application-supplied callback routine which will be
called by the module when any of the conditions of interest becomes
true.  \fIct\fR is the event context assotiated with the event,
either specific or default but is never NULL.  \fIfd\fR is the file
descriptor in question.  \fIrevents\fR is a bitmask indicating which
conditions (EV_IN, EV_OUT or EV_PRI) are true for the filedescriptor.
\fIdata\fR is the application-specific data that was passed to
\fBev_io_add\fR() or \fBev_io_mod\fR() (below) when the \fIfd\fR
where registered.
.PP
It is ok to add/remove events from within the callback routine.
.PP
Note that C language calling rules allows one to use a routine
that accepts only a subset of arguments.  Namely, a routine that
expects only one argument, a pointer to application data (e.g.
a structure describing server connection), will act as a callback
just fine.
.RE
.PP
.nf
int \fBev_io_add\fR(struct ev_ct *\fIct\fR, int \fIfd\fR, int \fIevents\fR,
              ev_io_cbck_f *\fRcbck\fR, void *\fIdata\fR)
.fi
.RS
Registers the new filedescriptor \fIfd\fR to be monitored for conditions
specified by \fIevents\fR parameter, to call a callback routine
\fIcbck\fR with data \fIdata\fR when any of the conditions becomes true.
Routine return 0 if registration was successeful, or negative value on
error (and sets \fIerrno\fR variable appropriately).  It is an error to
register a filedescriptor twice.  The following error conditions are
possible:
.IP EEXIST
\fIfd\fR is already registered with a given event context
(for \fBev_io_add\fR() only)
.IP ENOENT
\fIfd\fR is not registered with a given event context
(for \fBev_io_mod\fR() only, see below)
.IP EINVAL
\fIfd\fR is negative
.IP EMFILE
\fIfd\fR is too large for underlying monitoring mechanism to handle
(e.g. \fBselect\fR(2) usually unable to work when \fIfd\fR >= 1024)
.IP ENOMEM
there is no memory available to initialize internal structure
.IP EFAULT
\fIcbck\fR is NULL
.RE
.PP
.nf
int \fBev_io_mod\fR(struct ev_ct *\fIct\fR, int \fIfd\fR, int \fIevents\fR,
              ev_io_cbck_f *\fRcbck\fR, void *\fIdata\fR)
.fi
.RS
Modifies monitoring parameters for already registered filedescriptor \fIfd\fR.
Parameters and return value are the same of \fBev_io_add\fR().
.RE
.PP
.nf
int \fBev_io_del\fR(struct ev_ct *\fIct\fR, int \fIfd\fR)
.fi
.RS
Deregisters filedescriptor \fIfd\fR and return 0 on success or negative value
(and sets \fBerrno\fR) on failure.  It is ok to deregister already closed
filedescriptor \fIfd\fR.  The following error conditions are possible:
.IP ENOENT
\fIfd\fR is not registered with this event context.
.RE
.PP
.nf
int \fBev_io_count\fR(const struct ev_ct *\fIct\fR)
.fi
.RS
return number of filedescriptors currently registered with the given
event context \fIct\fR.  The number may be used to watch when there's
no filedescriptors to be monitored, as a condition to exit event loop
for example.  There's no error return.

.SS Timers
.PP
In addition to I/O events, the module also implements concept of a
\fItimer\fR, which is once-triggering event based on time.  Timer
events are delivered by callbacks in a way similar to I/O events.
Unlike I/O events, each timer is assotiated with a structure which
is owned by application and have to be allocated and freed appropriately
(or it may be a part of some larger application structure).  When
timer event is triggered (i.e. when the module calls the application-supplied
callback routine), the timer is already removed from the list of active
timers, and pointer to timer structure is passed to the routine.
An application may free the storage if it was dynamically allocated,
or reuse the timer structure (to implement repeating timers).
.PP
Module caches current time to reduce system call overhead, updating it
during initialisation and at each call to \fBev_wait\fR() dispatching
routine (below).  In most cases this is sufficient, but an application
may update the cached time by calling \fBev_gettime\fR() routine (below).
Cached current time is stored in \fBev_time\fR (of type \fBtime_t\fR, with
secound resolution), and in \fBev_now\fR (of type \fBlong long\fR) global
variables.
.PP
The following types, routines and variables are provided:
.PP
.nf
typedef void \fBev_tm_cbck_f\fR(void *\fIdata\fR,
    struct ev_tm *\fItmr\fR, struct ev_ct *\fIct\fR)
.fi
.RS
The type of timer callback routine.  When the module calls the timer callback
routine, it passes application\-registered data pointer \fIdata\fR, pointer to
the timer structure \fItmr\fR and assotiated event context \fIct\fR to it.
When the callback routine is executed, the timer in question \fItmr\fR was
already removed from set of active timers and was disassotiated from the
event context, and may be reused or freed by an application as appropriate.
.PP
It is ok to add/remove events from within the callback routine, and
\fItmr\fR structure may be reused to (re\-)add a timer as appropriate.
.PP
The same note as given for \fBev_io_cbck_f\fR callback applies here
as well: actual callback may expect and handle less parameters than
the module passes to it (e.g. usually, only \fIdata\fR pointer is sufficient
for an application).
.RE
.PP
.nf
extern ev_time_t \fBev_now\fR
extern time_t \fBev_time\fR
ev_time_t \fBev_gettime\fR(void)
.fi
.RS
cached current time in secounds (\fBev_time\fR) or millisecounds
(\fBev_now\fR), and routine that updates the cache and return the
same value as it has just stored in \fBev_now\fR.  Type \fBev_time_t\fR
is a 64bit integer (long long).  There is no error return.
.RE
.nf
.PP
.nf
struct ev_tm *\fBev_tm_add\fR(struct ev_ct *\fIct\fR, int \fImstimeout\fR,
   struct ev_tm *\fItmr\fR, ev_tm_cbck_f *\fIcbck\fR, void *\fIdata\fR)
.fi
.RS
Registers new timer event to be triggered after \fImstimeout\fR millisecounds
from now (since \fBev_now\fR).  When the timer will be triggered, the module
will call the callback \fIcbck\fR with the value \fIdata\fR.  Argument
\fItmr\fR may be either NULL, in which case the routine will allocate
new timer structure dynamically and return it upon successeful completion,
or timer structure already allocated by application, in which case it shold
be initialized to zero, and \fImust not\fR already be registered.
In either case the application is responsible for freeing memory hold by
\fItmr\fR when it will be disassotiated from the event context (either
when the module will execute callback routine or after \fBev_tm_del\fR).
Routine return pointer to the timer structure, or NULL in case of error
(and sets \fBerrno\fR appropriately).
.PP
Timer structure is opaque for an application, and should be zero-initialized
on allocation.  The only two fields assessible by the applications are:
.nf
  ev_tm_cbck_f *\fIevtm_cbck\fR
  void *\fIevtm_data\fR
.fi
which holds the pointer to the callback routine and the application-supplied
data.  Both fields may be modified by application while the timer is
assotiated with an event context, with the exception that \fIevtm_cbck\fR
can not be NULL.
.PP
Possible \fBerrno\fR values after call to \fBev_tm_add\fR() are:
.IP EFAULT
\fIcbck\fR parameter is NULL
.IP EINVAL
\fImstimeout\fR value is negative
.IP ENOMEM
\fItmr\fR is NULL and there is no memory to allocate new structure.
.RE
.PP
.nf
struct ev_tm *\fBev_ts_add\fR(struct ev_ct *\fIct\fR, int \fIstimeout\fR,
   struct ev_tm *\fItmr\fR, ev_tm_cbck_f *\fIcbck\fR, void *\fIdata\fR)
.fi
.RS
similar to \fBev_tm_add\fR(), with the difference that this one expects
timeout in secounds instead of millisecounds, and tries to fire all
timers sheduled for the same secound at once (even if they where registered
at different millisecounds).
.RE
.PP
.nf
int \fBev_tm_del\fR(struct ev_ct *\fIct\fR, struct ev_tm *\fItmr\fR)
.fi
.RS
Removes the given timer \fItmr\fR, which should be registered with
the event context \fIct\fR by \fBev_tm_add\fR() routine above.  As
usual, the application owns the \fItmr\fR structure after the call
to this routine.  Routine return amount of millisecounds left to
the time when the timer should be triggered (which may be 0), or
negative value on error.  In an attempt to remove a timer which
isn't registered (or has been triggered already), routine will
indicate error and set \fBerrno\fR to ENOENT.
.RE
.PP
.nf
int \fBev_tm_count\fR(const struct ev_ct *\fIct\fR)
.fi
.RS
return number of timers registered with a given event context \fIct\fR.
.RE
.PP
.nf
ev_time_t \fBev_tm_first\fR(const struct ev_ct *\fIct\fR)
int \fBev_tm_timeout\fR(const struct ev_ct *\fIct\fR)
.fi
.RS
return a time when first timer will be triggered (or 0 if no timers are
registered), and amount of millisecounds left to that time (or -1).
.RE

.SS "Event Loop"
.PP
The main event loop handling routines are as follows:
.PP
.nf
int \fBev_wait\fR(struct ev_ct *\fIct\fR, int \fImstimeout\fR)
.fi
.RS
one\-shot wait\-and\-dispatch routine.  It waits up to \fImstimeout\fR
millisecounds (specify negative value for to wait forever) for registered
events to happen and executes all necessary callback routines, and when
returns.  Return value indicates how many I/O events where handled
(i.e. how many filedescriptors where ready), which may be 0 in case
of timeout or a timer expired, or -1 in case of error.  If error
occured (typical case is interrupt, in which case \fBerrno\fR will be
set to EINTR), \fBev_wait\fR() still executes any pending timers and
updates current time cache.  For real event loop, an application should
call this routine repeatedly until some condition (e.g. number of
filedescriptors registered is non-zero) is true.

.SH "RETURN VALUES"
.PP
Most routines in the module return zero or positive integer value in
case of error

.SH "SEE ALSO"
select(2), poll(2), epoll(4), kqueue(2), poll(7d), gettimeofday(2), time(2).

.SH BUGS
The module is using non-standard time representation (\fBev_time_t\fR
type which is currently defined as long long).  This may be not portable.
But using any standard types (struct timeval, struct timespec and the
like) complicates code significantly.

.SH AUTHOR
This software was written by Michael Tokarev, <mjt@corpit.ru>,
with help of ideas from work by Wietse Venema.