/**
 * @file	acl_aio.h
 * @author	zsx
 * @date	2010-1-2
 * @brief	ļж˹ ACL_ASTREAM첽ͨ˵ӿ.
 * @version	1.1
 */

#ifndef	ACL_AIO_INCLUDE_H
#define	ACL_AIO_INCLUDE_H

#ifdef	__cplusplus
extern "C" {
#endif

#include "../stdlib/acl_define.h"
#include <stdarg.h>
#ifdef	ACL_UNIX
#include <sys/uio.h>
#endif

#include "../stdlib/acl_stdlib.h"
#include "../event/acl_events.h"
#include "../net/acl_netdb.h"

/*------------------------------- ݽṹͶ ---------------------------*/

/**
 * 첽Ͷ
 */
typedef struct ACL_AIO ACL_AIO;

/**
 * 첽Ͷ
 */
typedef struct ACL_ASTREAM ACL_ASTREAM;

/**
 * ¼֪ͨ, ĳܼصݿɶʱĻصûעắ,
 * Ŀǰص첽:
 *   acl_aio_gets, acl_aio_gets_nonl, acl_aio_read, acl_aio_readn.
 * @param astream {ACL_ASTREAM*} 첽ָ
 * @param context {void*} ûݵĲ
 * @param data {const char*} жȡָ
 * @param dlen {int} data ݵĳ
 * @return {int} úָ-1ӦҪر첽
 */
typedef int (*ACL_AIO_READ_FN)(ACL_ASTREAM *astream,
	void *context, char *data, int dlen);

/**
 * ¼֪ͨͣĳ첽ɶ/дʱô͵ûص
 * @param astream {ACL_ASTREAM*} 첽ָ
 * @param context {void*} ûݵĲ
 * @return {int} úͷ -1 ӦҪر첽
 */
typedef int (*ACL_AIO_NOTIFY_FN)(ACL_ASTREAM *astream, void *context);

/**
 * ¼֪ͨ, ĳܼصдʱĻصûעắ,
 * Ŀǰص첽:
 *   acl_aio_writen, acl_aio_writev, acl_aio_fprintf, acl_aio_vfprintf.
 * @param astream {ACL_ASTREAM*} 첽ָ
 * @param context {void*} ûݵĲ
 * @return {int} úָ-1ӦҪر첽
 */
typedef int (*ACL_AIO_WRITE_FN)(ACL_ASTREAM *astream, void *context);

/**
 * ĳµĿͻʱ, 첽ܽոӲݸû; ,
 * û˸üļʱֵҵóʱֵ, Ҳᴥú;. ú
 * ;ص첽: acl_aio_accept.
 * @param cstream {ACL_ASTREAM*}  sstream ͨ accept() õĿͻ
 * @param context {void*} ûݵĲ
 * @return {int} ú÷ -1 ʾټµĿͻ
 */
typedef int (*ACL_AIO_ACCEPT_FN)(ACL_ASTREAM *cstream,	void *context);

/**
 * ĳµĿͻʱ, 첽ܻصûעắ, ûҪ
 * ü accept ÿͻ. úص첽: acl_aio_listen.
 * @param sstream {ACL_ASTREAM*} 
 * @param context {void*} ûݵĲ
 * @return {int} úĵ÷-1Ӱ
 * ע: עú ACL_AIO_ACCEPT_FN Ĺܲ.
 */
typedef int (*ACL_AIO_LISTEN_FN)(ACL_ASTREAM *sstream, void *context);

/**
 * 첽Զ̷ʱ, ʧܡʱɹʱ¼֪ͨ
 * صûעắ. úص첽: acl_aio_connect.
 * @param cstream {ACL_ASTREAM*} ܼص״̬Ŀͻ
 * @param context {void*} ûݵĲ
 * @return {int} øú-1Ҫرո첽
 */
typedef int (*ACL_AIO_CONNECT_FN)(ACL_ASTREAM *cstream, void *context);

typedef struct ACL_ASTREAM_CTX ACL_ASTREAM_CTX;

ACL_API int acl_astream_get_status(const ACL_ASTREAM_CTX *ctx);
#define ACL_ASTREAM_STATUS_INVALID		-1
#define ACL_ASTREAM_STATUS_OK			0
#define ACL_ASTREAM_STATUS_NS_ERROR		1
#define ACL_ASTREAM_STATUS_CONNECT_ERROR	2
#define ACL_ASTREAM_STATUS_CONNECT_TIMEOUT	3

ACL_API const ACL_SOCKADDR *acl_astream_get_ns_addr(const ACL_ASTREAM_CTX *ctx);
ACL_API const ACL_SOCKADDR *acl_astream_get_serv_addr(const ACL_ASTREAM_CTX *ctx);
ACL_API ACL_ASTREAM *acl_astream_get_conn(const ACL_ASTREAM_CTX *ctx);
ACL_API void *acl_astream_get_ctx(const ACL_ASTREAM_CTX *ctx);

/**
 * 첽Զ̷ʱĻص壬 acl_aio_connect_addr() ʹ
 * @param ctx {ACL_ASTREAM_CTX*} صĲ acl_astream_get_xxx
 *  øöаĶָ
 */
typedef int (*ACL_AIO_CONNECT_ADDR_FN)(const ACL_ASTREAM_CTX *ctx);

/**
 * дʱĻصָ
 * @param astream {ACL_ASTREAM*} 첽ָ
 * @param context {void*} ûݵĲ
 * @return {int} ú÷-1ʱڶдʾҪرո첽д
 *  ڼʾټµĿͻӣ0ʱʾ
 */
typedef int (*ACL_AIO_TIMEO_FN)(ACL_ASTREAM *astream, void *context);

/**
 * Ҫر첽дʱҪصûעĺ
 * @param astream {ACL_ASTREAM*} 첽ָ
 * @param context {void*} ûݵĲ
 * @return {int} ۸ֵΣ첽Ҫر
 */
typedef int (*ACL_AIO_CLOSE_FN)(ACL_ASTREAM *astream, void *context);

/* 첽Ͷ */

struct ACL_ASTREAM {
	ACL_AIO *aio;		/**< 첽¼ */
	ACL_VSTREAM *stream;	/**< ͬ */

	ACL_VSTRING strbuf;	/**< ڲ */
	int   timeout;		/**< IOʱʱ */
	int   nrefer;		/**< ͨüֹǰر */
	int   flag;		/**< ־λ */
#define ACL_AIO_FLAG_IOCP_CLOSE     (1 << 0) /* Ƿ IOCP رձ־λ */
#define	ACL_AIO_FLAG_ISRD           (1 << 1) /* Ƿע˶¼ */
#define	ACL_AIO_FLAG_ISWR           (1 << 2) /* Ƿעд¼ */
#define ACL_AIO_FLAG_DELAY_CLOSE    (1 << 3) /* Ƿʱر״̬ */
#define ACL_AIO_FLAG_DEAD           (1 << 4) /* ׽ǷѾ */
#define	ACL_AIO_FLAG_FLUSH_CLOSE    (1 << 5) /* ǷҪݺŹر */

	ACL_FIFO write_fifo;	/**< 첽дʱȽȳ */
	int   write_left;	/**< дδд */
	int   write_offset;	/**< деһλƫ */
	int   write_nested;	/**< дʱǶײ */
	int   write_nested_limit;  /**< дʱǶײ */

	int   (*read_ready_fn) (ACL_VSTREAM *, ACL_VSTRING *, int *);
	int   read_nested;	/**< ʱǶײ */
	int   read_nested_limit;  /**< ʱǶײ */
	int   count;		/**<  acl_aio_readn()/2 ʱõĵڶֵ */
	int   keep_read;	/**< ǷóԶ */
	int   accept_nloop;	/**<  acl_aio_accept ڲѭ accept  */
	int   error;		/**< ǰ׽ӿڵĴ */
	int   line_length;	/**< Ϊλʱֵÿ󳤶 */

	ACL_AIO_ACCEPT_FN  accept_fn;	/**< accept ʱĻص */
	ACL_AIO_LISTEN_FN  listen_fn;	/**< ӵʱĻص */
	void *context;			/**< ûõĲ */

	ACL_AIO_NOTIFY_FN  can_read_fn; /**< ԶʱĻص */
	void *can_read_ctx;		/**< can_read_fn ֮һ */
	ACL_AIO_NOTIFY_FN  can_write_fn; /**< дʱĻص */
	void *can_write_ctx;		/**< can_write_fn ֮һ */

	ACL_ARRAY *read_handles;	/**< ʱĸص */
	ACL_ARRAY *write_handles;	/**< дʱĸص */
	ACL_ARRAY *close_handles;	/**< رʱĸص */
	ACL_ARRAY *timeo_handles;	/**< ʱʱĸص */
	ACL_ARRAY *connect_handles;	/**< ӳɹʱص */
	ACL_FIFO   reader_fifo;		/**< ʱŻص */
	ACL_FIFO   writer_fifo;		/**< ʱŻص */

	/* ɶʱĻص */
	void (*event_read_callback)(int event_type, ACL_ASTREAM *astream);
};

/**
 * IOʱʱ
 */
#define ACL_AIO_SET_TIMEOUT(stream_ptr, _timeo_) do {  \
	ACL_ASTREAM *__stream_ptr = stream_ptr;        \
	__stream_ptr->timeout = _timeo_;               \
} while(0)

