Learn Yunfeng's Skynet source code, simply record it.
void Skynet_globalmq_push (struct message_queue * queue) {struct Global_queue *q= q;uint32_t tail = GP (__sync_fetch_and_ad D (&q->tail,1));//Only one thread can set the slot (change Q->queue[tail] from NULL to queue) if (!__sync_bool_co Mpare_and_swap (&q->queue[tail], NULL, queue)) {//the queue may be full seldom, save queue in list//assuming swap failure description queue[] Full, reached the 64K queue, the probability of the occurrence is very small//assuming such words, it is stored in the 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;}} The head in the structure global_queue, the tail field controls the Q's take, the deposit process//GP can be regarded as a hash process, in order to determine its maintenance queues indexstruct Message_queue * skynet_ Globalmq_pop () {struct Global_queue *q = q;uint32_t head = q->head;if (head = = Q->tail) {//the queue is Empty.retu RN NULL;} uint32_t head_ptr = GP (head), struct message_queue * list = q->list;//assumes that the list is not empty, stating that Q->queue was full before transferring them back to queue[], Because there is faster if (list) {//If q->list is not emPty, try to load it back to the queuestruct 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);}} Take a message queue from scratch struct message_queue * mq = q->queue[head_ptr];if (MQ = = null) {//GLOBALMQ push not Completereturn NULL;} After taking a message, it is natural to move the index back one position, and just that position is empty 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->que UE[HEAD_PTR], MQ, NULL) {return null;} return MQ;}
Skynet source code Learning-eject/press into a Message Queuing process from a global queue