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;
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值