summaryrefslogtreecommitdiff
path: root/xmake/core/base
diff options
context:
space:
mode:
authorruki <[email protected]>2021-05-12 00:37:42 +0800
committerruki <[email protected]>2021-05-12 00:37:42 +0800
commit4e67226f86e1949d1087893cd8fe218535d91ba9 (patch)
treeab02507940eabe403903b4ce80ec353681510223 /xmake/core/base
parenta19a2e76fbd8abe1f592f013776a8776a758aa1f (diff)
isolate coroutine
Diffstat (limited to 'xmake/core/base')
-rw-r--r--xmake/core/base/os.lua6
-rw-r--r--xmake/core/base/scheduler.lua65
2 files changed, 43 insertions, 28 deletions
diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua
index 8fe7457e9..bff650f5d 100644
--- a/xmake/core/base/os.lua
+++ b/xmake/core/base/os.lua
@@ -1002,7 +1002,7 @@ end
function os.getenvs()
local envs = os._CURENVS
if not envs then
--- print("os.getenvs")
+ print("os.getenvs")
envs = {}
for _, line in ipairs(os._getenvs()) do
local p = line:find('=', 1, true)
@@ -1051,7 +1051,6 @@ function os.setenvs(envs)
return oldenvs
end
---[[
os._setenv2 = os._setenv
os._setenv = function (name, value)
print("setenv", name, value)
@@ -1062,7 +1061,7 @@ os._getenv = os.getenv
os.getenv = function (name)
print("getenv", name)
return os._getenv(name)
-end]]
+end
-- add environment variables
-- e.g. envs["PATH"] = "/xxx:/yyy/foo"
@@ -1073,6 +1072,7 @@ function os.addenvs(envs)
for name, values in pairs(envs) do
local ok
local oldenv = oldenvs[name]
+ print("oldenv", name, oldenv)
if oldenv == "" or oldenv == nil then
ok = os._setenv(name, values)
elseif not oldenv:startswith(values) then
diff --git a/xmake/core/base/scheduler.lua b/xmake/core/base/scheduler.lua
index 34dfacb85..c33b5c7f0 100644
--- a/xmake/core/base/scheduler.lua
+++ b/xmake/core/base/scheduler.lua
@@ -87,15 +87,14 @@ function _coroutine:is_suspended()
return self:status() == "suspended"
end
--- is trampoline?
-function _coroutine:is_trampoline()
- return self._TRAMPOLINE
+-- is isolated?
+function _coroutine:is_isolated()
+ return self._ISOLATED
end
--- mark this coroutine as trampoline,
--- envs and curdir will not be changed when switch to this coroutine
-function _coroutine:set_trampoline(trampoline)
- self._TRAMPOLINE = trampoline
+-- isolate coroutine environments
+function _coroutine:isolate(isolate)
+ self._ISOLATED = isolate
end
-- get the current timer task
@@ -249,26 +248,35 @@ end
-- update the current directory hash of current coroutine
function scheduler:_co_curdir_update(curdir)
+ -- get running coroutine
+ local running = self:co_running()
+ if not running then
+ return
+ end
+
-- save the current directory hash
curdir = curdir or os.curdir()
local curdir_hash = hash.uuid4(path.absolute(curdir)):sub(1, 8)
self._CO_CURDIR_HASH = curdir_hash
-- save the current directory for each coroutine
- local running = self:co_running()
- if running then
- local co_curdirs = self._CO_CURDIRS
- if not co_curdirs then
- co_curdirs = {}
- self._CO_CURDIRS = co_curdirs
- end
- co_curdirs[running] = {curdir_hash, curdir}
+ local co_curdirs = self._CO_CURDIRS
+ if not co_curdirs then
+ co_curdirs = {}
+ self._CO_CURDIRS = co_curdirs
end
+ co_curdirs[running] = {curdir_hash, curdir}
end
-- update the current environments hash of current coroutine
function scheduler:_co_curenvs_update(envs)
+ -- get running coroutine
+ local running = self:co_running()
+ if not running or not running:is_isolated() then
+ return
+ end
+
-- save the current directory hash
local envs_hash = ""
envs = envs or os.getenvs()
@@ -279,15 +287,12 @@ function scheduler:_co_curenvs_update(envs)
self._CO_CURENVS_HASH = envs_hash
-- save the current directory for each coroutine
- local running = self:co_running()
- if running then
- local co_curenvs = self._CO_CURENVS
- if not co_curenvs then
- co_curenvs = {}
- self._CO_CURENVS = co_curenvs
- end
- co_curenvs[running] = {envs_hash, envs}
+ local co_curenvs = self._CO_CURENVS
+ if not co_curenvs then
+ co_curenvs = {}
+ self._CO_CURENVS = co_curenvs
end
+ co_curenvs[running] = {envs_hash, envs}
end
-- resume it's waiting coroutine if all coroutines are dead in group
@@ -339,8 +344,15 @@ end
-- start a new named coroutine task
function scheduler:co_start_named(coname, cotask, ...)
+ return self:co_start_withopt({name = coname}, cotask, ...)
+end
+
+-- start a new coroutine task with options
+function scheduler:co_start_withopt(opt, cotask, ...)
-- check coroutine task
+ opt = opt or {}
+ local coname = opt.name
if not cotask then
return nil, string.format("cannot start coroutine, invalid cotask(%s/%s)", coname and coname or "anonymous", cotask)
end
@@ -356,6 +368,9 @@ function scheduler:co_start_named(coname, cotask, ...)
self._CO_COUNT = self:co_count() - 1
end
end))
+ if opt.isolate then
+ co:isolate(true)
+ end
self:co_tasks()[co:thread()] = co
self._CO_COUNT = self:co_count() + 1
if self._STARTED then
@@ -393,14 +408,14 @@ function scheduler:co_suspend(...)
local running = assert(self:co_running())
local curdir = self._CO_CURDIR_HASH
local olddir = self._CO_CURDIRS and self._CO_CURDIRS[running] or nil
- if olddir and curdir ~= olddir[1] and not running:is_trampoline() then -- hash changed?
+ if olddir and curdir ~= olddir[1] then -- hash changed?
os.cd(olddir[2])
end
-- if the current environments has been changed? restore it
local curenvs = self._CO_CURENVS_HASH
local oldenvs = self._CO_CURENVS and self._CO_CURENVS[running] or nil
- if oldenvs and curenvs ~= oldenvs[1] and not running:is_trampoline() then -- hash changed?
+ if oldenvs and curenvs ~= oldenvs[1] and running:is_isolated() then -- hash changed?
os.setenvs(oldenvs[2])
end