📄 ioqueue.h
字号:
/* $Id: ioqueue.h 974 2007-02-19 01:13:53Z bennylp $ *//* * Copyright (C)2003-2007 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_IOQUEUE_H__#define __PJ_IOQUEUE_H__/** * @file ioqueue.h * @brief I/O Dispatching Mechanism */#include <pj/types.h>PJ_BEGIN_DECL/** * @defgroup PJ_IO Input/Output * @brief Input/Output * @ingroup PJ_OS * * This section contains API building blocks to perform network I/O and * communications. If provides: * - @ref PJ_SOCK *\n * A highly portable socket abstraction, runs on all kind of * network APIs such as standard BSD socket, Windows socket, Linux * \b kernel socket, PalmOS networking API, etc. * * - @ref pj_addr_resolve *\n * Portable address resolution, which implements #pj_gethostbyname(). * * - @ref PJ_SOCK_SELECT *\n * A portable \a select() like API (#pj_sock_select()) which can be * implemented with various back-ends. * * - @ref PJ_IOQUEUE *\n * Framework for dispatching network events. * * For more information see the modules below. *//** * @defgroup PJ_IOQUEUE IOQueue: I/O Event Dispatching with Proactor Pattern * @ingroup PJ_IO * @{ * * I/O Queue provides API for performing asynchronous I/O operations. It * conforms to proactor pattern, which allows application to submit an * asynchronous operation and to be notified later when the operation has * completed. * * The I/O Queue can work on both socket and file descriptors. For * asynchronous file operations however, one must make sure that the correct * file I/O back-end is used, because not all file I/O back-end can be * used with the ioqueue. Please see \ref PJ_FILE_IO for more details. * * The framework works natively in platforms where asynchronous operation API * exists, such as in Windows NT with IoCompletionPort/IOCP. In other * platforms, the I/O queue abstracts the operating system's event poll API * to provide semantics similar to IoCompletionPort with minimal penalties * (i.e. per ioqueue and per handle mutex protection). * * The I/O queue provides more than just unified abstraction. It also: * - makes sure that the operation uses the most effective way to utilize * the underlying mechanism, to achieve the maximum theoritical * throughput possible on a given platform. * - choose the most efficient mechanism for event polling on a given * platform. * * Currently, the I/O Queue is implemented using: * - <tt><b>select()</b></tt>, as the common denominator, but the least * efficient. Also the number of descriptor is limited to * \c PJ_IOQUEUE_MAX_HANDLES (which by default is 64). * - <tt><b>/dev/epoll</b></tt> on Linux (user mode and kernel mode), * a much faster replacement for select() on Linux (and more importantly * doesn't have limitation on number of descriptors). * - <b>I/O Completion ports</b> on Windows NT/2000/XP, which is the most * efficient way to dispatch events in Windows NT based OSes, and most * importantly, it doesn't have the limit on how many handles to monitor. * And it works with files (not only sockets) as well. * * * \section pj_ioqueue_concurrency_sec Concurrency Rules * * The items below describe rules that must be obeyed when using the I/O * queue, with regard to concurrency: * - simultaneous operations (by different threads) to different key is safe. * - simultaneous operations to the same key is also safe, except * <b>unregistration</b>, which is described below. * - <b>care must be taken when unregistering a key</b> from the * ioqueue. Application must take care that when one thread is issuing * an unregistration, other thread is not simultaneously invoking an * operation <b>to the same key</b>. *\n * This happens because the ioqueue functions are working with a pointer * to the key, and there is a possible race condition where the pointer * has been rendered invalid by other threads before the ioqueue has a * chance to acquire mutex on it. * * \section pj_ioqeuue_examples_sec Examples * * For some examples on how to use the I/O Queue, please see: * * - \ref page_pjlib_ioqueue_tcp_test * - \ref page_pjlib_ioqueue_udp_test * - \ref page_pjlib_ioqueue_perf_test *//** * This structure describes operation specific key to be submitted to * I/O Queue when performing the asynchronous operation. This key will * be returned to the application when completion callback is called. * * Application normally wants to attach it's specific data in the * \c user_data field so that it can keep track of which operation has * completed when the callback is called. Alternatively, application can * also extend this struct to include its data, because the pointer that * is returned in the completion callback will be exactly the same as * the pointer supplied when the asynchronous function is called. */typedef struct pj_ioqueue_op_key_t{ void *internal__[32]; /**< Internal I/O Queue data. */ void *user_data; /**< Application data. */} pj_ioqueue_op_key_t;/** * This structure describes the callbacks to be called when I/O operation * completes. */typedef struct pj_ioqueue_callback{ /** * This callback is called when #pj_ioqueue_recv or #pj_ioqueue_recvfrom * completes. * * @param key The key. * @param op_key Operation key. * @param bytes_read >= 0 to indicate the amount of data read, * otherwise negative value containing the error * code. To obtain the pj_status_t error code, use * (pj_status_t code = -bytes_read). */ void (*on_read_complete)(pj_ioqueue_key_t *key, pj_ioqueue_op_key_t *op_key, pj_ssize_t bytes_read); /** * This callback is called when #pj_ioqueue_write or #pj_ioqueue_sendto * completes. * * @param key The key. * @param op_key Operation key. * @param bytes_sent >= 0 to indicate the amount of data written, * otherwise negative value containing the error * code. To obtain the pj_status_t error code, use * (pj_status_t code = -bytes_sent). */ void (*on_write_complete)(pj_ioqueue_key_t *key, pj_ioqueue_op_key_t *op_key, pj_ssize_t bytes_sent); /** * This callback is called when #pj_ioqueue_accept completes. * * @param key The key. * @param op_key Operation key. * @param sock Newly connected socket. * @param status Zero if the operation completes successfully. */ void (*on_accept_complete)(pj_ioqueue_key_t *key, pj_ioqueue_op_key_t *op_key, pj_sock_t sock, pj_status_t status); /** * This callback is called when #pj_ioqueue_connect completes. * * @param key The key. * @param status PJ_SUCCESS if the operation completes successfully. */ void (*on_connect_complete)(pj_ioqueue_key_t *key, pj_status_t status);} pj_ioqueue_callback;/** * Types of pending I/O Queue operation. This enumeration is only used * internally within the ioqueue. */typedef enum pj_ioqueue_operation_e{ PJ_IOQUEUE_OP_NONE = 0, /**< No operation. */ PJ_IOQUEUE_OP_READ = 1, /**< read() operation. */ PJ_IOQUEUE_OP_RECV = 2, /**< recv() operation. */ PJ_IOQUEUE_OP_RECV_FROM = 4, /**< recvfrom() operation. */ PJ_IOQUEUE_OP_WRITE = 8, /**< write() operation. */ PJ_IOQUEUE_OP_SEND = 16, /**< send() operation. */ PJ_IOQUEUE_OP_SEND_TO = 32, /**< sendto() operation. */#if defined(PJ_HAS_TCP) && PJ_HAS_TCP != 0 PJ_IOQUEUE_OP_ACCEPT = 64, /**< accept() operation. */ PJ_IOQUEUE_OP_CONNECT = 128 /**< connect() operation. */#endif /* PJ_HAS_TCP */} pj_ioqueue_operation_e;/** * This macro specifies the maximum number of events that can be * processed by the ioqueue on a single poll cycle, on implementation * that supports it. The value is only meaningfull when specified * during PJLIB build. */#ifndef PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL# define PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL (16)#endif/** * When this flag is specified in ioqueue's recv() or send() operations, * the ioqueue will always mark the operation as asynchronous. */#define PJ_IOQUEUE_ALWAYS_ASYNC ((pj_uint32_t)1 << (pj_uint32_t)31)/** * Return the name of the ioqueue implementation. * * @return Implementation name. */PJ_DECL(const char*) pj_ioqueue_name(void);/** * Create a new I/O Queue framework. * * @param pool The pool to allocate the I/O queue structure. * @param max_fd The maximum number of handles to be supported, which * should not exceed PJ_IOQUEUE_MAX_HANDLES. * @param ioqueue Pointer to hold the newly created I/O Queue. * * @return PJ_SUCCESS on success. */PJ_DECL(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, pj_size_t max_fd, pj_ioqueue_t **ioqueue);/** * Destroy the I/O queue. * * @param ioque The I/O Queue to be destroyed. * * @return PJ_SUCCESS if success. */PJ_DECL(pj_status_t) pj_ioqueue_destroy( pj_ioqueue_t *ioque );/** * Set the lock object to be used by the I/O Queue. This function can only * be called right after the I/O queue is created, before any handle is * registered to the I/O queue. * * Initially the I/O queue is created with non-recursive mutex protection. * Applications can supply alternative lock to be used by calling this * function. * * @param ioque The ioqueue instance. * @param lock The lock to be used by the ioqueue. * @param auto_delete In non-zero, the lock will be deleted by the ioqueue. * * @return PJ_SUCCESS or the appropriate error code. */PJ_DECL(pj_status_t) pj_ioqueue_set_lock( pj_ioqueue_t *ioque, pj_lock_t *lock, pj_bool_t auto_delete );/** * Register a socket to the I/O queue framework. * When a socket is registered to the IOQueue, it may be modified to use * non-blocking IO. If it is modified, there is no guarantee that this * modification will be restored after the socket is unregistered. * * @param pool To allocate the resource for the specified handle, * which must be valid until the handle/key is unregistered * from I/O Queue. * @param ioque The I/O Queue. * @param sock The socket. * @param user_data User data to be associated with the key, which can be * retrieved later. * @param cb Callback to be called when I/O operation completes. * @param key Pointer to receive the key to be associated with this * socket. Subsequent I/O queue operation will need this * key. * * @return PJ_SUCCESS on success, or the error code. */PJ_DECL(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, pj_ioqueue_t *ioque, pj_sock_t sock, void *user_data, const pj_ioqueue_callback *cb, pj_ioqueue_key_t **key );/** * Unregister from the I/O Queue framework. Caller must make sure that * the key doesn't have any pending operations before calling this function, * by calling #pj_ioqueue_is_pending() for all previously submitted * operations except asynchronous connect, and if necessary call * #pj_ioqueue_post_completion() to cancel the pending operations. * * Note that asynchronous connect operation will automatically be * cancelled during the unregistration. * * Also note that when I/O Completion Port backend is used, application * MUST close the handle immediately after unregistering the key. This is * because there is no unregistering API for IOCP. The only way to * unregister the handle from IOCP is to close the handle. * * @param key The key that was previously obtained from registration. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -