summaryrefslogtreecommitdiff
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
parenta19a2e76fbd8abe1f592f013776a8776a758aa1f (diff)
isolate coroutine
-rw-r--r--xmake/actions/build/build.lua20
-rw-r--r--xmake/actions/build/kinds/binary.lua2
-rw-r--r--xmake/actions/build/kinds/object.lua12
-rw-r--r--xmake/actions/build/kinds/shared.lua2
-rw-r--r--xmake/actions/build/kinds/static.lua2
-rw-r--r--xmake/core/base/os.lua6
-rw-r--r--xmake/core/base/scheduler.lua65
-rw-r--r--xmake/core/sandbox/modules/import/core/base/scheduler.lua9
-rw-r--r--xmake/modules/private/action/build/object.lua2
-rw-r--r--xmake/modules/private/async/jobpool.lua4
-rw-r--r--xmake/modules/private/async/runjobs.lua20
11 files changed, 87 insertions, 57 deletions
diff --git a/xmake/actions/build/build.lua b/xmake/actions/build/build.lua
index 6448fd03d..692489f33 100644
--- a/xmake/actions/build/build.lua
+++ b/xmake/actions/build/build.lua
@@ -48,7 +48,7 @@ function _add_batchjobs_builtin(batchjobs, rootjob, target)
else
job = batchjobs:addjob("rule/" .. r:name() .. "/build", function (index, total)
script(target, {progress = (index * 100) / total})
- end, {rootjob = job or rootjob, envs = target:pkgenvs()})
+ end, {rootjob = job or rootjob})
end
end
end
@@ -91,7 +91,7 @@ function _add_batchjobs(batchjobs, rootjob, target)
--
job = batchjobs:addjob(target:name() .. "/build", function (index, total)
script(target, {progress = (index * 100) / total})
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+ end, {rootjob = rootjob})
end
return job, job_leaf or job
end
@@ -105,6 +105,7 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target)
end
-- add after_build job for target
+ local oldenvs
local job_after_build = batchjobs:addjob(target:name() .. "/after_build", function (index, total)
-- do after_build
@@ -119,7 +120,13 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target)
after_build(target, {progress = progress})
end
end
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+
+ -- restore environments
+ if oldenvs then
+ os.setenvs(oldenvs)
+ end
+
+ end, {rootjob = rootjob})
-- add batch jobs for target, @note only on_build script support batch jobs
local job_build, job_build_leaf = _add_batchjobs(batchjobs, job_after_build, target)
@@ -127,6 +134,9 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target)
-- add before_build job for target
local job_build_before = batchjobs:addjob(target:name() .. "/before_build", function (index, total)
+ -- enter package environments
+ oldenvs = os.addenvs(target:pkgenvs())
+
-- clean target if rebuild
if option.get("rebuild") and not option.get("dry-run") then
_clean_target(target)
@@ -144,7 +154,7 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target)
before_build(target, {progress = progress})
end
end
- end, {rootjob = job_build_leaf, envs = target:pkgenvs()})
+ end, {rootjob = job_build_leaf})
-- we need do build_before after all dependent targets if across_targets_in_parallel is disabled
return target:policy("build.across_targets_in_parallel") == false and job_build_before or job_build, job_after_build
@@ -212,7 +222,7 @@ function main(targetname)
if errors and progress.showing_without_scroll() then
print("")
end
- end, curdir = curdir, count_as_index = true})
+ end, curdir = curdir, count_as_index = true, isolate = true})
os.cd(curdir)
end
end
diff --git a/xmake/actions/build/kinds/binary.lua b/xmake/actions/build/kinds/binary.lua
index 0f2f8f96a..dd72fc21a 100644
--- a/xmake/actions/build/kinds/binary.lua
+++ b/xmake/actions/build/kinds/binary.lua
@@ -135,7 +135,7 @@ function main(batchjobs, rootjob, target)
-- add link job
local job_link = batchjobs:addjob(target:name() .. "/link", function (index, total)
_link_target(target, {progress = (index * 100) / total})
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+ end, {rootjob = rootjob})
-- we need only return and depend the link job for each target,
-- so we can compile the source files for each target in parallel
diff --git a/xmake/actions/build/kinds/object.lua b/xmake/actions/build/kinds/object.lua
index 5d4e4e47d..742311370 100644
--- a/xmake/actions/build/kinds/object.lua
+++ b/xmake/actions/build/kinds/object.lua
@@ -42,7 +42,7 @@ function _add_batchjobs_for_rule(batchjobs, rootjob, target, sourcebatch, suffix
else
batchjobs:addjob("rule/" .. rulename .. "/" .. scriptname, function (index, total)
script(target, sourcebatch, {progress = (index * 100) / total})
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+ end, {rootjob = rootjob})
end
end
@@ -55,7 +55,7 @@ function _add_batchjobs_for_rule(batchjobs, rootjob, target, sourcebatch, suffix
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
batchjobs:addjob(sourcefile, function (index, total)
script(target, sourcefile, {sourcekind = sourcekind, progress = (index * 100) / total})
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+ end, {rootjob = rootjob})
end
end
end
@@ -69,7 +69,7 @@ function _add_batchjobs_for_rule(batchjobs, rootjob, target, sourcebatch, suffix
local batchcmds_ = batchcmds.new({target = target})
script(target, batchcmds_, sourcebatch, {progress = (index * 100) / total})
batchcmds_:runcmds({dryrun = option.get("dry-run")})
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+ end, {rootjob = rootjob})
end
end
@@ -84,7 +84,7 @@ function _add_batchjobs_for_rule(batchjobs, rootjob, target, sourcebatch, suffix
local batchcmds_ = batchcmds.new({target = target})
script(target, batchcmds_, sourcefile, {sourcekind = sourcekind, progress = (index * 100) / total})
batchcmds_:runcmds({dryrun = option.get("dry-run")})
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+ end, {rootjob = rootjob})
end
end
end
@@ -102,7 +102,7 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target, sourcebatch, suff
else
batchjobs:addjob(target:name() .. "/" .. scriptname, function (index, total)
script(target, sourcebatch, {progress = (index * 100) / total})
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+ end, {rootjob = rootjob})
end
return true
else
@@ -113,7 +113,7 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target, sourcebatch, suff
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
batchjobs:addjob(sourcefile, function (index, total)
script(target, sourcefile, {sourcekind = sourcekind, progress = (index * 100) / total})
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+ end, {rootjob = rootjob})
end
return true
end
diff --git a/xmake/actions/build/kinds/shared.lua b/xmake/actions/build/kinds/shared.lua
index c7c4d2a37..2d2d9e507 100644
--- a/xmake/actions/build/kinds/shared.lua
+++ b/xmake/actions/build/kinds/shared.lua
@@ -150,7 +150,7 @@ function main(batchjobs, rootjob, target)
-- add link job
local job_link = batchjobs:addjob(target:name() .. "/link", function (index, total)
_link_target(target, {progress = (index * 100) / total})
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+ end, {rootjob = rootjob})
-- we need only return and depend the link job for each target,
-- so we can compile the source files for each target in parallel
diff --git a/xmake/actions/build/kinds/static.lua b/xmake/actions/build/kinds/static.lua
index 3983adef0..91fba6ed5 100644
--- a/xmake/actions/build/kinds/static.lua
+++ b/xmake/actions/build/kinds/static.lua
@@ -150,7 +150,7 @@ function main(batchjobs, rootjob, target)
-- add link job
local job_link = batchjobs:addjob(target:name() .. "/link", function (index, total)
_link_target(target, {progress = (index * 100) / total})
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+ end, {rootjob = rootjob})
-- we need only return and depend the link job for each target,
-- so we can compile the source files for each target in parallel
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
diff --git a/xmake/core/sandbox/modules/import/core/base/scheduler.lua b/xmake/core/sandbox/modules/import/core/base/scheduler.lua
index d0fff1504..50832d88c 100644
--- a/xmake/core/sandbox/modules/import/core/base/scheduler.lua
+++ b/xmake/core/sandbox/modules/import/core/base/scheduler.lua
@@ -49,6 +49,15 @@ function sandbox_core_base_scheduler.co_start_named(coname, cotask, ...)
return co
end
+-- start a new coroutine task with options
+function sandbox_core_base_scheduler.co_start_withopt(opt, cotask, ...)
+ local co, errors = scheduler:co_start_withopt(opt, cotask, ...)
+ if not co then
+ raise(errors)
+ end
+ return co
+end
+
-- resume the given coroutine
function sandbox_core_base_scheduler.co_resume(co, ...)
return scheduler:resume(co:thread(), ...)
diff --git a/xmake/modules/private/action/build/object.lua b/xmake/modules/private/action/build/object.lua
index 020c1ebc9..50397cda4 100644
--- a/xmake/modules/private/action/build/object.lua
+++ b/xmake/modules/private/action/build/object.lua
@@ -114,6 +114,6 @@ function main(target, batchjobs, sourcebatch, opt)
batchjobs:addjob(sourcefile, function (index, total)
local build_opt = table.join({objectfile = objectfile, dependfile = dependfile, sourcekind = sourcekind, progress = (index * 100) / total}, opt)
_build_object(target, sourcefile, build_opt)
- end, {rootjob = rootjob, envs = target:pkgenvs()})
+ end, {rootjob = rootjob})
end
end
diff --git a/xmake/modules/private/async/jobpool.lua b/xmake/modules/private/async/jobpool.lua
index 2709db341..299700534 100644
--- a/xmake/modules/private/async/jobpool.lua
+++ b/xmake/modules/private/async/jobpool.lua
@@ -39,11 +39,11 @@ end
--
-- @param name the job name
-- @param run the run command/script
--- @param opt the options (rootjob, envs)
+-- @param opt the options (rootjob)
--
function jobpool:addjob(name, run, opt)
opt = opt or {}
- return self:add({name = name, run = run, envs = opt.envs}, opt.rootjob)
+ return self:add({name = name, run = run}, opt.rootjob)
end
-- add job to the given job node
diff --git a/xmake/modules/private/async/runjobs.lua b/xmake/modules/private/async/runjobs.lua
index 23e6b7ecf..77bb8f2e0 100644
--- a/xmake/modules/private/async/runjobs.lua
+++ b/xmake/modules/private/async/runjobs.lua
@@ -73,10 +73,12 @@ function main(name, jobs, opt)
progress_helper = progress.new(nil, opt)
end
- -- mark current main coroutine as trampoline to avoid change envs/curdir
+ -- avoid main coroutine to change environments
+ local main_isolated
local co_running = scheduler.co_running()
if co_running then
- co_running:set_trampoline(true)
+ main_isolated = co_running:is_isolated()
+ co_running:isolate(false)
end
-- run timer
@@ -154,7 +156,7 @@ function main(name, jobs, opt)
while index < max do
-- uses job pool?
- local jobname, jobenvs
+ local jobname
if not jobs_cb then
-- get job priority
@@ -181,27 +183,21 @@ function main(name, jobs, opt)
-- get run function
jobfunc = job.run
jobname = job.name
- jobenvs = job.envs
else
jobname = tostring(index)
end
-- start this job
index = index + 1
- scheduler.co_start_named(name .. '/' .. jobname, function(i)
+ scheduler.co_start_withopt({name = name .. '/' .. jobname, isolate = opt.isolate}, function(i)
try
{
function()
running_jobs_indices[i] = i
if jobfunc then
- -- the curdir and envs of each coroutine are isolated.
- -- after the coroutine is finished, they will be automatically restored.
if opt.curdir then
os.cd(opt.curdir)
end
- if jobenvs then
- os.addenvs(jobenvs)
- end
jobfunc(count_as_index and count or i, total)
count = count + 1
end
@@ -257,8 +253,8 @@ function main(name, jobs, opt)
end
-- restore current main coroutine
- if co_running then
- co_running:set_trampoline(false)
+ if main_isolated ~= nil then
+ co_running:isolate(main_isolated)
end
-- do exit callback