首页 > 代码库 > skynet源代码学习 - 从全局队列中弹出/压入一个消息队列过程
skynet源代码学习 - 从全局队列中弹出/压入一个消息队列过程
学习云风的skynet源代码,简单记录下。
void skynet_globalmq_push(struct message_queue * queue) { struct global_queue *q= Q; uint32_t tail = GP(__sync_fetch_and_add(&q->tail,1)); // only one thread can set the slot (change q->queue[tail] from NULL to queue) if (!__sync_bool_compare_and_swap(&q->queue[tail], NULL, queue)) { // The queue may full seldom, save queue in list // 假设swap失败说明queue[] 满了,达到了64K个队列,出现的几率非常小 // 假设这种话,就把其保存在Q的list中 assert(queue->next == NULL); struct message_queue * last; do { last = q->list; queue->next = last; } while(!__sync_bool_compare_and_swap(&q->list, last, queue)); return; } } // 结构体global_queue中的 head, tail 字段分别控制着Q的取,存过程 // GP呢能够看做是一个hash的过程,以此来确定其维护的queues的index struct message_queue * skynet_globalmq_pop() { struct global_queue *q = Q; uint32_t head = q->head; if (head == q->tail) { // The queue is empty. return NULL; } uint32_t head_ptr = GP(head); struct message_queue * list = q->list; // 假设list非空,说明Q->queue以前满过,就把他们转移回queue[]中,由于那里速度更快 if (list) { // If q->list is not empty, try to load it back to the queue struct message_queue *newhead = list->next; if (__sync_bool_compare_and_swap(&q->list, list, newhead)) { // try load list only once, if success , push it back to the queue. list->next = NULL; skynet_globalmq_push(list); } } // 从头取一个消息队列 struct message_queue * mq = q->queue[head_ptr]; if (mq == NULL) { // globalmq push not complete return NULL; } // 取走一个消息后自然要将index往后移动一个位置,而且刚那个position置为空 if (!__sync_bool_compare_and_swap(&q->head, head, head+1)) { return NULL; } // only one thread can get the slot (change q->queue[head_ptr] to NULL) if (!__sync_bool_compare_and_swap(&q->queue[head_ptr], mq, NULL)) { return NULL; } return mq; }
skynet源代码学习 - 从全局队列中弹出/压入一个消息队列过程
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。