/**
 *  context 
 */
#define ACL_AIO_SET_CTX(stream_ptr, _ctx_) do {  \
	ACL_ASTREAM *__stream_ptr = stream_ptr;  \
	__stream_ptr->context = _ctx_;           \
} while(0)

/*--------------------------- 첽ӿ -------------------------------*/

/**
 * һ첽ͨŵ첽ʵ, ָǷ epoll/devpoll
 * @param event_mode {int} ¼ʽ: ACL_EVENT_SELECT, ACL_EVENT_POLL
 *  , ACL_EVENT_KERNEL, ACL_EVENT_WMSG
 * @return {ACL_AIO*} һ첽. OK: != NULL; ERR: == NULL.
 */
ACL_API ACL_AIO *acl_aio_create(int event_mode);

/**
 * 첽ʵ, ָǷ epoll/devpoll/windows message
 * @param event_mode {int} ¼ʽ: ACL_EVENT_SELECT, ACL_EVENT_POLL
 *  , ACL_EVENT_KERNEL, ACL_EVENT_WMSG
 * @param nMsg {unsigned int}  _WIN32 Ϣʱ event_mode Ϊ
 *  ACL_EVENT_WMSG ʱֵЧʾ첽󶨵Ϣֵ
 * @return {ACL_AIO*} һ첽. OK: != NULL; ERR: == NULL.
 */
