1: .\" Copyright (c) 2001-2002 Packet Design, LLC.
2: .\" All rights reserved.
3: .\"
4: .\" Subject to the following obligations and disclaimer of warranty,
5: .\" use and redistribution of this software, in source or object code
6: .\" forms, with or without modifications are expressly permitted by
7: .\" Packet Design; provided, however, that:
8: .\"
9: .\" (i) Any and all reproductions of the source or object code
10: .\" must include the copyright notice above and the following
11: .\" disclaimer of warranties; and
12: .\" (ii) No rights are granted, in any manner or form, to use
13: .\" Packet Design trademarks, including the mark "PACKET DESIGN"
14: .\" on advertising, endorsements, or otherwise except as such
15: .\" appears in the above copyright notice or in the software.
16: .\"
17: .\" THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
18: .\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
19: .\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
20: .\" THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
21: .\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
22: .\" OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
23: .\" OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
24: .\" OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
25: .\" RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
26: .\" LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
27: .\" OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
28: .\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
29: .\" DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
30: .\" USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
31: .\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32: .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
33: .\" THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
34: .\" THE POSSIBILITY OF SUCH DAMAGE.
35: .\"
36: .\" Author: Archie Cobbs <archie@freebsd.org>
37: .\"
38: .\" $Id: pevent.3,v 1.1.1.1 2012/02/21 23:25:53 misho Exp $
39: .\"
40: .Dd April 22, 2002
41: .Dt PEVENT 3
42: .Os
43: .Sh NAME
44: .Nm pevent
45: .Nd pthread event library
46: .Sh LIBRARY
47: PDEL Library (libpdel, \-lpdel)
48: .Sh SYNOPSIS
49: .In pthread.h
50: .In pdel/util/pevent.h
51: .Ft "struct pevent_ctx *"
52: .Fn pevent_ctx_create "const char *mtype" "const pthread_attr_t *attr"
53: .Ft void
54: .Fn pevent_ctx_destroy "struct pevent_ctx **ctxp"
55: .Ft u_int
56: .Fn pevent_ctx_count "struct pevent_ctx *ctx"
57: .Ft int
58: .Fn pevent_register "struct pevent_ctx *ctx" "struct pevent **peventp" "int flags" "pthread_mutex_t *mutex" "pevent_handler_t *handler" "void *arg" "enum pevent_type type" "..."
59: .Ft void
60: .Fn pevent_unregister "struct pevent **eventp"
61: .Ft void
62: .Fn pevent_trigger "struct pevent *event"
63: .Ft int
64: .Fn pevent_get_info "struct pevent *event" "struct pevent_info *info"
65: .Sh DESCRIPTION
66: These functions support event-driven programming.
67: Event-driven programming is simpler and more efficient than threaded
68: programming because only a single thread is created to handle all
69: blocking operations, rather than a new thread per operation.
70: However, because the thread's stack cannot be used to store information
71: between events, each event must be handled to completion, i.e., the
72: event handlers must not block before returning.
73: .Pp
74: Event handlers that block may also be used with these routines, but only
75: if a separate thread is spawned for the handler (see below).
76: .\"
77: .Ss Event contexts
78: .\"
79: .Fn pevent_ctx_create
80: creates a new event context, which is used to register events.
81: All events registered with the same event context will be serviced by
82: the single thread associated with that event context.
83: .Pp
84: The scheduling attributes contained in
85: .Fa "*attr"
86: are used when creating this thread; if
87: .Fa attr
88: is
89: .Dv NULL
90: then the default thread attributes are used.
91: Since
92: .Fn pevent_ctx_create
93: makes a copy of these attributes,
94: .Fa attr
95: may be discarded when
96: .Fn pevent_ctx_create
97: returns.
98: .Pp
99: .Fa mtype
100: is the
101: .Xr typed_mem 3
102: memory type used when allocating memory for the event context.
103: .Pp
104: .Fn pevent_ctx_destroy
105: destroys an event context.
106: Any events still registered are automatically unregistered.
107: Upon return,
108: .Fa "*ctxp"
109: is set to
110: .Dv NULL .
111: If
112: .Fa "*ctxp"
113: is already
114: .Dv NULL
115: when
116: .Fn pevent_ctx_destroy
117: is invoked, nothing happens.
118: .Pp
119: It is safe to call
120: .Fn pevent_ctx_destroy
121: from within an event handler function.
122: .Pp
123: .Fn pevent_ctx_count
124: returns the number of events currently registered with
125: .Fa ctx .
126: .\"
127: .Ss Events
128: .\"
129: .Fn pevent_register
130: creates a new event and registers it with
131: .Fa ctx .
132: If successful, zero is returned and a non-
133: .Dv NULL
134: reference to the event is stored in
135: .Fa "*peventp" .
136: When
137: .Fn pevent_register
138: is invoked,
139: .Fa "*peventp"
140: must be
141: .Dv NULL
142: or else an error will be returned with
143: .Va errno
144: set to
145: .Er EBUSY .
146: If
147: .Fn pevent_register
148: returns an error,
149: .Fa "*peventp"
150: will be unmodified.
151: .Pp
152: .Fa handler
153: must point to a function having this type:
154: .Bd -literal -offset 3n
155: typedef void pevent_handler_t(void *arg);
156: .Ed
157: .Pp
158: When the event occurs,
159: .Fa "*peventp"
160: is set to
161: .Dv NULL
162: and then
163: .Fn handler arg
164: is invoked.
165: Therefore,
166: .Fa "*peventp"
167: is not equal to
168: .Dv NULL
169: if and only if the event is still pending.
170: For this to work,
171: .Fa "*peventp"
172: must remain valid and unmodified while the event is pending,
173: and the user code must initialize
174: .Fa peventp
175: to
176: .Dv NULL
177: before the first call to
178: .Fn pevent_register .
179: .Pp
180: The
181: .Fa type
182: and subsequent argument(s) define the event itself;
183: .Fa type
184: may have be one of the following values:
185: .Bl -tag -offset 3n -width PEVENT_MESG_PORT
186: .It Dv PEVENT_READ
187: Readable condition on a file descriptor.
188: The next argument must have type
189: .Li int .
190: .It Dv PEVENT_WRITE
191: Writable condition on a file descriptor.
192: The next argument must have type
193: .Li int .
194: .It Dv PEVENT_TIME
195: Time passage.
196: The next argument must have type
197: .Li int ,
198: and it is the relative time delay in milliseconds.
199: Negative delay values are silently converted to zero.
200: .It Dv PEVENT_MESG_PORT
201: Message(s) available on a message port.
202: The next argument must have type
203: .Li "struct mesg_port *".
204: .It Dv PEVENT_USER
205: User-triggered event.
206: No further arguments are required.
207: .El
208: .Pp
209: The
210: .Fa flags
211: parameter may contain any of the following values OR'd together:
212: .Pp
213: .Bl -tag -offset 3n -width PEVENT_OWN_THREADX
214: .It Li PEVENT_RECURRING
215: The event is recurring.
216: .It Li PEVENT_OWN_THREAD
217: Invoke
218: .Fn handler
219: in a separate thread.
220: .El
221: .Pp
222: .Dv PEVENT_RECURRING
223: causes the event to be automatically re-registered just before
224: each invocation of
225: .Fn handler .
226: In particular, this means that
227: .Fa "*peventp"
228: will not be
229: .Dv NULL
230: when
231: .Fn handler
232: is invoked.
233: .Pp
234: .Dv PEVENT_OWN_THREAD
235: causes a new thread to be spawned for each invocation of
236: .Fn handler ;
237: this thread may block, exit, or be canceled, and is by default not joinable.
238: If this flag is not set,
239: .Fn handler
240: will execute in the event context's main thread, in which case
241: .Fn handler
242: .Em "must not"
243: block or exit and the thread
244: .Em "must not"
245: be canceled.
246: .Pp
247: .Fn pevent_unregister
248: unregisters the event referenced by
249: .Fa "*peventp" .
250: Upon return,
251: .Fa "*peventp"
252: is set to
253: .Dv NULL .
254: If
255: .Fa "*peventp"
256: is already
257: .Dv NULL
258: when
259: .Fn pevent_unregister
260: is invoked, nothing happens.
261: .Pp
262: .Fn pevent_trigger
263: manually triggers an event, causing its handler to be invoked.
264: Although intended for use with
265: .Dv PEVENT_USER
266: events, it will work with any event.
267: The
268: .Fa event
269: may be
270: .Dv NULL ,
271: in which case nothing happens.
272: .Pp
273: .Fn pevent_get_info
274: returns the type and parameters associated with
275: .Fa event
276: by filling in the
277: .Li "struct pevent_info"
278: structure pointed to by
279: .Fa info :
280: .Bd -literal -offset 3n
281: struct pevent_info {
282: enum pevent_type type; /* event type */
283: union {
284: int fd; /* file descriptor (READ, WRITE) */
285: int millis; /* delay in milliseconds (TIME) */
286: struct mesg_port *port; /* message port (MESG_PORT) */
287: }; u;
288: };
289: .Ed
290: .\"
291: .Ss Synchronization
292: .\"
293: .Fn pevent_ctx_count ,
294: .Fn pevent_register ,
295: .Fn pevent_unregister ,
296: .Fn pevent_trigger ,
297: and
298: .Fn pevent_get_info
299: may all safely be called from different threads simultaneously.
300: However, there are inherent race conditions between an event's
301: .Fn handler
302: being invoked and reading the value of
303: .Fa "*peventp"
304: or unregistering the event with
305: .Fn pevent_unregister .
306: The
307: .Fa mutex
308: parameter to
309: .Fn pevent_register
310: can be used to avoid these problems.
311: .Pp
312: If a non-
313: .Dv NULL
314: .Fa mutex
315: is provided to
316: .Fn pevent_register ,
317: then
318: .Nm pevent
319: will acquire
320: .Fa "*mutex"
321: just before setting
322: .Fa "*pevent"
323: to
324: .Dv NULL
325: and invoking
326: .Fn handler ,
327: and
328: .Fa "*mutex"
329: will be automatically released when
330: .Fn handler
331: returns (or, in the case of
332: .Dv PEVENT_OWN_THREAD ,
333: the handler thread exits by any means).
334: If the user code acquires this mutex before any calls to
335: .Fn pevent_register
336: or
337: .Fn pevent_unregister ,
338: or before accessing
339: .Fa "*eventp" ,
340: then
341: .Fa "*eventp"
342: will always reflect the 'registered' state of the event and
343: .Fn handler
344: is guaranteed to never be invoked after
345: .Fn pevent_unregister
346: returns.
347: .Sh RETURN VALUES
348: .Fn pevent_ctx_create ,
349: .Fn pevent_register ,
350: and
351: .Fn pevent_get_info
352: return
353: .Dv NULL
354: or -1 to indicate an error,
355: with
356: .Va errno
357: set appropriately.
358: .Sh SEE ALSO
359: .Xr libpdel 3 ,
360: .Xr mesg_port 3 ,
361: .Xr paction 3 ,
362: .Xr pthread 3 ,
363: .Xr typed_mem 3
364: .Sh HISTORY
365: The PDEL library was developed at Packet Design, LLC.
366: .Dv "http://www.packetdesign.com/"
367: .Sh AUTHORS
368: .An Archie Cobbs Aq archie@freebsd.org
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>