diff --git a/skynet-src/skynet_server.c b/skynet-src/skynet_server.c index 4ec7ea54..ab7094c8 100644 --- a/skynet-src/skynet_server.c +++ b/skynet-src/skynet_server.c @@ -228,11 +228,13 @@ _dispatch_message(struct skynet_context *ctx, struct skynet_message *msg) { CHECKCALLING_END(ctx) } -int -skynet_context_message_dispatch(struct skynet_monitor *sm) { - struct message_queue * q = skynet_globalmq_pop(); - if (q==NULL) - return 1; +struct message_queue * +skynet_context_message_dispatch(struct skynet_monitor *sm, struct message_queue *q) { + if (q == NULL) { + q = skynet_globalmq_pop(); + if (q==NULL) + return NULL; + } uint32_t handle = skynet_mq_handle(q); @@ -240,13 +242,13 @@ skynet_context_message_dispatch(struct skynet_monitor *sm) { if (ctx == NULL) { struct drop_t d = { handle }; skynet_mq_release(q, drop_message, &d); - return 0; + return skynet_globalmq_pop(); } struct skynet_message msg; if (skynet_mq_pop(q,&msg)) { skynet_context_release(ctx); - return 0; + return skynet_globalmq_pop(); } skynet_monitor_trigger(sm, msg.source , handle); @@ -258,12 +260,18 @@ skynet_context_message_dispatch(struct skynet_monitor *sm) { } assert(q == ctx->queue); - skynet_globalmq_push(q); + struct message_queue *nq = skynet_globalmq_pop(); + if (nq) { + // If global mq is not empty , push q back, and return next queue (nq) + // Else (global mq is empty or block, don't push q back, and return q again (for next dispatch) + skynet_globalmq_push(q); + q = nq; + } skynet_context_release(ctx); skynet_monitor_trigger(sm, 0,0); - return 0; + return q; } static void diff --git a/skynet-src/skynet_server.h b/skynet-src/skynet_server.h index 7adc1292..51b8d1b2 100644 --- a/skynet-src/skynet_server.h +++ b/skynet-src/skynet_server.h @@ -16,7 +16,7 @@ void skynet_context_init(struct skynet_context *, uint32_t handle); int skynet_context_push(uint32_t handle, struct skynet_message *message); void skynet_context_send(struct skynet_context * context, void * msg, size_t sz, uint32_t source, int type, int session); int skynet_context_newsession(struct skynet_context *); -int skynet_context_message_dispatch(struct skynet_monitor *); // return 1 when block +struct message_queue * skynet_context_message_dispatch(struct skynet_monitor *, struct message_queue *); // return next queue int skynet_context_total(); void skynet_context_endless(uint32_t handle); // for monitor diff --git a/skynet-src/skynet_start.c b/skynet-src/skynet_start.c index 09ab7711..d45ded49 100644 --- a/skynet-src/skynet_start.c +++ b/skynet-src/skynet_start.c @@ -121,8 +121,10 @@ _worker(void *p) { struct monitor *m = wp->m; struct skynet_monitor *sm = m->m[id]; skynet_initthread(THREAD_WORKER); + struct message_queue * q = NULL; for (;;) { - if (skynet_context_message_dispatch(sm)) { + q = skynet_context_message_dispatch(sm, q); + if (q == NULL) { CHECK_ABORT if (pthread_mutex_lock(&m->mutex) == 0) { ++ m->sleep;