ACL_API ACL_AIO *acl_aio_create2(int event_mode, unsigned int nMsg);

/**
 * ¼첽
 * @param event {ACL_EVENT *}
 * @return {ACL_AIO *}
 */
ACL_API ACL_AIO *acl_aio_create3(ACL_EVENT *event);

/**
 * ñ aio 󶨵 DNS ѯ
 * @param aio {ACL_AIO*}
 * @return {ACL_DNS*}  NULL ʾûа DNS ѯ󣬵ֵ NULL ʱӦÿ
 *  ֱӽֵתΪ ACL_DNS XXXΪѭͷļ⣬ˣ
 */
ACL_API void *acl_aio_dns(ACL_AIO *aio);

/**
 *  DNS ַбֻ DNS ַڲŻ֧
 * 첽ӷַ
 * @param aio {ACL_AIO*}
 * @param dns_list {const char*} DNS ַбʽip1:port,ip2:port...
 * @param timeout {int} ʱʱ䣨룩
 * @return {int}  DNS ѯǷɹ0 ʾɹ-1 ʾʧܣʧԭ
 *  У޷ UDP ׽ֻ UDP ׽ʧ
 */
ACL_API int acl_aio_set_dns(ACL_AIO *aio, const char *dns_list, int timeout);

/**
 * ɾ DNS ַб
 * @param aio {ACL_AIO*}
 * @param dns_list {const char*} DNS ַбʽip1:port,ip2:port...
 */
ACL_API void acl_aio_del_dns(ACL_AIO *aio, const char *dns_list);

/**
 *  aio а󶨵 DNS ַ
 * @param aio {ACL_AIO*}
 */
ACL_API void acl_aio_clear_dns(ACL_AIO *aio);

/**
 * ͷһ첽ͨ첽ʵͬʱͷŵǿյ aio->event 
 * @param aio {ACL_AIO*} 첽
 */
ACL_API void acl_aio_free(ACL_AIO *aio);

/**
 * ͷһ첽ͨ첽ʵ
 * @param keep {int} Ƿͬʱͷŵ aio 󶨵 event ¼
 * @param aio {ACL_AIO*} 첽
 */
ACL_API void acl_aio_free2(ACL_AIO *aio, int keep);

/**
 * 첽IOϢѭ(ڵ߳ģʽµ)
 * @param aio {ACL_AIO*} 첽
 */
ACL_API void acl_aio_loop(ACL_AIO *aio);

/**
 * ñ¼ѭ¼
 * @param aio {ACL_AIO*} 첽
 * @return {int} -1 ʾ󣬷򷵻ֵ >= 0
 */
ACL_API int acl_aio_last_nready(ACL_AIO *aio);

/**
 *  ACL_AIO дرյ첽ǷӦùرգô˺һЩҪ
 * ӳٹرյ첽ᱻر
 * @param aio {ACL_AIO*} 첽
 */
ACL_API void acl_aio_check(ACL_AIO *aio);

/**
 * ¼ľ
 * @param aio {ACL_AIO*} 첽
 * @return {ACL_EVENT*}
 */
ACL_API ACL_EVENT *acl_aio_event(ACL_AIO *aio);

/**
 * ¼õģʽ
 * @param aio {ACL_AIO*} 첽
 * @return {int} ACL_EVENT_KERNEL/ACL_EVENT_SELECT/ACL_EVENT_POLL
 */
ACL_API int acl_aio_event_mode(ACL_AIO *aio);

/**
 * 첽IOǷǲóģʽ
 * @param aio {ACL_AIO*} 첽
 * @return {int} != 0: ; == 0: 
 */
ACL_API int acl_aio_get_keep_read(ACL_AIO *aio);

/**
 * 첽IOܵĳģʽ
 * @param aio {ACL_AIO*} 첽
 * @param onoff {int} 0: رճ; != 0: 򿪳
 */
ACL_API void acl_aio_set_keep_read(ACL_AIO *aio, int onoff);

/**
 * õǰ첽ѭʱĵȴʱ벿
 * @param aio {ACL_AIO*} 첽
 * @return {int}  select/poll/epoll/kqueue/devpoll ʱ뼶ȴʱ
 */
ACL_API int acl_aio_get_delay_sec(ACL_AIO *aio);

/**
 * õǰ첽ѭʱĵȴʱ΢벿
 * @param aio {ACL_AIO*} 첽
 * @return {int}  select/poll/epoll/kqueue/devpoll ʱ΢뼶ȴʱ
 */
