From 129b1cd90e03598b74bc179dc0d5a0c211b4017f Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Thu, 17 Apr 2014 15:37:01 +0800 Subject: [PATCH] queue mode --- lualib/snax.lua | 2 +- service/snaxd.lua | 77 ++++++++++++++++++++++++++++++++++++++++++--- test/pingserver.lua | 3 ++ test/testping.lua | 2 +- 4 files changed, 77 insertions(+), 7 deletions(-) diff --git a/lualib/snax.lua b/lualib/snax.lua index fd476528..e60aa293 100644 --- a/lualib/snax.lua +++ b/lualib/snax.lua @@ -90,7 +90,7 @@ end function snax.kill(obj, ...) local t = snax.interface(obj.type) - return skynet_call(obj.handle, "lua", t.system.exit, ...) + skynet_call(obj.handle, "lua", t.system.exit, ...) end local function test_result(ok, ...) diff --git a/service/snaxd.lua b/service/snaxd.lua index 519c45e4..59fe756a 100644 --- a/service/snaxd.lua +++ b/service/snaxd.lua @@ -1,12 +1,70 @@ local skynet = require "skynet" +local c = require "skynet.c" local snax_interface = require "snax_interface" local func = snax_interface(tostring(...), _ENV) +local mode +local thread_id +local message_queue = {} +local init = false + +local function do_func(f, msg) + return pcall(f, table.unpack(msg)) +end + +local function dispatch(f, ...) + return skynet.pack(f(...)) +end + +local function message_dispatch() + while true do + if #message_queue==0 then + thread_id = coroutine.running() + skynet.wait() + else + local msg = table.remove(message_queue,1) + local method = msg.method + local f = method[4] + if f then + if method[2] == "subscribe" then + -- no return + local ok, data = pcall(f, table.unpack(msg)) + if not ok then + print(string.format("Error on [:%x] to [:%x] %s", msg.source, skynet.self(), tostring(data))) + end + else + local ok, data, size = pcall(dispatch, f, table.unpack(msg)) + if ok then + -- skynet.PTYPE_RESPONSE == 1 + c.send(msg.source, 1, msg.session, data, size) + if method[2] == "system" then + init = false + skynet.exit() + break + end + else + -- Can't throw error, so print it directly + print(string.format("Error on [:%x] to [:%x] %s", msg.source, skynet.self(), tostring(data))) + c.send(msg.source, skynet.PTYPE_ERROR, msg.session, "") + end + end + end + end + end +end + +local function queue( session, source, method, ...) + table.insert(message_queue, {session = session, source = source, method = method, ... }) + if thread_id then + skynet.wakeup(thread_id) + thread_id = nil + end +end skynet.start(function() - local init = false - skynet.dispatch("lua", function ( _, _, id, ...) + skynet.dispatch("lua", function ( session , source , id, ...) local method = func[id] + if method[2] == "system" then local command = method[3] if command == "hotfix" then @@ -15,19 +73,28 @@ skynet.start(function() elseif command == "init" then assert(not init, "Already init") local initfunc = method[4] or function() end - skynet.ret(skynet.pack(initfunc(...))) + mode = initfunc(...) + if mode == "queue" then + skynet.fork(message_dispatch) + end + skynet.ret() init = true + elseif mode == "queue" then + queue( session, source, method , ...) else assert(init, "Never init") assert(command == "exit") local exitfunc = method[4] or function() end - skynet.ret(skynet.pack(exitfunc(...))) + exitfunc(...) + skynet.ret() init = false skynet.exit() end else assert(init, "Init first") - if method[2] == "subscribe" then + if mode == "queue" then + queue(session, source, method , ...) + elseif method[2] == "subscribe" then -- no return method[4](...) else diff --git a/test/pingserver.lua b/test/pingserver.lua index cedc26d3..2a266860 100644 --- a/test/pingserver.lua +++ b/test/pingserver.lua @@ -19,6 +19,9 @@ end function init( ... ) print ("ping server start:", ...) + +-- You can return "queue" for queue service mode +-- return "queue" end function exit(...) diff --git a/test/testping.lua b/test/testping.lua index 7952f20b..1244551e 100644 --- a/test/testping.lua +++ b/test/testping.lua @@ -3,8 +3,8 @@ local snax = require "snax" skynet.start(function() local ps = snax.newservice ("pingserver", "hello world") - print(ps.pub.hello()) print(ps.req.ping("foobar")) + print(ps.pub.hello()) print(pcall(ps.req.error)) print("Hotfix (i) :", snax.hotfix(ps, [[