版权声明:转载请注明来源 https://blog.csdn.net/u013702678/article/details/81212964
这里我们接着第三篇的分析,分析另外一种线程池消息队列的实现和其他变量的初始化,这里是通过环装的数组实现队列,这里通过SW_USE_RINGQUEUE_TS区分定义了两种不同队列的实现,两种我们都简单分析一下。
首先分析基于cas控制队列操作的环状队列。
//基于数组实现的消息队列,swRingQueue是队列的抽象,buffer_size表示队列大小
int swRingQueue_init(swRingQueue *queue, int buffer_size)
{
queue->size = buffer_size;//设置队列大小
queue->flags = (char *)sw_malloc(queue->size);//从堆申请空间,这里吐槽一点flags这个变量名取的太有歧义了,这里表示的意思是操作数据时的序号。
if (queue->flags == NULL)//申请空间失败
{
return -1;
}
//队列的数据空间,数据为类型为void*,用数组表示,所以最终类型为void**
queue->data = (void **)sw_calloc(queue->size, sizeof(void*));
if (queue->data == NULL)//申请空间失败
{
sw_free(queue->flags);//flags表示队列的部分属性,数据空间失败时,这部分也没什么意思,也需要释放,不然有内存泄露的风险。
return -1;
}
queue->head = 0;//队列头部序号
queue->tail = 0;//队列尾部序号
memset(queue->flags, 0, queue->size);//空间初始化
memset(queue->data, 0, queue->size * sizeof(void*));//数据空间初始化
return 0;
}
//队列里面push元素
int swRingQueue_push(swRingQueue *queue, void * ele)
{
//队列个数有效性判断,即队列元素个数不能大于等于队列size。
if (!(queue->num < queue->size))
{
return -1;
}
int cur_tail_index = queue->tail;//队列尾部序号
char * cur_tail_flag_index = queue->flags + cur_tail_index;//队列序号空间加上尾部序号,则表示队列尾部的序号空间。
//cas操作判断,目前是否可以push元素,就cas的old为0,new值为1
while (!sw_atomic_cmp_set(cur_tail_flag_index, 0, 1))
{
cur_tail_index = queue->tail;//队列尾部序号
cur_tail_flag_index = queue->flags + cur_tail_index;//队列序号空间加上尾部序号,则表示队列尾部的序号空间。
}
//更新最新的队列尾部空间,这里是环状的,所以需要做mod操作
int update_tail_index = (cur_tail_index + 1) % queue->size;
//cas操作,更新队列尾部序号
sw_atomic_cmp_set(&queue->tail, cur_tail_index, update_tail_index);
*(queue->data + cur_tail_index) = ele;//存储元素
sw_atomic_fetch_add(cur_tail_flag_index, 1);//cas更新尾部序号,即序号+1操作
sw_atomic_fetch_add(&queue->num, 1);//cas更新队列元素个数,即队列个数+1
return 0;
}
下面分析普通的,也就是非多线程更新的环状队列。
//队列初始化,swRingQueue指向队列,buffer_size表示队列空间大小
int swRingQueue_init(swRingQueue *queue, int buffer_size)
{
//队列数据空间申请和初始化
queue->data = sw_calloc(buffer_size, sizeof(void*));
if (queue->data == NULL)//申请空间失败
{
swWarn("malloc failed.");
return -1;
}
queue->size = buffer_size;//设置队列的个数
queue->head = 0;//队列头部序号初始化
queue->tail = 0;//队列尾部序号初始化
queue->tag = 0;//为空为满的标志位
return 0;
}
//入队操作,queue为指向队列的指针,push_data为要入队的数据
int swRingQueue_push(swRingQueue *queue, void *push_data)
{
//队列已满,则抛错
if (swRingQueue_full(queue))
{
return SW_ERR;
}
queue->data[queue->tail] = push_data;//队尾添加元素
queue->tail = (queue->tail + 1) % queue->size;//更新队尾序号
//队头和队尾相等,则标记队列满
if (queue->tail == queue->head)
{
queue->tag = 1;
}
return SW_OK;
}