ACL_API int acl_aio_get_delay_usec(ACL_AIO *aio);

/**
 * 첽ѭĵȴʱе뼶
 * @param aio {ACL_AIO*} 첽
 * @param delay_sec {int}  select/poll/epoll/kqueue/devpoll
 *  ʱ뼶ȴʱ
 */
ACL_API void acl_aio_set_delay_sec(ACL_AIO *aio, int delay_sec);

/**
 * 첽ѭĵȴʱе΢뼶
 * @param aio {ACL_AIO*} 첽
 * @param delay_usec {int}  select/poll/epoll/kqueue/devpoll
 *  ʱ΢뼶ȴʱ
 */
ACL_API void acl_aio_set_delay_usec(ACL_AIO *aio, int delay_usec);

/**
 * ¼ѭжʱ״̬ʱڲȱʡֵΪ 100 ms
 * @param aio {ACL_AIO*} 첽
 * @param check_inter {int} ʱʱ (뼶)
 */
ACL_API void acl_aio_set_check_inter(ACL_AIO *aio, int check_inter);

/**
 * 첽ĶС
 * @param aio {ACL_AIO*} 첽
 * @param rbuf_size {int} С
 */
ACL_API void acl_aio_set_rbuf_size(ACL_AIO *aio, int rbuf_size);

/**
 * ü첽ÿνտͻʱѭո
 * @param astream {ACL_ASTREAM*} 
 * @param nloop {int}
 */
ACL_API void acl_aio_set_accept_nloop(ACL_ASTREAM *astream, int nloop);

/**
 * 첽л첽
 * @param stream {ACL_ASTREAM*} 첽IO
 * @return {ACL_AIO*} 첽
 */
ACL_API ACL_AIO *acl_aio_handle(ACL_ASTREAM *stream);

/**
 * 첽Ĳ
 * @param stream {ACL_ASTREAM*} 첽IO
 * @param ctx {void*} 
 */
ACL_API void acl_aio_set_ctx(ACL_ASTREAM *stream, void *ctx);

/**
 * 첽Ĳ
 * @param stream {ACL_ASTREAM*} 첽IO
 * @return {void*} 첽 stream Ĳ
 */
ACL_API void *acl_aio_get_ctx(ACL_ASTREAM *stream);

/**
 * һ첽ͨľ
 * @param aio {ACL_AIO*} 첽
 * @param stream {ACL_VSTREAM*} ܼص, һݡ
 *  ʱʱصûעắ.
 * @return {ACL_ASTREAM*} 첽ͨ
 */
ACL_API ACL_ASTREAM *acl_aio_open(ACL_AIO *aio, ACL_VSTREAM *stream);

/**
 * 첽IOɺر첽رնҪȶдʱŹر
 * @param astream {ACL_ASTREAM*} 첽
 */
ACL_API void acl_aio_iocp_close(ACL_ASTREAM *astream);

/**
 * ڹر׽ǰǷҪȽед꣬ڲȱʡֵΪ 1 (Ҫд
 * Żر), ҪرӶصд,Ҫô˷
 * õڶΪ0
 * @param astream {ACL_ASTREAM*} 첽
 * @param yes {int}  0 ʾر׽ǰҪдед
 */
ACL_API void acl_aio_flush_on_close(ACL_ASTREAM *astream, int yes);

/**
 * ȡ첽IỌùҪΪ˽첽IOתΪͬIOд
 * @param astream {ACL_ASTREAM*} 첽IO
 * @return {ACL_VSTREAM*} 
 */
ACL_API ACL_VSTREAM *acl_aio_cancel(ACL_ASTREAM *astream);

/**
 * üÿνտͻӵ
 * @param astream {ACL_ASTREAM *} 
 * @return {int} ÿνӵ
 * @return {int} ÿνչпѭյ
 *  ֵСΪ1
 */
ACL_API int acl_aio_get_accept_max(ACL_ASTREAM *astream);

/**
 * üÿνտͻӵ
 * @param astream {ACL_ASTREAM *} 
 * @param accept_max {int} ÿνչпѭյ
 *  ֵСΪ1
 */
ACL_API void acl_aio_set_accept_max(ACL_ASTREAM *astream, int accept_max);

/**
 * ӸӶص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 * @param callback {ACL_AIO_READ_FN} صΪ
 * @param ctx {void*} callback صĻصΪ
 */
ACL_API void acl_aio_add_read_hook(ACL_ASTREAM *astream,
	ACL_AIO_READ_FN callback, void *ctx);

/**
 * Ӹдص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 * @param callback {ACL_AIO_READ_FN} صΪ
 * @param ctx {void*} callback صĻصΪ
 */
ACL_API void acl_aio_add_write_hook(ACL_ASTREAM *astream,
	ACL_AIO_WRITE_FN callback, void *ctx);

/**
 * Ӹӹرջص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 * @param callback {ACL_AIO_READ_FN} صΪ
 * @param ctx {void*} callback صĻصΪ
 */
ACL_API void acl_aio_add_close_hook(ACL_ASTREAM *astream,
	ACL_AIO_CLOSE_FN callback, void *ctx);

