#ifndef	ACL_IOCTL_INCLUDE_H
#define	ACL_IOCTL_INCLUDE_H

#ifdef	__cplusplus
extern "C" {
#endif

#include "../stdlib/acl_define.h"
#include "../event/acl_events.h"
#include "../stdlib/acl_vstream.h"

typedef struct ACL_IOCTL ACL_IOCTL;

/**
 * ʱصͶ, ûҪݴ˺ԭʵԼ
 * @param event_type {int} ¼״̬, Ϊ״̬֮һ:
 *        ACL_EVENT_READ: ݿɶ; 
 *	  ACL_EVENT_WRITE: пռд;
 *	  ACL_EVENT_RW_TIMEOUT: дʱ;
 *	  ACL_EVENT_XCPT: ڲ쳣.
 * @param ioc {ACL_IOCTL*} io ƾ
 * @param stream {ACL_VSTREAM*} 
 * @param context {void*} ûԶ
 */
typedef void (*ACL_IOCTL_NOTIFY_FN)(int event_type, ACL_IOCTL *ioc,
	ACL_VSTREAM *stream, void *context);

typedef void (*ACL_IOCTL_WORKER_FN)(ACL_IOCTL *ioc, void *arg);
typedef void (*ACL_IOCTL_THREAD_INIT_FN)(void *);
typedef void (*ACL_IOCTL_THREAD_EXIT_FN)(void *);

/*----------------------------------------------------------------------------*/
/* in acl_ioctl.c */
/**
 * һ
 * @param max_threads {int} ڵ߳
 * @param idle_timeout {int} ÿ߳̿ʱ, ĳֵĿʱ䳬
 *  ֵʱԶ˳, λΪ
 * @return {ACL_IOCTL*} ؾ
 */
ACL_API ACL_IOCTL *acl_ioctl_create(int max_threads, int idle_timeout);

/**
 * һ
 * @param event_mode {int} ¼ʽ: ACL_EVENT_SELECT/ACL_EVENT_KERNEL
 * @param max_threads {int} ڵ߳
 * @param idle_timeout {int} ÿ߳̿ʱ, ĳֵĿʱ䳬
 *  ֵʱԶ˳, λΪ
 * @param delay_sec {int} ¼ѭеֵ
 * @param delay_usec {int} ¼ѭе΢ֵ
 * @return {ACL_IOCTL*} ؾ
 */
ACL_API ACL_IOCTL *acl_ioctl_create_ex(int event_mode, int max_threads,
	int idle_timeout, int delay_sec, int delay_usec);

/**
 * Ϊ˷ֹڶ߳ģʽ select ¼ѭʱȴӴжϵȴ
 * ӿ¼ѭ
 * @param ioc {ACL_IOCTL*} ؾ
 */
ACL_API void acl_ioctl_add_dog(ACL_IOCTL *ioc);

/**
 * ÷صĿƲ
 * @param ioc {ACL_IOCTL*} ؾ
 * @param name {int} беĵһ, ACL_IOCTL_CTL_
 * @param ... β
 */
ACL_API void acl_ioctl_ctl(ACL_IOCTL *ioc, int name, ...);
#define	ACL_IOCTL_CTL_END                       0  /**< ƽ־ */
#define	ACL_IOCTL_CTL_THREAD_MAX                1  /**< ߳ */
#define	ACL_IOCTL_CTL_THREAD_IDLE               2  /**< ߳̿˳ʱ */
#define	ACL_IOCTL_CTL_DELAY_SEC                 3  /**<  select ʱ뼶Ϣֵ */
#define	ACL_IOCTL_CTL_DELAY_USEC                4  /**<  select ʱ΢뼶Ϣֵ */
#define	ACL_IOCTL_CTL_INIT_FN                   5  /**< ̱߳ʱ̳߳ʼ */
#define	ACL_IOCTL_CTL_EXIT_FN                   6  /**< ߳˳ʱ߳˳ص */
#define	ACL_IOCTL_CTL_INIT_CTX                  7  /**< ̳߳ʼʱĻص */
#define	ACL_IOCTL_CTL_EXIT_CTX                  8  /**< ߳˳ʱĻص */
#define ACL_IOCTL_CTL_THREAD_STACKSIZE          9  /**< ̵߳ĹģߴС(ֽ) */

/**
 * Դ
 * @param ioc {ACL_IOCTL*} ؾ
 */
ACL_API void acl_ioctl_free(ACL_IOCTL *ioc);

/**
 * 
 * @param ioc {ACL_IOCTL*} ؾ
 * @return {int} Ƿ. 0: ok; < 0: err.
 */
ACL_API int acl_ioctl_start(ACL_IOCTL *ioc);

/**
 * Ϣѭ(ڵ߳ģʽ)
 * @param ioc {ACL_IOCTL*} ؾ
 */
ACL_API void acl_ioctl_loop(ACL_IOCTL *ioc);

/**
 * ¼
 * @param ioc {ACL_IOCTL*} ؾ
 * @return {ACL_EVENT*}
 */
ACL_API ACL_EVENT *acl_ioctl_event(ACL_IOCTL *ioc);

/**
 * ¼Ķдȥ
 * @param ioc {ACL_IOCTL*} ؾ
 * @param stream {ACL_VSTREAM*} ͻָ
 */
ACL_API void acl_ioctl_disable_readwrite(ACL_IOCTL *ioc, ACL_VSTREAM *stream);

/**
 * ¼Ķȥ
 * @param ioc {ACL_IOCTL*} ؾ
 * @param stream {ACL_VSTREAM*} ͻָ
 */
ACL_API void acl_ioctl_disable_read(ACL_IOCTL *ioc, ACL_VSTREAM *stream);

/**
 * ¼дȥ
 * @param ioc {ACL_IOCTL*} ؾ
 * @param stream {ACL_VSTREAM*} ͻָ
 */
ACL_API void acl_ioctl_disable_write(ACL_IOCTL *ioc, ACL_VSTREAM *stream);

/**
 * жĳǷܼ״̬, ֻҪдκһ״̬
 * @param ioc {ACL_IOCTL*} ؾ
 * @param stream {ACL_VSTREAM*} ͻָ
 * @return {int} 1ʾ; 0: ʾ
 */
ACL_API int acl_ioctl_isset(ACL_IOCTL *ioc, ACL_VSTREAM *stream);

/**
 * жĳǷڶ״̬
 * @param ioc {ACL_IOCTL*} ؾ
 * @param stream {ACL_VSTREAM*} ͻָ
 * @return {int} 1ʾ; 0: ʾ
 */
ACL_API int acl_ioctl_isrset(ACL_IOCTL *ioc, ACL_VSTREAM *stream);

/**
 * жĳǷдܼ״̬
 * @param ioc {ACL_IOCTL*} ؾ
 * @param stream {ACL_VSTREAM*} ͻָ
 * @return {int} 1ʾ; 0: ʾ
 */
ACL_API int acl_ioctl_iswset(ACL_IOCTL *ioc, ACL_VSTREAM *stream);

/**
 * ״, IOʱԶر
 * @param ioc {ACL_IOCTL*} ؾ
 * @param stream {ACL_VSTREAM*} ͻָ
 * @return {int} Ƿر
 *         0: ʾлδ, 첽رչ;
 *         1: ʾδ, Ѿͬر
 */
ACL_API int acl_ioctl_iocp_close(ACL_IOCTL *ioc, ACL_VSTREAM *stream);

/**
 * һ
 * @param ioc {ACL_IOCTL*} ؾ
 * @param stream {ACL_VSTREAM*} ͻָ
 * @param timeout {int} ӿгʱʱ
 * @param callback {ACL_IOCTL_NOTIFY_FN} ɶʱʱĻص
 * @param context {void*} ص callback Ĳ֮һ, ҪڴûԼĲ,
 *  ûҪ callback ڽòתԼĿʶ
 */
ACL_API void acl_ioctl_enable_read(ACL_IOCTL *ioc, ACL_VSTREAM *stream,
	int timeout, ACL_IOCTL_NOTIFY_FN callback, void *context);

/**
 * һдع
 * @param ioc {ACL_IOCTL*} ؾ
 * @param stream {ACL_VSTREAM*} ͻָ
 * @param timeout {int} ӿгʱʱ
 * @param callback {ACL_IOCTL_NOTIFY_FN} дʱʱĻص
 * @param context {void*} ص callback Ĳ֮һ, ҪڴûԼĲ,
 *  ûҪ callback ڽòתԼĿʶ
 */
ACL_API void acl_ioctl_enable_write(ACL_IOCTL *ioc, ACL_VSTREAM *stream,
	int timeout, ACL_IOCTL_NOTIFY_FN callback, void *context);

/**
 * 첽ӷ, ӳɹӳʱʱûĻص
 * @param ioc {ACL_IOCTL*} ؾ
 * @param stream {ACL_VSTREAM*} Զ̷״̬ıؿͻ
 * @param timeout {int} ӳʱʱ
 * @param callback {ACL_IOCTL_NOTIFY_FN} дʱʱĻص
 * @param context {void*} ص callback Ĳ֮һ, ҪڴûԼĲ,
 *  ûҪ callback ڽòתԼĿʶ
 */
ACL_API void acl_ioctl_enable_connect(ACL_IOCTL *ioc, ACL_VSTREAM *stream,
	int timeout, ACL_IOCTL_NOTIFY_FN callback, void *context);

/**
 * Ϊĳַ
 * @param ioc {ACL_IOCTL*} ؾ
 * @param stream {ACL_VSTREAM*} Զ̷״̬ıؿͻ
 * @param timeout {int} ׽ּʱʱ, ˳ʱʱ䵽ûӵʱ,
 *  ߿ڻصﴦ¼, ֵΪ 0 һֱ
 *  ӵʱûĻصű
 * @param callback {ACL_IOCTL_NOTIFY_FN} ӵ׽ֳ
 *  ʱʱĻص
 * @param context {void*} callback Ĳ֮һ, μ˵
 */
ACL_API void acl_ioctl_enable_listen(ACL_IOCTL *ioc, ACL_VSTREAM *stream,
	int timeout, ACL_IOCTL_NOTIFY_FN callback, void *context);

/*----------------------------------------------------------------------------*/
/**
 * Զ̷
 * @param addr {const char*} ˷ַ, ʽ: ip:port, : 192.168.0.1:80
 * @param timeout {int} ӳʱʱ, 京:
 *         1) 0:   Զ̷
 *         2) -1:  Զ̷ֱӳɹʧΪֹ
 *         3) > 0: ʱԶ̷
 * @return {ACL_VSTREAM*} ͻ.
 *  != NULL ʾӳɹ; == NULL ʧܻ
 * ע:
 *      1) ʱ, Ҫص ACL_VSTREAM Ӽͨص
 *     Ըжд, Ҫ acl_ioctl_enable_connect() ȷ
 *     ӳɹ.
 */
ACL_API ACL_VSTREAM *acl_ioctl_connect(const char *addr, int timeout);

/**
 * һ׽
 * @param addr {const char*} رĵַ, ʽ: ip:port, : 127.0.0.1:80
 * @param qlen {int} г
 * @return {ACL_VSTREAM*} ׽. != NULL ok; == NULL err.
 * ע: Ҫ첽, Ե acl_ioctl_enable_listen() 첽
 *     һͻ
 */
ACL_API ACL_VSTREAM *acl_ioctl_listen(const char *addr, int qlen);

/**
 * һ׽
 * @param addr {const char*} رĵַ, ʽ: ip:port, : 127.0.0.1:80
 * @param qlen {int} г
 * @param block_mode {int} Ƿ÷ģʽ, ACL_BLOCKING: ģʽ,
 *  ACL_NON_BLOCKING: ģʽ
 * @param io_bufsize {int} ÿͻĻС(ֽ)
 * @param io_timeout {int} ͻĶдʱʱ()
 * @return {ACL_VSTREAM*} ׽. != NULL ok; == NULL err.
 * ע: Ҫ첽, Ե acl_ioctl_enable_listen() 첽
 *     һͻ
 */
ACL_API ACL_VSTREAM *acl_ioctl_listen_ex(const char *addr, int qlen,
	int block_mode, int io_bufsize, int io_timeout);

/**
 * Ӽ׿ڻһͻ
 * @param sstream {ACL_VSTREAM*} 
 * @param ipbuf {char*} ͻĵַ
 * @param size {int} ipbuf ռС
 * @return {ACL_VSTREAM*} ͻ. != NULL ɹһͻӵ;
 *  == NULL ܱϵͳжһ, ӦԴ
 */
ACL_API ACL_VSTREAM *acl_ioctl_accept(ACL_VSTREAM *sstream,
	char *ipbuf, int size);

/**
 * һʱ, ú acl_event_request_timer ļ򵥷װ.
 * @param ioc {ACL_IOCTL*} ؾ
 * @param timer_fn {ACL_EVENT_NOTIFY_TIME} ʱص.
 * @param context {void*} timer_fn Ĳ֮һ.
 * @param idle_limit {acl_int64} ʱʱ(΢뼶)
 * @return {acl_int64} ʣʱ, λΪ΢.
 */
ACL_API acl_int64 acl_ioctl_request_timer(ACL_IOCTL *ioc,
	ACL_EVENT_NOTIFY_TIME timer_fn, void *context, acl_int64 idle_limit);

/**
 * ȡĳʱ, ú acl_event_cancel_timer ļ򵥷װ.
 * @param ioc {ACL_IOCTL*} ؾ
 * @param timer_fn {ACL_EVENT_NOTIFY_TIME} ʱص.
 * @param context {void*} timer_fn Ĳ֮һ.
 * @return {acl_int64} ʣʱ, λΪ΢.
 */
ACL_API acl_int64 acl_ioctl_cancel_timer(ACL_IOCTL *ioc,                                                            
	ACL_EVENT_NOTIFY_TIME timer_fn, void *context);

/**
 * ǰ̳߳һµ
 * @param ioc {ACL_IOCTL*} ؾ
 * @param callback {ACL_IOCTL_WORKER_FN} Ļص
 * @param arg {void*} callback Ĳ֮һ
 * @return {int} 0: ok; < 0: error
 */
ACL_API int acl_ioctl_add(ACL_IOCTL *ioc,
	ACL_IOCTL_WORKER_FN callback, void *arg);

/**
 * õǰ̳߳й̵߳.
 * @param ioc {ACL_IOCTL*} ؾ
 * @return {int} صǰ̵߳ == -1: error; >= 0: ok.
 */
ACL_API int acl_ioctl_nworker(ACL_IOCTL *ioc);

#ifdef	__cplusplus
}
#endif

#endif
