#ifndef ACL_EVENTS_H_INCLUDED
#define ACL_EVENTS_H_INCLUDED

#ifdef	__cplusplus
extern "C" {
#endif

#include "../stdlib/acl_define.h"
#include <time.h>
#include "../stdlib/acl_vstream.h"
#include "acl_timer.h"

/*+++++++++++++++++++++++++++ ȫֺ궨 +++++++++++++++++++++++++++++++++++*/
 /* Event codes. */
#define ACL_EVENT_READ          (1 << 0)      /**< read event */
#define	ACL_EVENT_ACCEPT        (1 << 1)      /**< accept one connection */
#define ACL_EVENT_WRITE         (1 << 2)      /**< write event */
#define	ACL_EVENT_CONNECT       (1 << 3)      /**< client has connected the server*/
#define ACL_EVENT_XCPT          (1 << 4)      /**< exception */
#define ACL_EVENT_TIME          (1 << 5)      /**< timer event */
#define	ACL_EVENT_RW_TIMEOUT    (1 << 6)      /**< read/write timeout event */
#define	ACL_EVENT_TIMEOUT       ACL_EVENT_RW_TIMEOUT

#define	ACL_EVENT_FD_IDLE	0
#define	ACL_EVENT_FD_BUSY	1

#define ACL_EVENT_ERROR		ACL_EVENT_XCPT

#define	ACL_EVENT_SELECT	0
#define	ACL_EVENT_POLL		1
#define	ACL_EVENT_KERNEL	2
#define ACL_EVENT_WMSG		3

 /*
  * Dummies.
  */
#define ACL_EVENT_NULL_TYPE	0
#define ACL_EVENT_NULL_CONTEXT	((char *) 0)


/* in acl_events.c */

typedef	struct	ACL_EVENT		ACL_EVENT;
typedef	struct	ACL_EVENT_FDTABLE	ACL_EVENT_FDTABLE;

/*
 * External interface.
 */
#if 0
typedef void (*ACL_EVENT_NOTIFY_FN) (int event_type, void *context);
typedef	ACL_EVENT_NOTIFY_FN	ACL_EVENT_NOTIFY_RDWR;
typedef	ACL_EVENT_NOTIFY_FN	ACL_EVENT_NOTIFY_TIME;
#else
typedef void (*ACL_EVENT_NOTIFY_RDWR)(int event_type, ACL_EVENT *event,
		ACL_VSTREAM *stream, void *context);
typedef void (*ACL_EVENT_NOTIFY_TIME)(int event_type, ACL_EVENT *event,
		void *context);
#endif

/*----------------------------------------------------------------------------*/

/**
 * һ¼ѭڣ˺ûĲͬԶ¼󴴽
 * @param event_mode {int} ¼ʽĿǰ֧: ACL_EVENT_SELECT, ACL_EVENT_KERNEL,
 *  ACL_EVENT_POLL, ACL_EVENT_WMSG
 * @param use_thr {int} Ƿ߳¼ʽ0ʾ߳¼ʽ
 * @param delay_sec {int} ¼ѭȴʱ event_mode Ϊ ACL_EVENT_WMSG
 *  ʱҸֵ 0 ʱֵϢֵԴ acl_event_new_wmsg
 *  Ϣ
 * @param delay_usec {int} ¼ѭȴʱ΢( select ʽ)
 * @return {ACL_EVENT*} ¼ָ룬Ϊձʾ
 */
ACL_API ACL_EVENT *acl_event_new(int event_mode, int use_thr,
	int delay_sec, int delay_usec);

/**
 * һµ¼, ¼ֶ֧߳
 * @param delay_sec {int} ڵ select() ʱϢ
 * @param delay_usec {int} ڵ select() ʱϢ΢
 * @return {ACL_EVENT*} ¼ָ룬Ϊձʾ
 */
ACL_API ACL_EVENT *acl_event_new_select(int delay_sec, int delay_usec);

/**
 * һµ¼, ¼֧߳ģʽ
 * @param delay_sec {int} ڵ select() ʱϢ
 * @param delay_usec {int} ڵ select() ʱϢ΢
 * @return {ACL_EVENT*} ¼ָ룬Ϊձʾ
 */
ACL_API ACL_EVENT *acl_event_new_select_thr(int delay_sec, int delay_usec);

/**
 * һ֧ poll ¼󣬲ֶ֧߳
 * @param delay_sec {int} ڵ poll() ʱϢ
 * @param delay_usec {int} ڵ poll() ʱϢ΢
 * @return {ACL_EVENT*} ¼ָ룬Ϊձʾ
 */
ACL_API ACL_EVENT *acl_event_new_poll(int delay_sec, int delay_usec);

/**
 * һ֧ poll ¼ֶ֧߳
 * @param delay_sec {int} ڵ poll() ʱϢ
 * @param delay_usec {int} ڵ poll() ʱϢ΢
 * @return {ACL_EVENT*} ¼ָ룬Ϊձʾ
 */
ACL_API ACL_EVENT *acl_event_new_poll_thr(int delay_sec, int delay_usec);

/**
 * һµ¼, ¼Чʸߵ epoll/devpoll/kqueue ʽҲֶ֧߳
 * @param delay_sec {int} ڵ¼ѭʱϢ
 * @param delay_usec {int} ڵ¼ѭʱϢ΢(Բ)
 * @return {ACL_EVENT*} ¼ָ룬Ϊձʾ
 */
ACL_API ACL_EVENT *acl_event_new_kernel(int delay_sec, int delay_usec);

/**
 * һµ¼, ¼Чʸߵ epoll/devpoll/kqueue ʽҲ̷߳ʽ
 * @param delay_sec {int} ڵ¼ѭʱϢ
 * @param delay_usec {int} ڵ¼ѭʱϢ΢(Բ)
 * @return {ACL_EVENT*} ¼ָ룬Ϊձʾ
 */
ACL_API ACL_EVENT *acl_event_new_kernel_thr(int delay_sec, int delay_usec);

/**
 * һ Windows Ϣһ¼
 * @param nMsg {unsigned int} ֵ 0 򽫸첽Ϣֵ󶨣
 *  򽫸첽ȱʡϢֵ
 * @return {ACL_EVENT*} ¼ָ룬Ϊձʾ
 */
ACL_API ACL_EVENT *acl_event_new_wmsg(unsigned int nMsg);

#if defined (_WIN32) || defined(_WIN64)
ACL_API HWND acl_event_wmsg_hwnd(ACL_EVENT *eventp);
#endif

/**
 * Ϊ˷ֹڶ߳ģʽ select ¼ѭʱȴӴжϵȴ
 * ӿ¼ѭ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 */
ACL_API void acl_event_add_dog(ACL_EVENT *eventp);

/**
 * ¼ǰúͺô
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param fire_begin {void (*)(ACL_EVENT*, void*)} ¼ͳһǰĻص
 * @param fire_end {void (*)(ACL_EVENT*, void*)} ¼ͳһĻص
 * @param ctx {void*} fire_begin / fire_end ĵڶ
 */
ACL_API void acl_event_set_fire_hook(ACL_EVENT *eventp,
		void (*fire_begin)(ACL_EVENT*, void*),
		void (*fire_end)(ACL_EVENT*, void*),
		void* ctx);

/**
 * ¼ѭжʱ״̬ʱڲȱʡֵΪ 100 ms
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param n {int} ʱʱ (뼶)
 */
ACL_API void acl_event_set_check_inter(ACL_EVENT *eventp, int n);

/**
 * ͷ¼ṹ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 */
ACL_API void acl_event_free(ACL_EVENT *eventp);

/**
 * ¼ʱ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @return {acl_int64} ǰ¼ʱ(΢뼶)
 */
ACL_API acl_int64 acl_event_time(ACL_EVENT *eventp);

/**
 * ¼еִ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 */
ACL_API void acl_event_drain(ACL_EVENT *eventp);

/**
 * ɶʱ(ָݴر)Ļص
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param stream {ACL_VSTREAM*} ָ, Ϊ, еЧ
 * @param read_timeout {int} ʱʱ()
 * @param callback {ACL_EVENT_NOTIFY_RDWR} ɶʱĻص
 * @param context {void*} ص callback ҪĲ
 */
ACL_API void acl_event_enable_read(ACL_EVENT *eventp, ACL_VSTREAM *stream,
	int read_timeout, ACL_EVENT_NOTIFY_RDWR callback, void *context);

/**
 * дʱ(ָпռдر)Ļص
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param stream {ACL_VSTREAM*} ָ, Ϊ, еЧ
 * @param write_timeout {int} дʱʱ()
 * @param callback {ACL_EVENT_NOTIFY_RDWR} дʱĻص
 * @param context {void*} ص callback ҪĲ
 */
ACL_API void acl_event_enable_write(ACL_EVENT *eventp, ACL_VSTREAM *stream,
	int write_timeout, ACL_EVENT_NOTIFY_RDWR callback, void *context);

/**
 * ü׽ӿ(ָӵ/ϵͳж/ʱ)Ļص
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param stream {ACL_VSTREAM*} ָ, Ϊ, еЧ
 * @param read_timeout {int} ʱʱ()Ϊ0
 * @param callback {ACL_EVENT_NOTIFY_RDWR} ɶʱĻص
 * @param context {void*} ص callback ҪĲ
 */
ACL_API void acl_event_enable_listen(ACL_EVENT *eventp, ACL_VSTREAM *stream,
	int read_timeout, ACL_EVENT_NOTIFY_RDWR callback, void *context);

/**
 * ¼Ķ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param stream {ACL_VSTREAM*} ָ, Ϊ, еЧ
 */
ACL_API void acl_event_disable_read(ACL_EVENT *eventp, ACL_VSTREAM *stream);

/**
 * ¼д
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param stream {ACL_VSTREAM*} ָ, Ϊ, еЧ
 */
ACL_API void acl_event_disable_write(ACL_EVENT *eventp, ACL_VSTREAM *stream);

/**
 * ¼Ķд
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param stream {ACL_VSTREAM*} ָ, Ϊ, еЧ
 */
ACL_API void acl_event_disable_readwrite(ACL_EVENT *eventp, ACL_VSTREAM *stream);

/**
 * еǷѾд쳣¼ļ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param stream {ACL_VSTREAM*} ָ, Ϊ, еЧ
 */
ACL_API int acl_event_isset(ACL_EVENT *eventp, ACL_VSTREAM *stream);

/**
 * еǷѾ¼ļ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param stream {ACL_VSTREAM*} ָ, Ϊ, еЧ
 */
ACL_API int acl_event_isrset(ACL_EVENT *eventp, ACL_VSTREAM *stream);

/**
 * еǷѾд¼ļ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param stream {ACL_VSTREAM*} ָ, Ϊ, еЧ
 */
ACL_API int acl_event_iswset(ACL_EVENT *eventp, ACL_VSTREAM *stream);

/**
 * еǷѾ쳣¼ļ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param stream {ACL_VSTREAM*} ָ, Ϊ, еЧ
 */
ACL_API int acl_event_isxset(ACL_EVENT *eventp, ACL_VSTREAM *stream);

/**
 * һʱ¼
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param callback {ACL_EVENT_NOTIFY_TIME} ʱ¼Ļص
 * @param context {void*} callback ҪĻص
 * @param delay {acl_int64} eventp->event_present + delay Ϊ¼ʼִеʱ
 *  λΪ΢
 * @param keep {int} Ƿظʱ
 * @return {acl_int64} ¼ִеʱأλΪ΢
 */
ACL_API acl_int64 acl_event_request_timer(ACL_EVENT *eventp,
	ACL_EVENT_NOTIFY_TIME callback, void *context, acl_int64 delay, int keep);

/**
 * ȡһʱ¼
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param callback {ACL_EVENT_NOTIFY_TIME} ʱ¼Ļص
 * @param context {void*} callback ҪĻص
 * @return acl_int64 {acl_int64} 뿪ʼִ¼ʱ, ΢Ϊλ
 */
ACL_API acl_int64 acl_event_cancel_timer(ACL_EVENT *eventp,
	ACL_EVENT_NOTIFY_TIME callback, void *context);

/**
 * ʱϺǷҪٴøöʱԷѭ
 * ʹøöʱ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param callback {ACL_EVENT_NOTIFY_TIME} ǿ
 * @param context {void*}  callback ı
 * @param onoff {int} Ƿظͨ acl_event_request_timer õĶʱ
 */
ACL_API void acl_event_keep_timer(ACL_EVENT *eventp, ACL_EVENT_NOTIFY_TIME callback,
	void *context, int onoff);

/**
 * жõĶʱظʹ״̬
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param callback {ACL_EVENT_NOTIFY_TIME} ǿ
 * @param context {void*}  callback ı
 * @return {int} !0 ʾõĶʱظʹ״̬
 */
ACL_API int acl_event_timer_ifkeep(ACL_EVENT *eventp, ACL_EVENT_NOTIFY_TIME callback,
	void *context);

/**
 * ¼ѭִеĵȺ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 */
ACL_API void acl_event_loop(ACL_EVENT *eventp);

/**
 * ¼ѭĿϢʱе뼶ֵ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param sec {int} 뼶Ϣʱֵ
 */
ACL_API void acl_event_set_delay_sec(ACL_EVENT *eventp, int sec);

/**
 * ¼ѭĿϢʱе΢뼶ֵ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @param usec {int} ΢뼶Ϣʱֵ
 */
ACL_API void acl_event_set_delay_usec(ACL_EVENT *eventp, int usec);

/**
 * ¼ѭĿϢʱе뼶ֵ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @return {int} 뼶Ϣʱֵ
 */
ACL_API int acl_event_get_delay_sec(ACL_EVENT *eventp);

/**
 * ¼ѭĿϢʱе΢뼶ֵ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @return {int} ΢뼶Ϣʱֵ
 */
ACL_API int acl_event_get_delay_usec(ACL_EVENT *eventp);

/**
 * Ƿ߳¼ʽ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @return {int} 0: ; !=0: 
 */
ACL_API int acl_event_use_thread(ACL_EVENT *eventp);

/**
 * õǰ¼¼ģ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @return {int} ACL_EVENT_SELECT/ACL_EVENT_KERNEL/ACL_EVENT_POLL
 */
ACL_API int acl_event_mode(ACL_EVENT *eventp);

/**
 * ñ¼ѭ󱻴 IO ¼Ĵ
 * @param eventp {ACL_EVENT*} ¼ָ, ΪΪ
 * @return {int} ֵΪѭ¼
 */
ACL_API int acl_event_last_nready(ACL_EVENT *eventp);

#ifdef	__cplusplus
}
#endif

#endif