/**
 * Ӹӳʱص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 * @param callback {ACL_AIO_READ_FN} صΪ
 * @param ctx {void*} callback صĻصΪ
 */
ACL_API void acl_aio_add_timeo_hook(ACL_ASTREAM *astream,
	ACL_AIO_TIMEO_FN callback, void *ctx);

/**
 * Ӹӳɹص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 * @param callback {ACL_AIO_READ_FN} صΪ
 * @param ctx {void*} callback صĻصΪ
 */
ACL_API void acl_aio_add_connect_hook(ACL_ASTREAM *astream,
	ACL_AIO_CONNECT_FN callback, void *ctx);

/**
 * ɾӶص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 * @param callback {ACL_AIO_READ_FN} صΪ
 * @param ctx {void*} callback صĻصΪ
 */
ACL_API void acl_aio_del_read_hook(ACL_ASTREAM *astream,
	ACL_AIO_READ_FN callback, void *ctx);

/**
 * ɾдص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 * @param callback {ACL_AIO_READ_FN} صΪ
 * @param ctx {void*} callback صĻصΪ
 */
ACL_API void acl_aio_del_write_hook(ACL_ASTREAM *astream,
	ACL_AIO_WRITE_FN callback, void *ctx);

/**
 * ɾӹرջص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 * @param callback {ACL_AIO_READ_FN} صΪ
 * @param ctx {void*} callback صĻصΪ
 */
ACL_API void acl_aio_del_close_hook(ACL_ASTREAM *astream,
	ACL_AIO_CLOSE_FN callback, void *ctx);

/**
 * ɾӳʱص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 * @param callback {ACL_AIO_READ_FN} صΪ
 * @param ctx {void*} callback صĻصΪ
 */
ACL_API void acl_aio_del_timeo_hook(ACL_ASTREAM *astream,
	ACL_AIO_TIMEO_FN callback, void *ctx);

/**
 * ɾӳɹص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 * @param callback {ACL_AIO_READ_FN} صΪ
 * @param ctx {void*} callback صĻصΪ
 */
ACL_API void acl_aio_del_connect_hook(ACL_ASTREAM *astream,
	ACL_AIO_CONNECT_FN callback, void *ctx);

/**
 * еĸӶص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 */
ACL_API void acl_aio_clean_read_hooks(ACL_ASTREAM *astream);

/**
 * еĸдص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 */
ACL_API void acl_aio_clean_write_hooks(ACL_ASTREAM *astream);

/**
 * еĸӹرջص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 */
ACL_API void acl_aio_clean_close_hooks(ACL_ASTREAM *astream);

/**
 * еĸӳʱص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 */
ACL_API void acl_aio_clean_timeo_hooks(ACL_ASTREAM *astream);

/**
* еĸӳɹص
* @param astream {ACL_ASTREAM*} 첽Ϊ
*/
ACL_API void acl_aio_clean_connect_hooks(ACL_ASTREAM *astream);

/**
 * еĸӻص
 * @param astream {ACL_ASTREAM*} 첽Ϊ
 */
ACL_API void acl_aio_clean_hooks(ACL_ASTREAM *astream);

/**
 * 첽
 * @param astream {ACL_ASTREAM*} 첽
 * @param name {int} һƲ
 * @param ... бʽΪACL_AIO_CTL_XXX, xxx, һƲ
 *  Ϊ ACL_AIO_CTL_END
 */
ACL_API void acl_aio_ctl(ACL_ASTREAM *astream, int name, ...);
#define ACL_AIO_CTL_END                 0   /**< ƽ־ */
#define ACL_AIO_CTL_ACCEPT_FN           1   /**< ýӺص */
#define ACL_AIO_CTL_LISTEN_FN           2   /**< ӵʱص */
#define ACL_AIO_CTL_CTX                 3   /**< ӦõĲ */
#define ACL_AIO_CTL_TIMEOUT             4   /**< óʱʱ */
#define	ACL_AIO_CTL_LINE_LENGTH         5   /**< ݵ󳤳 */
#define ACL_AIO_CTL_STREAM              10  /**< ACL_VSTREAMָ */
#define ACL_AIO_CTL_READ_NESTED         11  /**< Ƕײ */
#define ACL_AIO_CTL_WRITE_NESTED        12  /**< дǶײ */
#define ACL_AIO_CTL_KEEP_READ           13  /**< Ƿ־ */
#define	ACL_AIO_CTL_READ_HOOK_ADD       14  /**< ӸӶص */
#define	ACL_AIO_CTL_READ_HOOK_DEL       15  /**< ɾӶص */
#define	ACL_AIO_CTL_WRITE_HOOK_ADD      16  /**< Ӹдص */
#define	ACL_AIO_CTL_WRITE_HOOK_DEL      17  /**< ɾдص */
#define	ACL_AIO_CTL_CLOSE_HOOK_ADD      18  /**< Ӹӹرջص */
#define	ACL_AIO_CTL_CLOSE_HOOK_DEL      19  /**< ɾӹرջص */
#define	ACL_AIO_CTL_TIMEO_HOOK_ADD      20  /**< Ӹӳʱص */
#define	ACL_AIO_CTL_TIMEO_HOOK_DEL      21  /**< ɾӳʱص */
#define	ACL_AIO_CTL_CONNECT_HOOK_ADD    22  /**< Ӹӻص */
#define	ACL_AIO_CTL_CONNECT_HOOK_DEL    23  /**< ɾӻص */

