#ifndef ACL_ALLOCATOR_INCLUDE_H
#define ACL_ALLOCATOR_INCLUDE_H

#ifdef __cplusplus
extern "C" {
#endif

#ifndef	ACL_PREPARE_COMPILE
#include "acl_define.h"
#include <stdlib.h>
#endif

typedef enum {
	ACL_MEM_TYPE_NONE,
	ACL_MEM_TYPE_8_BUF,
	ACL_MEM_TYPE_16_BUF,
	ACL_MEM_TYPE_32_BUF,
	ACL_MEM_TYPE_64_BUF,
	ACL_MEM_TYPE_128_BUF,
	ACL_MEM_TYPE_256_BUF,
	ACL_MEM_TYPE_512_BUF,
	ACL_MEM_TYPE_1K_BUF,
	ACL_MEM_TYPE_2K_BUF,
	ACL_MEM_TYPE_4K_BUF,
	ACL_MEM_TYPE_8K_BUF,
	ACL_MEM_TYPE_16K_BUF,
	ACL_MEM_TYPE_32K_BUF,
	ACL_MEM_TYPE_64K_BUF,
	ACL_MEM_TYPE_128K_BUF,
	ACL_MEM_TYPE_256K_BUF,
	ACL_MEM_TYPE_512K_BUF,
	ACL_MEM_TYPE_1M_BUF,
	ACL_MEM_TYPE_VSTRING,
	ACL_MEM_TYPE_MAX
} acl_mem_type;

typedef struct ACL_MEM_POOL ACL_MEM_POOL;
typedef struct ACL_ALLOCATOR ACL_ALLOCATOR;

/* in acl_mpool.c */
/**
 * һڴض
 * @param mem_limit {size_t} ڴصڴ棬λΪֽ
 * @return {ACL_ALLOCATOR *} ڴضָ
 */
ACL_API ACL_ALLOCATOR *acl_allocator_create(size_t mem_limit);

/**
 * ڴصһЩ
 * @param name {int} бĵһ
 * ÷ʽ£
 * acl_allocator_ctl(ACL_ALLOCATOR_CTL_MIN_SIZE, 128,
 *		ACL_ALLOCATOR_CTL_MAX_SIZE, 1024,
 *		ACL_ALLOCATOR_CTL_END);
 */
ACL_API void acl_allocator_ctl(int name, ...);

#define ACL_ALLOCATOR_CTL_END		0    /**<  */
#define ACL_ALLOCATOR_CTL_MIN_SIZE	1    /**< Сֽ */
#define ACL_ALLOCATOR_CTL_MAX_SIZE	2    /**< ֽ */

/**
 * ڴصС
 * @param allocator {ACL_ALLOCATOR*}
 * @param mem_limit {size_t} ڴصֵλΪֽ
 */
ACL_API void acl_allocator_config(ACL_ALLOCATOR *allocator, size_t mem_limit);

/**
 * ͷڴضڴ
 * @param allocator {ACL_ALLOCATOR*}
 */
ACL_API void acl_allocator_free(ACL_ALLOCATOR *allocator);

/**
 * һµڴ
 * @param allocator {ACL_ALLOCATOR*}
 * @param label {const char*} ڴ͵Ϣ
 * @param obj_size {size_t} ÿڴ͵ĴСλΪֽ
 * @param type {acl_mem_type} ڴ
 * @param after_alloc_fn {void (*)(void*, void*)} ڴɹõĺΪ
 * @param before_free_fn {void (*)(void*, void*)} ͷڴǰصĺΪ
 * @param pool_ctx {void*} ӦԼ˽ж after_alloc_fn  before_free_fn
 *        Ϊգصʱ˲ֱӴݸӦ
 * @return {ACL_MEM_POOL*} ڴӦĶ
 */
ACL_API ACL_MEM_POOL *acl_allocator_pool_add(ACL_ALLOCATOR *allocator,
					const char *label,
					size_t obj_size,
					acl_mem_type type,
					void (*after_alloc_fn)(void *obj, void *pool_ctx),
					void (*before_free_fn)(void *obj, void *pool_ctx),
					void *pool_ctx);

/**
 * ڴƳĳڴ
 * @param allocator {ACL_ALLOCATOR*}
 * @param pool {ACL_MEM_POOL*}  acl_allocatore_pool_add صĶ
 */
ACL_API void acl_allocator_pool_remove(ACL_ALLOCATOR *allocator, ACL_MEM_POOL *pool);

/**
 * ̽ĳַǷڴصڴ
 * @param allocator {ACL_ALLOCATOR*}
 * @param type {acl_mem_type} ڴ
 * @return {int}, 0: != 0: 
 */
ACL_API int acl_allocator_pool_ifused(ACL_ALLOCATOR *allocator, acl_mem_type type);

/**
 * ĳַ͵ڴǰʹõĸ
 * @param allocator {ACL_ALLOCATOR*}
 * @param type {acl_mem_type} ڴ
 * @return {int} ǰڱʹõĳڴ͵ڴ
 */
ACL_API int acl_allocator_pool_inuse_count(ACL_ALLOCATOR *allocator, acl_mem_type type);

/**
 * ĳַڴеǰڱʹõڴС
 * @param allocator {ACL_ALLOCATOR*}
 * @param type {acl_mem_type} ڴ
 * @return {int} ĳַڴеǰڱʹõڴСλΪֽ
 */
ACL_API int acl_allocator_pool_inuse_size(ACL_ALLOCATOR *allocator, acl_mem_type type);

/**
 * ڴܹڱʹõڴĴС
 * @param allocator {ACL_ALLOCATOR*}
 * @return {int} ڴСλֽ
 */
ACL_API int acl_allocator_pool_total_allocated(ACL_ALLOCATOR *allocator);

/**
 * ĳڴ͵ڴ
 * @param filename {const char*}
 * @param line {int}
 * @param allocator {ACL_ALLOCATOR*}
 * @param type {acl_mem_type} ڴ
 * @return {void*} ·ڴĵַ
 */
ACL_API void *acl_allocator_mem_alloc(const char *filename, int line,
	ACL_ALLOCATOR *allocator, acl_mem_type type);

/**
 * ͷĳڴ͵ڴռ
 * @param filename {const char*}
 * @param line {int}
 * @param allocator {ACL_ALLOCATOR*}
 * @param type {acl_mem_type} ڴ
 * @param obj {void*} ͷŵڴ󣬲Ϊ
 */
ACL_API void acl_allocator_mem_free(const char *filename, int line,
	ACL_ALLOCATOR *allocator, acl_mem_type type, void *obj);

/**
 * ҪڴСԶڴƥ䣬ҵƥͣڴ
 * ڴԣֱӵ acl_mymalloc ڴ
 * @param filename {const char*} ñĵǰļ
 * @param line {int} ñĵǰļк
 * @param allocator {ACL_ALLOCATOR*}
 * @param size {size_t} ڴС
 * @return {void*} ·ڴĵַ
 */
ACL_API void *acl_allocator_membuf_alloc(const char *filename, int line,
	ACL_ALLOCATOR *allocator, size_t size);

/**
 * ڴС·ڴռ䣬ҵƥͣڴ
 * ڴԣֱ acl_mymalloc ڴ
 * @param filename {const char*} ñĵǰļ
 * @param line {int} ñĵǰļк
 * @param allocator {ACL_ALLOCATOR*}
 * @param oldbuf {void*} ԭڴ
 * @param size {size_t} ڴС
 * @return {void*} ·ڴĵַ
 */
ACL_API void *acl_allocator_membuf_realloc(const char *filename, int line,
	ACL_ALLOCATOR *allocator, void *oldbuf, size_t size);

/**
 * ͷڴ, ҵôСڴڴͣл壬ֱ
 * acl_myfree ͷ
 * @param filename {const char*} ñĵǰļ
 * @param line {int} ñĵǰļк
 * @param allocator {ACL_ALLOCATOR*}
 * @param buf {void*} ڴַ
 */
ACL_API void acl_allocator_membuf_free(const char *filename, int line,
	ACL_ALLOCATOR *allocator, void *buf);

#ifdef __cplusplus
}
#endif

#endif
