#ifndef ACL_PTHREAD_POOL_INCLUDE_H
#define ACL_PTHREAD_POOL_INCLUDE_H

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

#ifdef	ACL_UNIX
#include <pthread.h>
#endif

#ifdef	__cplusplus
extern "C" {
#endif

typedef struct acl_pthread_job_t acl_pthread_job_t;

/**
 * һ̳߳صĹ
 * @param run_fn {void (*)(void*)} ߳бõĻص 
 * @param run_arg {void*} run_fn Ļص֮һ
 * @param fixed {int}
 * @return {acl_pthread_job_t*} شĹ
 */
ACL_API acl_pthread_job_t *acl_pthread_pool_alloc_job(void (*run_fn)(void*),
		void *run_arg, int fixed);

/**
 * ͷ acl_pthread_pool_alloc_job Ĺ
 * @param job {acl_pthread_job_t*}
 */
ACL_API void acl_pthread_pool_free_job(acl_pthread_job_t *job);

/**
 * ̳߳ضṹͶ
 */
typedef struct acl_pthread_pool_t acl_pthread_pool_t;

/**
 * ̳߳ضԵĽṹͶ
 */
typedef struct acl_pthread_pool_attr_t {
	int   threads_limit;	/**< ̳߳߳ */
#define ACL_PTHREAD_POOL_DEF_THREADS   100  /**< ȱʡֵΪ 100 ߳ */
	int   idle_timeout;                 /**< ߳̿гʱʱ() */
#define ACL_PTHREAD_POOL_DEF_IDLE      0    /**< ȱʡռ䳬ʱʱΪ 0  */
	size_t stack_size;                  /**< ̵߳ĶջС(ֽ) */
} acl_pthread_pool_attr_t;

/**
 * 򵥵ش̶߳ķ
 * @param threads_limit {int}  ̳߳󲢷߳
 * @param idle_timeout {int} ߳̿гʱ˳ʱ()
 * @return {acl_pthread_pool_t*}, Ϊʾɹʧ
 */
ACL_API acl_pthread_pool_t *acl_thread_pool_create(
		int threads_limit, int idle_timeout);

/**
 * һ̳߳ض
 * @param attr {acl_pthread_pool_attr_t*} ̳߳شʱԣòΪգ
 *  Ĭϲ: ACL_PTHREAD_POOL_DEF_XXX
 * @return {acl_pthread_pool_t*}, Ϊʾɹʧ
 */
ACL_API acl_pthread_pool_t *acl_pthread_pool_create(
		const acl_pthread_pool_attr_t *attr);

/**
 * жѻڿ߳2ʱ. ͨ˺
 * ߳ʱ, ô˺, ̲߳״̬.
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param timewait_sec {int} ߡʱֵ, 齫ֵΪ 1--5 
 * @return {int} ɹ 0, ʧܷ -1
 */
ACL_API int acl_pthread_pool_set_timewait(
		acl_pthread_pool_t *thr_pool, int timewait_sec);

/**
 * עắ̴ִ߳д˳ʼ
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param init_fn {int (*)(void*)} ̳߳ʼ, ú < 0,
 *  ߳Զ˳
 * @param init_arg {void*} init_fn ҪĲ
 * @return {int} 0: OK; != 0: Error.
 */
ACL_API int acl_pthread_pool_atinit(acl_pthread_pool_t *thr_pool,
		int (*init_fn)(void *), void *init_arg);

/**
 * עắ߳˳ִд˳
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param free_fn {void (*)(void*)} ߳˳ǰִеĺ
 * @param free_arg {void*} free_fn ҪĲ
 * @return {int} 0: OK; != 0: Error.
 */
ACL_API int acl_pthread_pool_atfree(acl_pthread_pool_t *thr_pool,
		void (*free_fn)(void *), void *free_arg);

/**
 * һ̳߳ض, ɹٺö.
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @return {int} 0: ɹ; != 0: ʧ
 */
ACL_API int acl_pthread_pool_destroy(acl_pthread_pool_t *thr_pool);

/**
 * ͣһ̳߳ض, ֹͣ󻹿.
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @return {int} 0: ɹ; != 0: ʧ
 */
ACL_API int acl_pthread_pool_stop(acl_pthread_pool_t *thr_pool);

/**
 * ̳߳һ
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param run_fn {void (*)(*)} пù߳ʱõĻص
 * @param run_arg {void*} ص run_fn ҪĻص
 */
ACL_API void acl_pthread_pool_add_one(acl_pthread_pool_t *thr_pool,
		void (*run_fn)(void *), void *run_arg);
#define	acl_pthread_pool_add	acl_pthread_pool_add_one

/**
 * ̳߳һ
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param job {acl_pthread_job_t*}  acl_pthread_pool_alloc_job ߳
 */
ACL_API void acl_pthread_pool_add_job(acl_pthread_pool_t *thr_pool,
		acl_pthread_job_t *job);

/**
 * ʼʽ, ʵǿʼм
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 */
ACL_API void acl_pthread_pool_bat_add_begin(acl_pthread_pool_t *thr_pool);

/**
 * һ, ǰѾɹ,  acl_pthread_pool_bat_add_begin ɹ
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param run_fn {void (*)(void*)} пù߳ʱõĻص
 * @param run_arg ص run_fn ҪĻص
 */
ACL_API void acl_pthread_pool_bat_add_one(acl_pthread_pool_t *thr_pool,
		void (*run_fn)(void *), void *run_arg);
/**
 * һ, ǰѾɹ,  acl_pthread_pool_bat_add_begin ɹ
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param job {acl_pthread_job_t*}  acl_pthread_pool_alloc_job ߳
 */
ACL_API void acl_pthread_pool_bat_add_job(acl_pthread_pool_t *thr_pool,
		acl_pthread_job_t *job);

/**
 * ӽ, ʵǽ
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 */
ACL_API void acl_pthread_pool_bat_add_end(acl_pthread_pool_t *thr_pool);

/**
 * ̳߳ POLLER ȺҪʹô˹ܣҪú
 * acl_pthread_pool_create ͨ˺õȺȻ
 *  acl_pthread_pool_start_poller ̨Ⱥų́
 * Ⱥ᲻ϵص poller_fn (ûĻص)û
 * ڻص acl_pthread_pool_add ӽ̳߳
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param poller_fn {int (*)(void*)} ѭеĻص
 * @param poller_arg {void*} poller_fn ҪĲ
 */
ACL_API void acl_pthread_pool_set_poller(acl_pthread_pool_t *thr_pool,
		int (*poller_fn)(void *), void *poller_arg);
/**
 * һ̳߳ POLLER ߳
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @return 0 ɹ; != 0 ʧ, ԶԷֵ strerror(ret) ȡôԭ
 */
ACL_API int acl_pthread_pool_start_poller(acl_pthread_pool_t *thr_pool);

/**
 * ʽķַ, ڲʵǵ acl_pthread_pool_add_one()
 * @return 0: OK; -1: err
 */
ACL_API int acl_pthread_pool_add_dispatch(void *dispatch_arg,
		void (*run_fn)(void *), void *run_arg);

/**
 * Եӵķʽķַ
 * @return 0: OK; -1: err
 * עworker_fn еĵڶΪACL_WORKER_ATTRṹָ룬̳߳صĳ
 *     ߳άýṹָеĳԱ init_data Ϊûĸֵͱ
 *     磺ݿӶȡ
 */
ACL_API int acl_pthread_pool_dispatch(void *dispatch_arg,
		void (*run_fn)(void *), void *run_arg);

/**
 * õǰ̳߳ص߳
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @return {int} ֵ߳
 */
ACL_API int acl_pthread_pool_limit(acl_pthread_pool_t *thr_pool);

/**
 * õǰ̳߳е߳
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @return {int} ̳߳еֵ߳ < 0 ʾ
 */
ACL_API int acl_pthread_pool_size(acl_pthread_pool_t *thr_pool);

/**
 * õǰ̳߳еĿ߳
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @return {int} ̳߳еĿֵ߳ < 0 ʾ
 */
ACL_API int acl_pthread_pool_idle(acl_pthread_pool_t *thr_pool);

/**
 * õǰ̳߳еķæ߳
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @return {int} ̳߳еķæֵ߳ < 0 ʾ
 */
ACL_API int acl_pthread_pool_busy(acl_pthread_pool_t *thr_pool);

/**
 * ߳ȳʱʱ()
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param n {acl_int64} ֵ > 0 ʱ߳ĵʱ䳬ֵ¼־()
 */
ACL_API void acl_pthread_pool_set_schedule_warn(
		acl_pthread_pool_t *thr_pool, acl_int64 n);

/**
 * ̵̳߳߳ȴĳʱ׼ʱ()
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param n {acl_int64} ֵ > 0 ʱ̵߳ȴĳʱȴ׼ʱ()
 */
ACL_API void acl_pthread_pool_set_schedule_wait(
		acl_pthread_pool_t *thr_pool, acl_int64 n);

/**
 * ̳߳еѻʱͨúжѻֵ
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param max {int} жѻֵ
 */
ACL_API void acl_pthread_pool_set_qlen_warn(
		acl_pthread_pool_t *thr_pool, int max);
/**
 * ȡõǰ̳߳ȫֶδ
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @return {int} ǰδֵ < 0 ʾ
 */
ACL_API int acl_pthread_pool_qlen(acl_pthread_pool_t *thr_pool);

/**
 * ̵̳߳߳ĶջС
 * @param thr_pool {acl_pthread_pool_t*} ̳߳ض󣬲Ϊ
 * @param size {size_t} ̴߳ʱĶջСλΪֽ
 */
ACL_API void acl_pthread_pool_set_stacksize(
		acl_pthread_pool_t *thr_pool, size_t size);

/**
 * ʼֵ̳߳
 * @param attr {acl_pthread_pool_attr_t*}
 */
ACL_API void acl_pthread_pool_attr_init(acl_pthread_pool_attr_t *attr);

/**
 * ̳߳еջС(ֽ)
 * @param attr {acl_pthread_pool_attr_t*}
 * @param size {size_t}
 */
ACL_API void acl_pthread_pool_attr_set_stacksize(
		acl_pthread_pool_attr_t *attr, size_t size);

/**
 * ̳߳еֵ߳
 * @param attr {acl_pthread_pool_attr_t*}
 * @param threads_limit {int} ̳߳е߳
 */
ACL_API void acl_pthread_pool_attr_set_threads_limit(
		acl_pthread_pool_attr_t *attr, int threads_limit);

/**
 * ̳߳߳̿гʱֵ
 * @param attr {acl_pthread_pool_attr_t*}
 * @param idle_timeout {int} ߳̿гʱʱ()
 */
ACL_API void acl_pthread_pool_attr_set_idle_timeout(
		acl_pthread_pool_attr_t *attr, int idle_timeout);

#ifdef	__cplusplus
}
#endif

#endif	/* !__acl_pthread_pool_t_H_INCLUDED__ */