/**
 * 첽ȡ ACL_VSTREAM 
 * @param astream {ACL_ASTREAM*} 첽IO
 * @return {ACL_VSTREAM*} ָͨ
 */
ACL_API ACL_VSTREAM *acl_aio_vstream(ACL_ASTREAM *astream);

/*---------------------------- 첽ӿ --------------------------------*/

/**
 * 첽жȡһ, ɹȡһݡʱʱصû
 * עắ: notify_fn
 * @param astream {ACL_ASTREAM*} ܼص, һݡ
 *  ʱʱصûעắ.
 * ע: 첽.
 *     ͨ acl_aio_stream_set_line_length 󳤶ƣ򵱽յ
 *     йʱΪ⻺úĴ̽ڻﵽó
 *     ʱֱӽݽʹעĻص
 */
ACL_API void acl_aio_gets(ACL_ASTREAM *astream);

/**
 * 첽жȡһ, ɹȡһݡʱʱصû
 * עắ: notify_fn,  acl_aio_gets , ΨһǷص
 * data в "\r\n"  "\n", һʱ,  dlen == 0.
 * @param astream {ACL_ASTREAM*} ܼص, һݡ
 *  ʱʱصûעắ.
 * ע: 첽.
 *     йʱΪ⻺úĴ̽ڻﵽó
 *     ʱֱӽݽʹעĻص
 */
ACL_API void acl_aio_gets_nonl(ACL_ASTREAM *astream);

/**
 * 첽жȡ, ȡݸʽûҪ.
 * @param astream {ACL_ASTREAM*} ڶص. ʱѾȡһ
 *  ȵʱ¼֪ͨ
 * ע: 첽.
 */
ACL_API void acl_aio_read(ACL_ASTREAM *astream);

/**
 * 첽жȡҪ󳤶ȵ, ʱҪݳʱ
 * ¼֪ͨ
 * @param astream {ACL_ASTREAM*} ڶص. ʱѾȡ
 *  Ҫ󳤶ȵʱ¼֪ͨ
 * @param count {int} Ҫݵĳ,  0.
 * ע: 첽.
 */
ACL_API void acl_aio_readn(ACL_ASTREAM *astream, int count);

/**
 * Զȡһ
 * @param astream {ACL_ASTREM*} 첽
 * @return {ACL_VSTRING*} һ򷵻طǿնû ACL_VSTRING
 *  ݺӦ ACL_VSTRING_RESET(s) ջ; δ򷵻ؿ
 */
ACL_API ACL_VSTRING *acl_aio_gets_peek(ACL_ASTREAM *astream);

/**
 * Զȡһ( \n  \r\n)
 * @param astream {ACL_ASTREM*} 첽
 * @return {ACL_VSTRING*} һ򷵻طǿնû ACL_VSTRING
 *  ݺӦ ACL_VSTRING_RESET(s) ջ, һУ򷵻ص
 *  ACL_VSTRING Ļݳ(ACL_VSTRING_LEN ôֵ) ӦΪ 0;
 *  δ򷵻ؿ
 */
ACL_API ACL_VSTRING *acl_aio_gets_nonl_peek(ACL_ASTREAM *astream);

/**
 * Դ첽жȡݣ򷵻û򷵻ؿ
 * @param astream {ACL_ASTREM*} 첽
 * @param count {int*} غ󽫴űζݳȣֵԶ >= 0
 * @return {ACL_VSTRING*} 򷵻صĻǿ(ʹ˻
 *  Ҫ ACL_VSTRING_RESET(s) մ˻), 򷵻ؿ
 */
ACL_API ACL_VSTRING *acl_aio_read_peek(ACL_ASTREAM *astream, int *count);

/**
 * Դ첽жȵݣҪ򷵻ػ
 * @param astream {ACL_ASTREM*} 첽
 * @param count {int*} Ҫݳȣغ󽫴űζֽ
 *  ŵֵԶ >= 0
 * @return {ACL_VSTRING*} 涨򷵻طǿջ(ʹ˻
 *  Ҫ ACL_VSTRING_RESET(s) մ˻), 򷵻ؿ
 */
ACL_API ACL_VSTRING *acl_aio_readn_peek(ACL_ASTREAM *astream, int *count);

/**
 * 첽Ϊ״̬ɶʱûĻص
 * @param astream {ACL_ASTREM*} 첽
 * @param can_read_fn {ACL_AIO_NOTIFY_FN} ûص
 * @param context {void*} can_read_fn Ĳ֮һ
 */
ACL_API void acl_aio_enable_read(ACL_ASTREAM *astream,
	ACL_AIO_NOTIFY_FN can_read_fn, void *context);

