一、任务消息的抽象池,用于从中分配任务消息
/** Abstract pool of task messages to allocate task messages from */
struct apt_task_msg_pool_t {
void (*destroy)(apt_task_msg_pool_t *pool);
apt_task_msg_t* (*acquire_msg)(apt_task_msg_pool_t *pool);
void (*release_msg)(apt_task_msg_t *task_msg);
void *obj;
apr_pool_t *pool;
};
二、动态分配消息的结构体,并没有实际池的存在
struct apt_msg_pool_dynamic_t {
apr_size_t size;
};
消息池的创建函数,看一下函数声明:
APT_DECLARE(apt_task_msg_pool_t*) apt_task_msg_pool_create_dynamic(apr_size_t msg_size, apr_pool_t *pool)
msg_size是用户私有的、自定义的消息内容,pool是内存池。
这个函数主要作用是创建一个任务消息的抽象池,定义了消息获取、消息释放的函数指针并且赋值实现。另外还使用了一个销毁消息池的函数指针。
动态分配消息的结构体(apt_msg_pool_dynamic_t)的实例变量,赋值给了obj这个指针。因为这个结构体中唯一的一个成员变量size,它是自定义消息大小 + apt_task_msg_t结构大小,与外部上下文内容强相关的,这赋值给obj也很好理解。
消息池里面,有三个东西: 内存池、外部对象(apt_msg_pool_dynamic_t)、消息池操作方法(acquire_msg、release_msg、destroy)。
来看一下task_msg_t结构:
/** Task message is used for inter task communication */
struct apt_task_msg_t {
/** Message pool the task message is allocated from */
apt_task_msg_pool_t *msg_pool;
/** Task msg type */
int type;
/** Task msg sub type */
int sub_type;
/** Context specific data */
char data[1];
};
要留意的是结构体最后一个成员变量是 char data[1],这儿使用长度为1的数组的主要原因是方便管理内存,如果直接使用指针而不是使用数组,那么在malloc分配内存时,就必须先分配结构体一次,然后在分配结构体中的指针一次。此时分配的内存已经跟分配结构体的内存不连续了,所以要分别管理。而如果使用数组,那么只需要一次就可以全部分配出来,用完之后,一次释放。这样分配了一段连续的内存,减少内存的碎片化。至于这儿使用了char data[1] 而没有使用char data[0]的原因,是出于可移植性的考虑。有些编译器不支持[0]数组,将其改成[]或[1]作为解决方案。
data数组指向的内存地址,就是我们存放自定义消息数据的地方。以动态缓冲区的方式。