Alexandre Lision | 8af73cb | 2013-12-10 14:11:20 -0500 | [diff] [blame] | 1 | /* $Id: ioqueue.h 4359 2013-02-21 11:18:36Z bennylp $ |
Tristan Matthews | 0a329cc | 2013-07-17 13:20:14 -0400 | [diff] [blame] | 2 | */ |
| 3 | /* |
| 4 | * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) |
| 5 | * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | * |
| 12 | * This program is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | * GNU General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU General Public License |
| 18 | * along with this program; if not, write to the Free Software |
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 20 | */ |
| 21 | #ifndef __PJ_IOQUEUE_H__ |
| 22 | #define __PJ_IOQUEUE_H__ |
| 23 | |
| 24 | /** |
| 25 | * @file ioqueue.h |
| 26 | * @brief I/O Dispatching Mechanism |
| 27 | */ |
| 28 | |
| 29 | #include <pj/types.h> |
| 30 | |
| 31 | PJ_BEGIN_DECL |
| 32 | |
| 33 | /** |
| 34 | * @defgroup PJ_IO Input/Output |
| 35 | * @brief Input/Output |
| 36 | * @ingroup PJ_OS |
| 37 | * |
| 38 | * This section contains API building blocks to perform network I/O and |
| 39 | * communications. If provides: |
| 40 | * - @ref PJ_SOCK |
| 41 | *\n |
| 42 | * A highly portable socket abstraction, runs on all kind of |
| 43 | * network APIs such as standard BSD socket, Windows socket, Linux |
| 44 | * \b kernel socket, PalmOS networking API, etc. |
| 45 | * |
| 46 | * - @ref pj_addr_resolve |
| 47 | *\n |
| 48 | * Portable address resolution, which implements #pj_gethostbyname(). |
| 49 | * |
| 50 | * - @ref PJ_SOCK_SELECT |
| 51 | *\n |
| 52 | * A portable \a select() like API (#pj_sock_select()) which can be |
| 53 | * implemented with various back-ends. |
| 54 | * |
| 55 | * - @ref PJ_IOQUEUE |
| 56 | *\n |
| 57 | * Framework for dispatching network events. |
| 58 | * |
| 59 | * For more information see the modules below. |
| 60 | */ |
| 61 | |
| 62 | /** |
| 63 | * @defgroup PJ_IOQUEUE IOQueue: I/O Event Dispatching with Proactor Pattern |
| 64 | * @ingroup PJ_IO |
| 65 | * @{ |
| 66 | * |
| 67 | * I/O Queue provides API for performing asynchronous I/O operations. It |
| 68 | * conforms to proactor pattern, which allows application to submit an |
| 69 | * asynchronous operation and to be notified later when the operation has |
| 70 | * completed. |
| 71 | * |
| 72 | * The I/O Queue can work on both socket and file descriptors. For |
| 73 | * asynchronous file operations however, one must make sure that the correct |
| 74 | * file I/O back-end is used, because not all file I/O back-end can be |
| 75 | * used with the ioqueue. Please see \ref PJ_FILE_IO for more details. |
| 76 | * |
| 77 | * The framework works natively in platforms where asynchronous operation API |
| 78 | * exists, such as in Windows NT with IoCompletionPort/IOCP. In other |
| 79 | * platforms, the I/O queue abstracts the operating system's event poll API |
| 80 | * to provide semantics similar to IoCompletionPort with minimal penalties |
| 81 | * (i.e. per ioqueue and per handle mutex protection). |
| 82 | * |
| 83 | * The I/O queue provides more than just unified abstraction. It also: |
| 84 | * - makes sure that the operation uses the most effective way to utilize |
| 85 | * the underlying mechanism, to achieve the maximum theoritical |
| 86 | * throughput possible on a given platform. |
| 87 | * - choose the most efficient mechanism for event polling on a given |
| 88 | * platform. |
| 89 | * |
| 90 | * Currently, the I/O Queue is implemented using: |
| 91 | * - <tt><b>select()</b></tt>, as the common denominator, but the least |
| 92 | * efficient. Also the number of descriptor is limited to |
| 93 | * \c PJ_IOQUEUE_MAX_HANDLES (which by default is 64). |
| 94 | * - <tt><b>/dev/epoll</b></tt> on Linux (user mode and kernel mode), |
| 95 | * a much faster replacement for select() on Linux (and more importantly |
| 96 | * doesn't have limitation on number of descriptors). |
| 97 | * - <b>I/O Completion ports</b> on Windows NT/2000/XP, which is the most |
| 98 | * efficient way to dispatch events in Windows NT based OSes, and most |
| 99 | * importantly, it doesn't have the limit on how many handles to monitor. |
| 100 | * And it works with files (not only sockets) as well. |
| 101 | * |
| 102 | * |
| 103 | * \section pj_ioqueue_concurrency_sec Concurrency Rules |
| 104 | * |
| 105 | * The ioqueue has been fine tuned to allow multiple threads to poll the |
| 106 | * handles simultaneously, to maximize scalability when the application is |
| 107 | * running on multiprocessor systems. When more than one threads are polling |
| 108 | * the ioqueue and there are more than one handles are signaled, more than |
| 109 | * one threads will execute the callback simultaneously to serve the events. |
| 110 | * These parallel executions are completely safe when the events happen for |
| 111 | * two different handles. |
| 112 | * |
| 113 | * However, with multithreading, care must be taken when multiple events |
| 114 | * happen on the same handle, or when event is happening on a handle (and |
| 115 | * the callback is being executed) and application is performing |
| 116 | * unregistration to the handle at the same time. |
| 117 | * |
| 118 | * The treatments of above scenario differ according to the concurrency |
| 119 | * setting that are applied to the handle. |
| 120 | * |
| 121 | * \subsection pj_ioq_concur_set Concurrency Settings for Handles |
| 122 | * |
| 123 | * Concurrency can be set on per handle (key) basis, by using |
| 124 | * #pj_ioqueue_set_concurrency() function. The default key concurrency value |
| 125 | * for the handle is inherited from the key concurrency setting of the ioqueue, |
| 126 | * and the key concurrency setting for the ioqueue can be changed by using |
| 127 | * #pj_ioqueue_set_default_concurrency(). The default key concurrency setting |
| 128 | * for ioqueue itself is controlled by compile time setting |
| 129 | * PJ_IOQUEUE_DEFAULT_ALLOW_CONCURRENCY. |
| 130 | * |
| 131 | * Note that this key concurrency setting only controls whether multiple |
| 132 | * threads are allowed to operate <b>on the same key</b> at the same time. |
| 133 | * The ioqueue itself always allows multiple threads to enter the ioqeuue at |
| 134 | * the same time, and also simultaneous callback calls to <b>differrent |
| 135 | * keys</b> is always allowed regardless to the key concurrency setting. |
| 136 | * |
| 137 | * \subsection pj_ioq_parallel Parallel Callback Executions for the Same Handle |
| 138 | * |
| 139 | * Note that when key concurrency is enabled (i.e. parallel callback calls on |
| 140 | * the same key is allowed; this is the default setting), the ioqueue will only |
| 141 | * perform simultaneous callback executions on the same key when the key has |
| 142 | * invoked multiple pending operations. This could be done for example by |
| 143 | * calling #pj_ioqueue_recvfrom() more than once on the same key, each with |
| 144 | * the same key but different operation key (pj_ioqueue_op_key_t). With this |
| 145 | * scenario, when multiple packets arrive on the key at the same time, more |
| 146 | * than one threads may execute the callback simultaneously, each with the |
| 147 | * same key but different operation key. |
| 148 | * |
| 149 | * When there is only one pending operation on the key (e.g. there is only one |
| 150 | * #pj_ioqueue_recvfrom() invoked on the key), then events occuring to the |
| 151 | * same key will be queued by the ioqueue, thus no simultaneous callback calls |
| 152 | * will be performed. |
| 153 | * |
| 154 | * \subsection pj_ioq_allow_concur Concurrency is Enabled (Default Value) |
| 155 | * |
| 156 | * The default setting for the ioqueue is to allow multiple threads to |
| 157 | * execute callbacks for the same handle/key. This setting is selected to |
| 158 | * promote good performance and scalability for application. |
| 159 | * |
| 160 | * However this setting has a major drawback with regard to synchronization, |
| 161 | * and application MUST carefully follow the following guidelines to ensure |
| 162 | * that parallel access to the key does not cause problems: |
| 163 | * |
| 164 | * - Always note that callback may be called simultaneously for the same |
| 165 | * key. |
| 166 | * - <b>Care must be taken when unregistering a key</b> from the |
| 167 | * ioqueue. Application must take care that when one thread is issuing |
| 168 | * an unregistration, other thread is not simultaneously invoking the |
| 169 | * callback <b>to the same key</b>. |
| 170 | *\n |
| 171 | * This happens because the ioqueue functions are working with a pointer |
| 172 | * to the key, and there is a possible race condition where the pointer |
| 173 | * has been rendered invalid by other threads before the ioqueue has a |
| 174 | * chance to acquire mutex on it. |
| 175 | * |
| 176 | * \subsection pj_ioq_disallow_concur Concurrency is Disabled |
| 177 | * |
| 178 | * Alternatively, application may disable key concurrency to make |
| 179 | * synchronization easier. As noted above, there are three ways to control |
| 180 | * key concurrency setting: |
| 181 | * - by controlling on per handle/key basis, with #pj_ioqueue_set_concurrency(). |
| 182 | * - by changing default key concurrency setting on the ioqueue, with |
| 183 | * #pj_ioqueue_set_default_concurrency(). |
| 184 | * - by changing the default concurrency on compile time, by declaring |
| 185 | * PJ_IOQUEUE_DEFAULT_ALLOW_CONCURRENCY macro to zero in your config_site.h |
| 186 | * |
| 187 | * \section pj_ioqeuue_examples_sec Examples |
| 188 | * |
| 189 | * For some examples on how to use the I/O Queue, please see: |
| 190 | * |
| 191 | * - \ref page_pjlib_ioqueue_tcp_test |
| 192 | * - \ref page_pjlib_ioqueue_udp_test |
| 193 | * - \ref page_pjlib_ioqueue_perf_test |
| 194 | */ |
| 195 | |
| 196 | |
| 197 | /** |
| 198 | * This structure describes operation specific key to be submitted to |
| 199 | * I/O Queue when performing the asynchronous operation. This key will |
| 200 | * be returned to the application when completion callback is called. |
| 201 | * |
| 202 | * Application normally wants to attach it's specific data in the |
| 203 | * \c user_data field so that it can keep track of which operation has |
| 204 | * completed when the callback is called. Alternatively, application can |
| 205 | * also extend this struct to include its data, because the pointer that |
| 206 | * is returned in the completion callback will be exactly the same as |
| 207 | * the pointer supplied when the asynchronous function is called. |
| 208 | */ |
| 209 | typedef struct pj_ioqueue_op_key_t |
| 210 | { |
| 211 | void *internal__[32]; /**< Internal I/O Queue data. */ |
| 212 | void *activesock_data; /**< Active socket data. */ |
| 213 | void *user_data; /**< Application data. */ |
| 214 | } pj_ioqueue_op_key_t; |
| 215 | |
| 216 | /** |
| 217 | * This structure describes the callbacks to be called when I/O operation |
| 218 | * completes. |
| 219 | */ |
| 220 | typedef struct pj_ioqueue_callback |
| 221 | { |
| 222 | /** |
| 223 | * This callback is called when #pj_ioqueue_recv or #pj_ioqueue_recvfrom |
| 224 | * completes. |
| 225 | * |
| 226 | * @param key The key. |
| 227 | * @param op_key Operation key. |
| 228 | * @param bytes_read >= 0 to indicate the amount of data read, |
| 229 | * otherwise negative value containing the error |
| 230 | * code. To obtain the pj_status_t error code, use |
| 231 | * (pj_status_t code = -bytes_read). |
| 232 | */ |
| 233 | void (*on_read_complete)(pj_ioqueue_key_t *key, |
| 234 | pj_ioqueue_op_key_t *op_key, |
| 235 | pj_ssize_t bytes_read); |
| 236 | |
| 237 | /** |
| 238 | * This callback is called when #pj_ioqueue_send or #pj_ioqueue_sendto |
| 239 | * completes. |
| 240 | * |
| 241 | * @param key The key. |
| 242 | * @param op_key Operation key. |
| 243 | * @param bytes_sent >= 0 to indicate the amount of data written, |
| 244 | * otherwise negative value containing the error |
| 245 | * code. To obtain the pj_status_t error code, use |
| 246 | * (pj_status_t code = -bytes_sent). |
| 247 | */ |
| 248 | void (*on_write_complete)(pj_ioqueue_key_t *key, |
| 249 | pj_ioqueue_op_key_t *op_key, |
| 250 | pj_ssize_t bytes_sent); |
| 251 | |
| 252 | /** |
| 253 | * This callback is called when #pj_ioqueue_accept completes. |
| 254 | * |
| 255 | * @param key The key. |
| 256 | * @param op_key Operation key. |
| 257 | * @param sock Newly connected socket. |
| 258 | * @param status Zero if the operation completes successfully. |
| 259 | */ |
| 260 | void (*on_accept_complete)(pj_ioqueue_key_t *key, |
| 261 | pj_ioqueue_op_key_t *op_key, |
| 262 | pj_sock_t sock, |
| 263 | pj_status_t status); |
| 264 | |
| 265 | /** |
| 266 | * This callback is called when #pj_ioqueue_connect completes. |
| 267 | * |
| 268 | * @param key The key. |
| 269 | * @param status PJ_SUCCESS if the operation completes successfully. |
| 270 | */ |
| 271 | void (*on_connect_complete)(pj_ioqueue_key_t *key, |
| 272 | pj_status_t status); |
| 273 | } pj_ioqueue_callback; |
| 274 | |
| 275 | |
| 276 | /** |
| 277 | * Types of pending I/O Queue operation. This enumeration is only used |
| 278 | * internally within the ioqueue. |
| 279 | */ |
| 280 | typedef enum pj_ioqueue_operation_e |
| 281 | { |
| 282 | PJ_IOQUEUE_OP_NONE = 0, /**< No operation. */ |
| 283 | PJ_IOQUEUE_OP_READ = 1, /**< read() operation. */ |
| 284 | PJ_IOQUEUE_OP_RECV = 2, /**< recv() operation. */ |
| 285 | PJ_IOQUEUE_OP_RECV_FROM = 4, /**< recvfrom() operation. */ |
| 286 | PJ_IOQUEUE_OP_WRITE = 8, /**< write() operation. */ |
| 287 | PJ_IOQUEUE_OP_SEND = 16, /**< send() operation. */ |
| 288 | PJ_IOQUEUE_OP_SEND_TO = 32, /**< sendto() operation. */ |
| 289 | #if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0 |
| 290 | PJ_IOQUEUE_OP_ACCEPT = 64, /**< accept() operation. */ |
| 291 | PJ_IOQUEUE_OP_CONNECT = 128 /**< connect() operation. */ |
| 292 | #endif /* PJ_HAS_TCP */ |
| 293 | } pj_ioqueue_operation_e; |
| 294 | |
| 295 | |
| 296 | /** |
| 297 | * This macro specifies the maximum number of events that can be |
| 298 | * processed by the ioqueue on a single poll cycle, on implementation |
| 299 | * that supports it. The value is only meaningfull when specified |
| 300 | * during PJLIB build. |
| 301 | */ |
| 302 | #ifndef PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL |
| 303 | # define PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL (16) |
| 304 | #endif |
| 305 | |
| 306 | /** |
| 307 | * When this flag is specified in ioqueue's recv() or send() operations, |
| 308 | * the ioqueue will always mark the operation as asynchronous. |
| 309 | */ |
| 310 | #define PJ_IOQUEUE_ALWAYS_ASYNC ((pj_uint32_t)1 << (pj_uint32_t)31) |
| 311 | |
| 312 | /** |
| 313 | * Return the name of the ioqueue implementation. |
| 314 | * |
| 315 | * @return Implementation name. |
| 316 | */ |
| 317 | PJ_DECL(const char*) pj_ioqueue_name(void); |
| 318 | |
| 319 | |
| 320 | /** |
| 321 | * Create a new I/O Queue framework. |
| 322 | * |
| 323 | * @param pool The pool to allocate the I/O queue structure. |
| 324 | * @param max_fd The maximum number of handles to be supported, which |
| 325 | * should not exceed PJ_IOQUEUE_MAX_HANDLES. |
| 326 | * @param ioqueue Pointer to hold the newly created I/O Queue. |
| 327 | * |
| 328 | * @return PJ_SUCCESS on success. |
| 329 | */ |
| 330 | PJ_DECL(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, |
| 331 | pj_size_t max_fd, |
| 332 | pj_ioqueue_t **ioqueue); |
| 333 | |
| 334 | /** |
| 335 | * Destroy the I/O queue. |
| 336 | * |
| 337 | * @param ioque The I/O Queue to be destroyed. |
| 338 | * |
| 339 | * @return PJ_SUCCESS if success. |
| 340 | */ |
| 341 | PJ_DECL(pj_status_t) pj_ioqueue_destroy( pj_ioqueue_t *ioque ); |
| 342 | |
| 343 | /** |
| 344 | * Set the lock object to be used by the I/O Queue. This function can only |
| 345 | * be called right after the I/O queue is created, before any handle is |
| 346 | * registered to the I/O queue. |
| 347 | * |
| 348 | * Initially the I/O queue is created with non-recursive mutex protection. |
| 349 | * Applications can supply alternative lock to be used by calling this |
| 350 | * function. |
| 351 | * |
| 352 | * @param ioque The ioqueue instance. |
| 353 | * @param lock The lock to be used by the ioqueue. |
| 354 | * @param auto_delete In non-zero, the lock will be deleted by the ioqueue. |
| 355 | * |
| 356 | * @return PJ_SUCCESS or the appropriate error code. |
| 357 | */ |
| 358 | PJ_DECL(pj_status_t) pj_ioqueue_set_lock( pj_ioqueue_t *ioque, |
| 359 | pj_lock_t *lock, |
| 360 | pj_bool_t auto_delete ); |
| 361 | |
| 362 | /** |
| 363 | * Set default concurrency policy for this ioqueue. If this function is not |
| 364 | * called, the default concurrency policy for the ioqueue is controlled by |
| 365 | * compile time setting PJ_IOQUEUE_DEFAULT_ALLOW_CONCURRENCY. |
| 366 | * |
| 367 | * Note that changing the concurrency setting to the ioqueue will only affect |
| 368 | * subsequent key registrations. To modify the concurrency setting for |
| 369 | * individual key, use #pj_ioqueue_set_concurrency(). |
| 370 | * |
| 371 | * @param ioqueue The ioqueue instance. |
| 372 | * @param allow Non-zero to allow concurrent callback calls, or |
| 373 | * PJ_FALSE to disallow it. |
| 374 | * |
| 375 | * @return PJ_SUCCESS on success or the appropriate error code. |
| 376 | */ |
| 377 | PJ_DECL(pj_status_t) pj_ioqueue_set_default_concurrency(pj_ioqueue_t *ioqueue, |
| 378 | pj_bool_t allow); |
| 379 | |
| 380 | /** |
| 381 | * Register a socket to the I/O queue framework. |
| 382 | * When a socket is registered to the IOQueue, it may be modified to use |
| 383 | * non-blocking IO. If it is modified, there is no guarantee that this |
| 384 | * modification will be restored after the socket is unregistered. |
| 385 | * |
| 386 | * @param pool To allocate the resource for the specified handle, |
| 387 | * which must be valid until the handle/key is unregistered |
| 388 | * from I/O Queue. |
| 389 | * @param ioque The I/O Queue. |
| 390 | * @param sock The socket. |
| 391 | * @param user_data User data to be associated with the key, which can be |
| 392 | * retrieved later. |
| 393 | * @param cb Callback to be called when I/O operation completes. |
| 394 | * @param key Pointer to receive the key to be associated with this |
| 395 | * socket. Subsequent I/O queue operation will need this |
| 396 | * key. |
| 397 | * |
| 398 | * @return PJ_SUCCESS on success, or the error code. |
| 399 | */ |
| 400 | PJ_DECL(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, |
| 401 | pj_ioqueue_t *ioque, |
| 402 | pj_sock_t sock, |
| 403 | void *user_data, |
| 404 | const pj_ioqueue_callback *cb, |
| 405 | pj_ioqueue_key_t **key ); |
| 406 | |
| 407 | /** |
| 408 | * Variant of pj_ioqueue_register_sock() with additional group lock parameter. |
| 409 | * If group lock is set for the key, the key will add the reference counter |
| 410 | * when the socket is registered and decrease it when it is destroyed. |
| 411 | */ |
| 412 | PJ_DECL(pj_status_t) pj_ioqueue_register_sock2(pj_pool_t *pool, |
| 413 | pj_ioqueue_t *ioque, |
| 414 | pj_sock_t sock, |
| 415 | pj_grp_lock_t *grp_lock, |
| 416 | void *user_data, |
| 417 | const pj_ioqueue_callback *cb, |
| 418 | pj_ioqueue_key_t **key ); |
| 419 | |
| 420 | /** |
| 421 | * Unregister from the I/O Queue framework. Caller must make sure that |
| 422 | * the key doesn't have any pending operations before calling this function, |
| 423 | * by calling #pj_ioqueue_is_pending() for all previously submitted |
| 424 | * operations except asynchronous connect, and if necessary call |
| 425 | * #pj_ioqueue_post_completion() to cancel the pending operations. |
| 426 | * |
| 427 | * Note that asynchronous connect operation will automatically be |
| 428 | * cancelled during the unregistration. |
| 429 | * |
| 430 | * Also note that when I/O Completion Port backend is used, application |
| 431 | * MUST close the handle immediately after unregistering the key. This is |
| 432 | * because there is no unregistering API for IOCP. The only way to |
| 433 | * unregister the handle from IOCP is to close the handle. |
| 434 | * |
| 435 | * @param key The key that was previously obtained from registration. |
| 436 | * |
| 437 | * @return PJ_SUCCESS on success or the error code. |
| 438 | * |
| 439 | * @see pj_ioqueue_is_pending |
| 440 | */ |
| 441 | PJ_DECL(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key ); |
| 442 | |
| 443 | |
| 444 | /** |
| 445 | * Get user data associated with an ioqueue key. |
| 446 | * |
| 447 | * @param key The key that was previously obtained from registration. |
| 448 | * |
| 449 | * @return The user data associated with the descriptor, or NULL |
| 450 | * on error or if no data is associated with the key during |
| 451 | * registration. |
| 452 | */ |
| 453 | PJ_DECL(void*) pj_ioqueue_get_user_data( pj_ioqueue_key_t *key ); |
| 454 | |
| 455 | /** |
| 456 | * Set or change the user data to be associated with the file descriptor or |
| 457 | * handle or socket descriptor. |
| 458 | * |
| 459 | * @param key The key that was previously obtained from registration. |
| 460 | * @param user_data User data to be associated with the descriptor. |
| 461 | * @param old_data Optional parameter to retrieve the old user data. |
| 462 | * |
| 463 | * @return PJ_SUCCESS on success or the error code. |
| 464 | */ |
| 465 | PJ_DECL(pj_status_t) pj_ioqueue_set_user_data( pj_ioqueue_key_t *key, |
| 466 | void *user_data, |
| 467 | void **old_data); |
| 468 | |
| 469 | /** |
| 470 | * Configure whether the ioqueue is allowed to call the key's callback |
| 471 | * concurrently/in parallel. The default concurrency setting for the key |
| 472 | * is controlled by ioqueue's default concurrency value, which can be |
| 473 | * changed by calling #pj_ioqueue_set_default_concurrency(). |
| 474 | * |
| 475 | * If concurrency is allowed for the key, it means that if there are more |
| 476 | * than one pending operations complete simultaneously, more than one |
| 477 | * threads may call the key's callback at the same time. This generally |
| 478 | * would promote good scalability for application, at the expense of more |
| 479 | * complexity to manage the concurrent accesses in application's code. |
| 480 | * |
| 481 | * Alternatively application may disable the concurrent access by |
| 482 | * setting the \a allow flag to false. With concurrency disabled, only |
| 483 | * one thread can call the key's callback at one time. |
| 484 | * |
| 485 | * @param key The key that was previously obtained from registration. |
| 486 | * @param allow Set this to non-zero to allow concurrent callback calls |
| 487 | * and zero (PJ_FALSE) to disallow it. |
| 488 | * |
| 489 | * @return PJ_SUCCESS on success or the appropriate error code. |
| 490 | */ |
| 491 | PJ_DECL(pj_status_t) pj_ioqueue_set_concurrency(pj_ioqueue_key_t *key, |
| 492 | pj_bool_t allow); |
| 493 | |
| 494 | /** |
| 495 | * Acquire the key's mutex. When the key's concurrency is disabled, |
| 496 | * application may call this function to synchronize its operation |
| 497 | * with the key's callback (i.e. this function will block until the |
| 498 | * key's callback returns). |
| 499 | * |
| 500 | * @param key The key that was previously obtained from registration. |
| 501 | * |
| 502 | * @return PJ_SUCCESS on success or the appropriate error code. |
| 503 | */ |
| 504 | PJ_DECL(pj_status_t) pj_ioqueue_lock_key(pj_ioqueue_key_t *key); |
| 505 | |
| 506 | /** |
| 507 | * Release the lock previously acquired with pj_ioqueue_lock_key(). |
| 508 | * |
| 509 | * @param key The key that was previously obtained from registration. |
| 510 | * |
| 511 | * @return PJ_SUCCESS on success or the appropriate error code. |
| 512 | */ |
| 513 | PJ_DECL(pj_status_t) pj_ioqueue_unlock_key(pj_ioqueue_key_t *key); |
| 514 | |
| 515 | /** |
| 516 | * Initialize operation key. |
| 517 | * |
| 518 | * @param op_key The operation key to be initialied. |
| 519 | * @param size The size of the operation key. |
| 520 | */ |
| 521 | PJ_DECL(void) pj_ioqueue_op_key_init( pj_ioqueue_op_key_t *op_key, |
| 522 | pj_size_t size ); |
| 523 | |
| 524 | /** |
| 525 | * Check if operation is pending on the specified operation key. |
| 526 | * The \c op_key must have been initialized with #pj_ioqueue_op_key_init() |
| 527 | * or submitted as pending operation before, or otherwise the result |
| 528 | * is undefined. |
| 529 | * |
| 530 | * @param key The key. |
| 531 | * @param op_key The operation key, previously submitted to any of |
| 532 | * the I/O functions and has returned PJ_EPENDING. |
| 533 | * |
| 534 | * @return Non-zero if operation is still pending. |
| 535 | */ |
| 536 | PJ_DECL(pj_bool_t) pj_ioqueue_is_pending( pj_ioqueue_key_t *key, |
| 537 | pj_ioqueue_op_key_t *op_key ); |
| 538 | |
| 539 | |
| 540 | /** |
| 541 | * Post completion status to the specified operation key and call the |
| 542 | * appropriate callback. When the callback is called, the number of bytes |
| 543 | * received in read/write callback or the status in accept/connect callback |
| 544 | * will be set from the \c bytes_status parameter. |
| 545 | * |
| 546 | * @param key The key. |
| 547 | * @param op_key Pending operation key. |
| 548 | * @param bytes_status Number of bytes or status to be set. A good value |
| 549 | * to put here is -PJ_ECANCELLED. |
| 550 | * |
| 551 | * @return PJ_SUCCESS if completion status has been successfully |
| 552 | * sent. |
| 553 | */ |
| 554 | PJ_DECL(pj_status_t) pj_ioqueue_post_completion( pj_ioqueue_key_t *key, |
| 555 | pj_ioqueue_op_key_t *op_key, |
| 556 | pj_ssize_t bytes_status ); |
| 557 | |
| 558 | |
| 559 | |
| 560 | #if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0 |
| 561 | /** |
| 562 | * Instruct I/O Queue to accept incoming connection on the specified |
| 563 | * listening socket. This function will return immediately (i.e. non-blocking) |
| 564 | * regardless whether a connection is immediately available. If the function |
| 565 | * can't complete immediately, the caller will be notified about the incoming |
| 566 | * connection when it calls pj_ioqueue_poll(). If a new connection is |
| 567 | * immediately available, the function returns PJ_SUCCESS with the new |
| 568 | * connection; in this case, the callback WILL NOT be called. |
| 569 | * |
| 570 | * @param key The key which registered to the server socket. |
| 571 | * @param op_key An operation specific key to be associated with the |
| 572 | * pending operation, so that application can keep track of |
| 573 | * which operation has been completed when the callback is |
| 574 | * called. |
| 575 | * @param new_sock Argument which contain pointer to receive the new socket |
| 576 | * for the incoming connection. |
| 577 | * @param local Optional argument which contain pointer to variable to |
| 578 | * receive local address. |
| 579 | * @param remote Optional argument which contain pointer to variable to |
| 580 | * receive the remote address. |
| 581 | * @param addrlen On input, contains the length of the buffer for the |
| 582 | * address, and on output, contains the actual length of the |
| 583 | * address. This argument is optional. |
| 584 | * @return |
| 585 | * - PJ_SUCCESS When connection is available immediately, and the |
| 586 | * parameters will be updated to contain information about |
| 587 | * the new connection. In this case, a completion callback |
| 588 | * WILL NOT be called. |
| 589 | * - PJ_EPENDING If no connection is available immediately. When a new |
| 590 | * connection arrives, the callback will be called. |
| 591 | * - non-zero which indicates the appropriate error code. |
| 592 | */ |
| 593 | PJ_DECL(pj_status_t) pj_ioqueue_accept( pj_ioqueue_key_t *key, |
| 594 | pj_ioqueue_op_key_t *op_key, |
| 595 | pj_sock_t *new_sock, |
| 596 | pj_sockaddr_t *local, |
| 597 | pj_sockaddr_t *remote, |
| 598 | int *addrlen ); |
| 599 | |
| 600 | /** |
| 601 | * Initiate non-blocking socket connect. If the socket can NOT be connected |
| 602 | * immediately, asynchronous connect() will be scheduled and caller will be |
| 603 | * notified via completion callback when it calls pj_ioqueue_poll(). If |
| 604 | * socket is connected immediately, the function returns PJ_SUCCESS and |
| 605 | * completion callback WILL NOT be called. |
| 606 | * |
| 607 | * @param key The key associated with TCP socket |
| 608 | * @param addr The remote address. |
| 609 | * @param addrlen The remote address length. |
| 610 | * |
| 611 | * @return |
| 612 | * - PJ_SUCCESS If socket is connected immediately. In this case, the |
| 613 | * completion callback WILL NOT be called. |
| 614 | * - PJ_EPENDING If operation is queued, or |
| 615 | * - non-zero Indicates the error code. |
| 616 | */ |
| 617 | PJ_DECL(pj_status_t) pj_ioqueue_connect( pj_ioqueue_key_t *key, |
| 618 | const pj_sockaddr_t *addr, |
| 619 | int addrlen ); |
| 620 | |
| 621 | #endif /* PJ_HAS_TCP */ |
| 622 | |
| 623 | /** |
| 624 | * Poll the I/O Queue for completed events. |
| 625 | * |
| 626 | * Note: polling the ioqueue is not necessary in Symbian. Please see |
| 627 | * @ref PJ_SYMBIAN_OS for more info. |
| 628 | * |
| 629 | * @param ioque the I/O Queue. |
| 630 | * @param timeout polling timeout, or NULL if the thread wishes to wait |
| 631 | * indefinetely for the event. |
| 632 | * |
| 633 | * @return |
| 634 | * - zero if timed out (no event). |
| 635 | * - (<0) if error occured during polling. Callback will NOT be called. |
| 636 | * - (>1) to indicate numbers of events. Callbacks have been called. |
| 637 | */ |
| 638 | PJ_DECL(int) pj_ioqueue_poll( pj_ioqueue_t *ioque, |
| 639 | const pj_time_val *timeout); |
| 640 | |
| 641 | |
| 642 | /** |
| 643 | * Instruct the I/O Queue to read from the specified handle. This function |
| 644 | * returns immediately (i.e. non-blocking) regardless whether some data has |
| 645 | * been transfered. If the operation can't complete immediately, caller will |
| 646 | * be notified about the completion when it calls pj_ioqueue_poll(). If data |
| 647 | * is immediately available, the function will return PJ_SUCCESS and the |
| 648 | * callback WILL NOT be called. |
| 649 | * |
| 650 | * @param key The key that uniquely identifies the handle. |
| 651 | * @param op_key An operation specific key to be associated with the |
| 652 | * pending operation, so that application can keep track of |
| 653 | * which operation has been completed when the callback is |
| 654 | * called. Caller must make sure that this key remains |
| 655 | * valid until the function completes. |
| 656 | * @param buffer The buffer to hold the read data. The caller MUST make sure |
| 657 | * that this buffer remain valid until the framework completes |
| 658 | * reading the handle. |
| 659 | * @param length On input, it specifies the size of the buffer. If data is |
| 660 | * available to be read immediately, the function returns |
| 661 | * PJ_SUCCESS and this argument will be filled with the |
| 662 | * amount of data read. If the function is pending, caller |
| 663 | * will be notified about the amount of data read in the |
| 664 | * callback. This parameter can point to local variable in |
| 665 | * caller's stack and doesn't have to remain valid for the |
| 666 | * duration of pending operation. |
| 667 | * @param flags Recv flag. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then |
| 668 | * the function will never return PJ_SUCCESS. |
| 669 | * |
| 670 | * @return |
| 671 | * - PJ_SUCCESS If immediate data has been received in the buffer. In this |
| 672 | * case, the callback WILL NOT be called. |
| 673 | * - PJ_EPENDING If the operation has been queued, and the callback will be |
| 674 | * called when data has been received. |
| 675 | * - non-zero The return value indicates the error code. |
| 676 | */ |
| 677 | PJ_DECL(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key, |
| 678 | pj_ioqueue_op_key_t *op_key, |
| 679 | void *buffer, |
| 680 | pj_ssize_t *length, |
| 681 | pj_uint32_t flags ); |
| 682 | |
| 683 | /** |
| 684 | * This function behaves similarly as #pj_ioqueue_recv(), except that it is |
| 685 | * normally called for socket, and the remote address will also be returned |
| 686 | * along with the data. Caller MUST make sure that both buffer and addr |
| 687 | * remain valid until the framework completes reading the data. |
| 688 | * |
| 689 | * @param key The key that uniquely identifies the handle. |
| 690 | * @param op_key An operation specific key to be associated with the |
| 691 | * pending operation, so that application can keep track of |
| 692 | * which operation has been completed when the callback is |
| 693 | * called. |
| 694 | * @param buffer The buffer to hold the read data. The caller MUST make sure |
| 695 | * that this buffer remain valid until the framework completes |
| 696 | * reading the handle. |
| 697 | * @param length On input, it specifies the size of the buffer. If data is |
| 698 | * available to be read immediately, the function returns |
| 699 | * PJ_SUCCESS and this argument will be filled with the |
| 700 | * amount of data read. If the function is pending, caller |
| 701 | * will be notified about the amount of data read in the |
| 702 | * callback. This parameter can point to local variable in |
| 703 | * caller's stack and doesn't have to remain valid for the |
| 704 | * duration of pending operation. |
| 705 | * @param flags Recv flag. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then |
| 706 | * the function will never return PJ_SUCCESS. |
| 707 | * @param addr Optional Pointer to buffer to receive the address. |
| 708 | * @param addrlen On input, specifies the length of the address buffer. |
| 709 | * On output, it will be filled with the actual length of |
| 710 | * the address. This argument can be NULL if \c addr is not |
| 711 | * specified. |
| 712 | * |
| 713 | * @return |
| 714 | * - PJ_SUCCESS If immediate data has been received. In this case, the |
| 715 | * callback must have been called before this function |
| 716 | * returns, and no pending operation is scheduled. |
| 717 | * - PJ_EPENDING If the operation has been queued. |
| 718 | * - non-zero The return value indicates the error code. |
| 719 | */ |
| 720 | PJ_DECL(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key, |
| 721 | pj_ioqueue_op_key_t *op_key, |
| 722 | void *buffer, |
| 723 | pj_ssize_t *length, |
| 724 | pj_uint32_t flags, |
| 725 | pj_sockaddr_t *addr, |
| 726 | int *addrlen); |
| 727 | |
| 728 | /** |
| 729 | * Instruct the I/O Queue to write to the handle. This function will return |
| 730 | * immediately (i.e. non-blocking) regardless whether some data has been |
| 731 | * transfered. If the function can't complete immediately, the caller will |
| 732 | * be notified about the completion when it calls pj_ioqueue_poll(). If |
| 733 | * operation completes immediately and data has been transfered, the function |
| 734 | * returns PJ_SUCCESS and the callback will NOT be called. |
| 735 | * |
| 736 | * @param key The key that identifies the handle. |
| 737 | * @param op_key An operation specific key to be associated with the |
| 738 | * pending operation, so that application can keep track of |
| 739 | * which operation has been completed when the callback is |
| 740 | * called. |
| 741 | * @param data The data to send. Caller MUST make sure that this buffer |
| 742 | * remains valid until the write operation completes. |
| 743 | * @param length On input, it specifies the length of data to send. When |
| 744 | * data was sent immediately, this function returns PJ_SUCCESS |
| 745 | * and this parameter contains the length of data sent. If |
| 746 | * data can not be sent immediately, an asynchronous operation |
| 747 | * is scheduled and caller will be notified via callback the |
| 748 | * number of bytes sent. This parameter can point to local |
| 749 | * variable on caller's stack and doesn't have to remain |
| 750 | * valid until the operation has completed. |
| 751 | * @param flags Send flags. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then |
| 752 | * the function will never return PJ_SUCCESS. |
| 753 | * |
| 754 | * @return |
| 755 | * - PJ_SUCCESS If data was immediately transfered. In this case, no |
| 756 | * pending operation has been scheduled and the callback |
| 757 | * WILL NOT be called. |
| 758 | * - PJ_EPENDING If the operation has been queued. Once data base been |
| 759 | * transfered, the callback will be called. |
| 760 | * - non-zero The return value indicates the error code. |
| 761 | */ |
| 762 | PJ_DECL(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key, |
| 763 | pj_ioqueue_op_key_t *op_key, |
| 764 | const void *data, |
| 765 | pj_ssize_t *length, |
| 766 | pj_uint32_t flags ); |
| 767 | |
| 768 | |
| 769 | /** |
| 770 | * Instruct the I/O Queue to write to the handle. This function will return |
| 771 | * immediately (i.e. non-blocking) regardless whether some data has been |
| 772 | * transfered. If the function can't complete immediately, the caller will |
| 773 | * be notified about the completion when it calls pj_ioqueue_poll(). If |
| 774 | * operation completes immediately and data has been transfered, the function |
| 775 | * returns PJ_SUCCESS and the callback will NOT be called. |
| 776 | * |
| 777 | * @param key the key that identifies the handle. |
| 778 | * @param op_key An operation specific key to be associated with the |
| 779 | * pending operation, so that application can keep track of |
| 780 | * which operation has been completed when the callback is |
| 781 | * called. |
| 782 | * @param data the data to send. Caller MUST make sure that this buffer |
| 783 | * remains valid until the write operation completes. |
| 784 | * @param length On input, it specifies the length of data to send. When |
| 785 | * data was sent immediately, this function returns PJ_SUCCESS |
| 786 | * and this parameter contains the length of data sent. If |
| 787 | * data can not be sent immediately, an asynchronous operation |
| 788 | * is scheduled and caller will be notified via callback the |
| 789 | * number of bytes sent. This parameter can point to local |
| 790 | * variable on caller's stack and doesn't have to remain |
| 791 | * valid until the operation has completed. |
| 792 | * @param flags send flags. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then |
| 793 | * the function will never return PJ_SUCCESS. |
| 794 | * @param addr Optional remote address. |
| 795 | * @param addrlen Remote address length, \c addr is specified. |
| 796 | * |
| 797 | * @return |
| 798 | * - PJ_SUCCESS If data was immediately written. |
| 799 | * - PJ_EPENDING If the operation has been queued. |
| 800 | * - non-zero The return value indicates the error code. |
| 801 | */ |
| 802 | PJ_DECL(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key, |
| 803 | pj_ioqueue_op_key_t *op_key, |
| 804 | const void *data, |
| 805 | pj_ssize_t *length, |
| 806 | pj_uint32_t flags, |
| 807 | const pj_sockaddr_t *addr, |
| 808 | int addrlen); |
| 809 | |
| 810 | |
| 811 | /** |
| 812 | * !} |
| 813 | */ |
| 814 | |
| 815 | PJ_END_DECL |
| 816 | |
| 817 | #endif /* __PJ_IOQUEUE_H__ */ |
| 818 | |