From 4cb84ac881b6c160bbc25a3df871442a6fc850c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E9=A3=8E?= Date: Thu, 14 Jan 2021 10:23:58 +0800 Subject: [PATCH] skynet.init rework, See #1322 (#1323) * skynet.init rework, See #1322 * restore init_list #1322 * xpcall init_all, See #1322 --- lualib/loader.lua | 2 ++ lualib/skynet.lua | 50 +++++++----------------------------- lualib/skynet/multicast.lua | 2 +- lualib/skynet/require.lua | 51 +++++++++++++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 42 deletions(-) create mode 100644 lualib/skynet/require.lua diff --git a/lualib/loader.lua b/lualib/loader.lua index 1c4ee58a..c18597e8 100644 --- a/lualib/loader.lua +++ b/lualib/loader.lua @@ -45,4 +45,6 @@ if LUA_PRELOAD then LUA_PRELOAD = nil end +_G.require = (require "skynet.require").require + main(select(2, table.unpack(args))) diff --git a/lualib/skynet.lua b/lualib/skynet.lua index c65bb948..ad2ba3c9 100644 --- a/lualib/skynet.lua +++ b/lualib/skynet.lua @@ -1,5 +1,6 @@ -- read https://github.com/cloudwu/skynet/wiki/FAQ for the module "skynet.core" local c = require "skynet.core" +local skynet_require = require "skynet.require" local tostring = tostring local coroutine = coroutine local assert = assert @@ -925,49 +926,16 @@ do } end -local init_func = {} - -function skynet.init(f, name) - assert(type(f) == "function") - if init_func == nil then - f() - else - tinsert(init_func, f) - if name then - assert(type(name) == "string") - assert(init_func[name] == nil) - init_func[name] = f - end - end -end - -local function init_all() - local funcs = init_func - init_func = nil - if funcs then - for _,f in ipairs(funcs) do - f() - end - end -end - -local function ret(f, ...) - f() - return ... -end - -local function init_template(start, ...) - init_all() - init_func = {} - return ret(init_all, start(...)) -end - -function skynet.pcall(start, ...) - return xpcall(init_template, traceback, start, ...) -end +skynet.init = skynet_require.init +-- skynet.pcall is deprecated, use pcall directly +skynet.pcall = pcall function skynet.init_service(start) - local ok, err = skynet.pcall(start) + local function main() + skynet_require.init_all() + start() + end + local ok, err = xpcall(main, traceback) if not ok then skynet.error("init service failed: " .. tostring(err)) skynet.send(".launcher","lua", "ERROR") diff --git a/lualib/skynet/multicast.lua b/lualib/skynet/multicast.lua index 07e74df6..8b3a4e5d 100644 --- a/lualib/skynet/multicast.lua +++ b/lualib/skynet/multicast.lua @@ -95,6 +95,6 @@ local function init() } end -skynet.init(init, "multicast") +skynet.init(init) return multicast \ No newline at end of file diff --git a/lualib/skynet/require.lua b/lualib/skynet/require.lua new file mode 100644 index 00000000..23724726 --- /dev/null +++ b/lualib/skynet/require.lua @@ -0,0 +1,51 @@ +-- skynet module two-step initialize . When you require a skynet module : +-- 1. Run module main function as official lua module behavior. +-- 2. Run the functions register by skynet.init() during the step 1, +-- unless calling `require` in main thread . +-- If you call `require` in main thread ( service main function ), the functions +-- registered by skynet.init() do not execute immediately, they will be executed +-- by skynet.start() before start function. + +local M = {} + +local mainthread, ismain = coroutine.running() +assert(ismain, "skynet.require must initialize in main thread") + +local context = { + [mainthread] = {}, +} + +do + local require = _G.require + function M.require(...) + local co, main = coroutine.running() + if main then + return require(...) + else + local old_init_list = context[co] + local init_list = {} + context[co] = init_list + local ret = require(...) + for _, f in ipairs(init_list) do + f() + end + context[co] = old_init_list + return ret + end + end +end + +function M.init_all() + for _, f in ipairs(context[mainthread]) do + f() + end + context[mainthread] = nil +end + +function M.init(f) + assert(type(f) == "function") + local co = coroutine.running() + table.insert(context[co], f) +end + +return M \ No newline at end of file