/**
 * 첽жݿɶ
 * @param astream {ACL_ASTREM*} 첽
 * @return {int} ACL_VSTREAM_EOF ʾӦùرո; 0 ʾݿɶ;
 *  > 0 ʾݿɶ
 */
ACL_API int acl_aio_can_read(ACL_ASTREAM *astream);

/**
 * ֹͣһIO
 * @param astream {ACL_ASTREAM*} 첽
 */
ACL_API void acl_aio_disable_read(ACL_ASTREAM *astream);

/**
 * жǷ첽¼Ķ
 * @param astream {ACL_ASTREAM*} 첽
 * @return {int} 0: != 0: 
 */
ACL_API int acl_aio_isrset(ACL_ASTREAM *astream);

/**
 * öһʱÿݵ󳤶ƣĿҪΪ˷ֹԷ͵
 * һݹɱؽջڴ
 * @param astream {ACL_ASTREAM*} 첽
 * @param len {int} ֵ > 0 ʱưжݳ
 */
ACL_API void acl_aio_stream_set_line_length(ACL_ASTREAM *astream, int len);

/**
 * õжʱ󳤶
 * @param astream {ACL_ASTREAM*} 첽
 * @return {int}
 */
ACL_API int acl_aio_stream_get_line_length(ACL_ASTREAM *astream);

/**
 * 첽ǣȱʡԶ̳ ACL_AIO е keep_read
 * (Ĭ)
 * @param astream {ACL_ASTREAM*} 첽
 * @param onoff {int} 0 ʾرܣ0ʾ
 */
ACL_API void acl_aio_stream_set_keep_read(ACL_ASTREAM *astream, int onoff);

/**
 * 첽Ƿ
 * @return {int} 0 ʾرܣ0ʾ
 */
ACL_API int acl_aio_stream_get_keep_read(ACL_ASTREAM *astream);

/*---------------------------- 첽дӿ --------------------------------*/

/**
 * 첽д, дʱдɹʱ¼֪ͨ
 * @param astream {ACL_ASTREAM*} дص.
 * @param data {const char*} дݵڴ濪ʼָλ
 * @param dlen {int} data ݳ
 */
ACL_API void acl_aio_writen(ACL_ASTREAM *astream, const char *data, int dlen);

/**
 * 첽д, дʱдɹʱ¼֪̣ͨϵͳ
 * writev
 * @param astream {ACL_ASTREAM*} дص.
 * @param vector {const struct iovec*} ݼ
 * @param count {int} vector ĳ
 */
ACL_API void acl_aio_writev(ACL_ASTREAM *astream,
		const struct iovec *vector, int count);

/**
 * Ըʽʽ첽д, дʱдɹʱ¼֪ͨ
 * @param astream {ACL_ASTREAM*} дص
 * @param fmt {const char*} ʽַ
 * @param ap {va_list} ʽַĲб
 */
ACL_API void acl_aio_vfprintf(ACL_ASTREAM *astream, const char *fmt, va_list ap);

/**
 * Ըʽʽ첽д, дʱдɹʱ¼֪ͨ
 * @param astream {ACL_ASTREAM*} дص
 * @param fmt {const char*} ʽַ
 * @param ... β
 */
ACL_API void ACL_PRINTF(2, 3) acl_aio_fprintf(ACL_ASTREAM *astream, const char *fmt, ...);

/**
 * õǰͶݳ
 * @param astream {ACL_ASTREAM*}
 * @return {size_tt}
 */
ACL_API size_t acl_aio_send_pending(ACL_ASTREAM *astream);

/**
 * 첽Ϊд״̬дʱûĻص
 * @param astream {ACL_ASTREM*} 첽
 * @param can_write_fn {ACL_AIO_NOTIFY_FN} ûص
 * @param context {void*} can_write_fn Ĳ֮һ
 */
ACL_API void acl_aio_enable_write(ACL_ASTREAM *astream,
	ACL_AIO_NOTIFY_FN can_write_fn, void *context);

/**
 * ֹͣһIOд
 * @param astream {ACL_ASTREAM*} 첽
 */
ACL_API void acl_aio_disable_write(ACL_ASTREAM *astream);

/**
 * жǷ첽¼д
 * @param astream {ACL_ASTREAM*} 첽
 * @return {int} 0: != 0: 
 */
ACL_API int acl_aio_iswset(ACL_ASTREAM *astream);

/*---------------------------- 첽ӿ ------------------------------*/

/**
 * 첽һͻ, ÿͻشû
 * @param astream {ACL_ASTREAM*} ڼ״̬
 */
ACL_API void acl_aio_accept(ACL_ASTREAM *astream);

/**
 * 첽, ϳʱӵʱ¼֪ͨ, 
 * ʱûԼעắ accept() .
 * @param astream {ACL_ASTREAM*} ڼ״̬
 */
ACL_API void acl_aio_listen(ACL_ASTREAM *astream);

/*---------------------------- 첽Ӳӿ ------------------------------*/

/**
 * 첽һԶ̷, ʱӳɹʱ¼֪ͨ.
 * @param aio {ACL_AIO*} 첽
 * @param addr {const char*} Զ̷ַ, ʽ: ip:port, : 192.168.0.1:80
 * @param local {const char*} IPַǿʱһĸ
 *  Ϊ @ ʾ IP ַΪ # ʾ
 * @param timeout {int} ӳʱʱֵλΪ
 * @return {ACL_ASTREAM*} 첽ӹǷɹ
 */
ACL_API ACL_ASTREAM *acl_aio_connect2(ACL_AIO *aio, const char *addr,
		const char *local, int timeout);
ACL_API ACL_ASTREAM *acl_aio_connect(ACL_AIO *aio, const char *addr, int timeout);

/**
 * 첽һԶ̷ĵַ acl_aio_connect 
 * ʹñҪǱͨ acl_aio_set_dns õĵַ
 * @param aio {ACL_AIO*} 첽
 * @param addr {const char*} ַʽdomain:port磺www.sina.com:80
 * @param local {const char*} IPַǿʱһĸ
 *  Ϊ @ ʾ IP ַΪ # ʾ
 * @param timeout {int} ӳʱʱֵλΪ
 * @param callback {ACL_AIO_CONNECT_ADDR_FN}
 * @param context {void*} ݸ callback صĲ
 * @return {int}  0 ʾʼ첽첽ӹ̣ < 0 ʾ
 *  ڴ ACL_AIO ûͨ acl_aio_set_dns 
 */
ACL_API int acl_aio_connect_addr2(ACL_AIO *aio, const char *addr,
		const char *local, int timeout,
		ACL_AIO_CONNECT_ADDR_FN callback, void *context);
ACL_API int acl_aio_connect_addr(ACL_AIO *aio, const char *addr, int timeout,
		ACL_AIO_CONNECT_ADDR_FN callback, void *context);

/*---------------------------- ͨ첽ӿ --------------------------*/

/**
 * ֹͣһIOд
 * @param astream {ACL_ASTREAM*} 첽
 */
ACL_API void acl_aio_disable_readwrite(ACL_ASTREAM *astream);

/**
 * жǷ첽¼Ķд
 * @param astream {ACL_ASTREAM*} 첽
 * @return {int} 0: != 0: 
 */
ACL_API int acl_aio_isset(ACL_ASTREAM *astream);

/**
 * õǰ첽üֵ
 * @param astream {ACL_ASTREAM*} 첽
 * @return {int} >=0첽üֵ
 */
ACL_API int acl_aio_refer_value(ACL_ASTREAM * astream);

/**
 * 첽üֵ1
 * @param astream {ACL_ASTREAM*} 첽
 */
ACL_API void acl_aio_refer(ACL_ASTREAM *astream);

/**
 * 첽üֵ1
 * @param astream {ACL_ASTREAM*} 첽
 */
ACL_API void acl_aio_unrefer(ACL_ASTREAM *astream);

/**
 * һʱ, ú acl_event_request_timer ļ򵥷װ
 * @param aio {ACL_AIO*} 첽ͨ
 * @param timer_fn {ACL_EVENT_NOTIFY_TIME} ʱص.
 * @param context {void*} timer_fn Ĳ֮һ.
 * @param idle_limit {acl_int64} ʱʱ䣬λΪ΢.
 * @param keep {int} Ƿظʱ
 * @return {acl_int64} ʣʱ, λΪ΢.
 */
ACL_API acl_int64 acl_aio_request_timer(ACL_AIO *aio,
		ACL_EVENT_NOTIFY_TIME timer_fn, void *context,
		acl_int64 idle_limit, int keep);

/**
 * ȡĳʱ, ú acl_event_cancel_timer ļ򵥷װ.
 * @param aio {ACL_AIO*} 첽ͨ
 * @param timer_fn {ACL_EVENT_NOTIFY_TIME} ʱص.
 * @param context {void*} timer_fn Ĳ֮һ.
 * @return {acl_int64} ʣʱ, λΪ΢.
 */
ACL_API acl_int64 acl_aio_cancel_timer(ACL_AIO *aio,
		ACL_EVENT_NOTIFY_TIME timer_fn, void *context);

/**
 * ǷҪѭͨ acl_aio_request_timer õĶʱ
 * @param aio {ACL_AIO*} 첽ͨ
 * @param timer_fn {ACL_EVENT_NOTIFY_TIME} ʱص.
 * @param context {void*} timer_fn Ĳ֮һ.
 * @param onoff {int} Ƿظʱ
 */
ACL_API void acl_aio_keep_timer(ACL_AIO *aio, ACL_EVENT_NOTIFY_TIME timer_fn,
		void *context, int onoff);

/**
 * жõĶʱظʹ״̬
 * @param aio {ACL_AIO*} 첽ͨ
 * @param timer_fn {ACL_EVENT_NOTIFY_TIME} ʱص.
 * @param context {void*} timer_fn Ĳ֮һ.
 * @return {int} !0 ʾõĶʱظʹ״̬
 */
ACL_API int acl_aio_timer_ifkeep(ACL_AIO *aio, ACL_EVENT_NOTIFY_TIME timer_fn,
		void *context);

#ifdef	__cplusplus
}
#endif

#endif
