summaryrefslogtreecommitdiff
path: root/pjlib/include/pj/equeue.h
blob: 77374bdb0d67539ef272bcc893d06f925621be43 (plain)
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
/* $Id$ */
/* 
 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#ifndef __PJ_EQUEUE_H__
#define __PJ_EQUEUE_H__

/**
 * @file equeue.h
 * @brief Event Queue
 */
#include <pj/types.h>


PJ_BEGIN_DECL

/**
 * @defgroup PJ_EQUEUE Event Queue
 * @brief Event Queue
 * @ingroup PJ_OS
 * @{
 */


/**
 * Opaque data type for Event Queue.
 */
typedef struct pj_equeue_t pj_equeue_t;

/**
 * Opaque data type for Event Queue key.
 */
typedef struct pj_equeue_key_t pj_equeue_key_t;


/**
 * This structure describes the callbacks to be called when I/O operation
 * completes.
 */
typedef struct pj_io_callback
{
    /**
     * This callback is called when #pj_equeue_read, #pj_equeue_recv or 
     * #pj_equeue_recvfrom completes.
     *
     * @param key	    The key.
     * @param bytes_read    The size of data that has just been read.
     */
    void (*on_read_complete)(pj_equeue_key_t *key, pj_ssize_t bytes_read);

    /**
     * This callback is called when #pj_equeue_write, #pj_equeue_send, or
     * #pj_equeue_sendto completes.
     *
     * @param key	    The key.
     * @param bytes_read    The size of data that has just been written.
     */
    void (*on_write_complete)(pj_equeue_key_t *key, pj_ssize_t bytes_sent);

    /**
     * This callback is called when #pj_equeue_accept completes.
     *
     * @param key	    The key.
     * @param status	    Zero if the operation completes successfully.
     */
    void (*on_accept_complete)(pj_equeue_key_t *key, int status);

    /**
     * This callback is called when #pj_equeue_connect completes.
     *
     * @param key	    The key.
     * @param status	    Zero if the operation completes successfully.
     */
    void (*on_connect_complete)(pj_equeue_key_t *key, int status);

} pj_io_callback;

/**
 * Event Queue options.
 */
typedef struct pj_equeue_options
{
    /** Maximum number of threads that are allowed to access Event Queue
     *  simulteneously.
     */
    unsigned	nb_threads;

    /** If non-zero, then no mutex protection will be used. */
    pj_bool_t	no_lock;

    /** Interval of the busy loop inside the event queue.
     *  The time resolution here determines the accuracy of the
     *  timer in the Event Queue.
     */
    pj_time_val	poll_interval;

} pj_equeue_options;


/**
 * Error value returned by I/O operations to indicate that the operation
 * can't complete immediately and will complete later.
 */
#define PJ_EQUEUE_PENDING   (-2)

/**
 * Types of Event Queue operation.
 */
typedef enum pj_equeue_op
{
    PJ_EQUEUE_OP_NONE		= 0,	/**< No operation.	    */
    PJ_EQUEUE_OP_READ		= 1,	/**< read() operation.	    */
    PJ_EQUEUE_OP_RECV_FROM	= 2,	/**< recvfrom() operation.  */
    PJ_EQUEUE_OP_WRITE		= 4,	/**< write() operation.	    */
    PJ_EQUEUE_OP_SEND_TO	= 8,	/**< sendto() operation.    */
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0
    PJ_EQUEUE_OP_ACCEPT		= 16,	/**< accept() operation.    */
    PJ_EQUEUE_OP_CONNECT	= 32,	/**< connect() operation.   */
#endif	/* PJ_HAS_TCP */
} pj_equeue_op;



/**
 * Initialize Event Queue options with default values.
 *
 * @param options   Event Queue options.
 */
PJ_DECL(void) pj_equeue_options_init(pj_equeue_options *options);

/**
 * Create a new Event Queue framework.
 *
 * @param pool	    The pool to allocate the event queue structure.
 * @param options   Event queue options, or if NULL is given, then
 *		    default options will be used.
 * @param equeue    Pointer to receive event queue structure.
 *
 * @return	    zero on success.
 */
PJ_DECL(pj_status_t) pj_equeue_create( pj_pool_t *pool, 
				       const pj_equeue_options *options,
				       pj_equeue_t **equeue);

/**
 * Get the first instance of Event Queue, or NULL if no Event Queue
 * instance has been created in the application.
 *
 * @return	    The first instance of Event Queue created, or NULL.
 */
PJ_DECL(pj_equeue_t*) pj_equeue_instance(void);

/**
 * Destroy the Event Queue.
 *
 * @param equeue    The Event Queue instance to be destroyed.
 */
PJ_DECL(pj_status_t) pj_equeue_destroy( pj_equeue_t *equeue );

/**
 * Customize the lock object that is used by the Event Queue.
 *
 * @param equeue    The Event Queue instance.
 * @param lock	    The lock object.
 * @param auto_del  If non-zero, the lock will be destroyed by
 *		    Event Queue.
 *
 * @return	    Zero on success.
 */
PJ_DECL(pj_status_t) pj_equeue_set_lock( pj_equeue_t *equeue,
					 pj_lock_t *lock, 
					 pj_bool_t auto_del);

/**
 * Associate an Event Queue key to particular handle. The key is also
 * associated with the callback and user data, which will be used by
 * the Event Queue framework when signalling event back to application.
 *
 * @param pool	    To allocate the resource for the specified handle, which
 *		    must be valid until the handle/key is unregistered
 *		    from Event Queue.
 * @param equeue    The Event Queue.
 * @param hnd	    The OS handle to be registered, which can be a socket
 *		    descriptor (pj_sock_t), file descriptor, etc.
 * @param cb	    Callback to be called when I/O operation completes. 
 * @param user_data User data to be associated with the key.
 * @param key	    Pointer to receive the key.
 *
 * @return	    Zero on success.
 */
PJ_DECL(pj_status_t) pj_equeue_register( pj_pool_t *pool,
					 pj_equeue_t *equeue,
					 pj_oshandle_t hnd,
					 pj_io_callback *cb,
					 void *user_data,
					 pj_equeue_key_t **key);

/**
 * Retrieve user data associated with a key.
 *
 * @param key	    The Event Queue key.
 *
 * @return	    User data associated with the key.
 */
PJ_DECL(void*) pj_equeue_get_user_data( pj_equeue_key_t *key );


/**
 * Unregister Event Queue key from the Event Queue.
 *
 * @param equeue    The Event Queue.
 * @param key	    The key.
 *
 * @return	    Zero on success.
 */
PJ_DECL(pj_status_t) pj_equeue_unregister( pj_equeue_t *equeue,
					   pj_equeue_key_t *key);

/**
 * Instruct the Event Queue to read from the specified handle. This function
 * returns immediately (i.e. non-blocking) regardless whether some data has 
 * been transfered. If the operation can't complete immediately, caller will 
 * be notified about the completion when it calls pj_equeue_poll().
 *
 * @param key	    The key that uniquely identifies the handle.
 * @param buffer    The buffer to hold the read data. The caller MUST make sure
 *		    that this buffer remain valid until the framework completes
 *		    reading the handle.
 * @param size	    The maximum size to be read.
 *
 * @return
 *  - zero or positive number to indicate the number of bytes has been
 *		    read, and in this case the operation was not queued.
 *  - (-1) on error, which in this case operation was not queued.
 *  - PJ_EQUEUE_PENDING if the operation has been queued.
 */
PJ_DECL(pj_ssize_t) pj_equeue_read( pj_equeue_key_t *key,
				    void *buffer,
				    pj_size_t size);

/**
 * Start recv() operation on the specified handle.
 *
 * @see ::pj_ioqueue_read
 */
PJ_DECL(pj_ssize_t) pj_equeue_recv( pj_equeue_key_t *key,
				    void *buf,
				    pj_size_t size,
				    unsigned flags);

/**
 * Start recvfrom() operation on the specified handle.
 *
 * @see ::pj_equeue_read
 */
PJ_DECL(pj_ssize_t) pj_equeue_recvfrom( pj_equeue_key_t *key,
					void *buf,
					pj_size_t size,
					unsigned flags,
					pj_sockaddr_t *addr,
					int *addrlen );

/**
 * Write.
 */
PJ_DECL(pj_ssize_t) pj_equeue_write( pj_equeue_key_t *key,
				     const void *buf,
				     pj_size_t size);

/**
 * Send.
 */
PJ_DECL(pj_ssize_t) pj_equeue_send( pj_equeue_key_t *key,
				    const void *buf,
				    pj_size_t size,
				    unsigned flags);

/**
 * Sendto.
 */
PJ_DECL(pj_ssize_t) pj_equeue_sendto( pj_equeue_key_t *key,
				      const void *buf,
				      pj_size_t size,
				      unsigned flags,
				      const pj_sockaddr_t *addr,
				      int addrlen);

/**
 * Schedule timer.
 */
PJ_DECL(pj_status_t) pj_equeue_schedule_timer( pj_equeue_t *equeue,
					       const pj_time_val *timeout,
					       pj_timer_entry *entry);

/**
 * Cancel timer.
 */
PJ_DECL(pj_status_t) pj_equeue_cancel_timer( pj_equeue_t *equeue,
					     pj_timer_entry *entry);

/**
 * Poll for events.
 */
PJ_DECL(pj_status_t) pj_equeue_poll( pj_equeue_t *equeue,
				     const pj_time_val *timeout );

/**
 * Run.
 */
PJ_DECL(pj_status_t) pj_equeue_run( pj_equeue_t *equeue );

/**
 * Stop all running threads.
 */
PJ_DECL(pj_status_t) pj_equeue_stop( pj_equeue_t *equeue );


/** @} */

PJ_END_DECL

#endif	/* __PJ_EQUEUE_H__ */