diff options
| author | ruki <[email protected]> | 2021-05-12 00:37:42 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2021-05-12 00:37:42 +0800 |
| commit | 4e67226f86e1949d1087893cd8fe218535d91ba9 (patch) | |
| tree | ab02507940eabe403903b4ce80ec353681510223 | |
| parent | a19a2e76fbd8abe1f592f013776a8776a758aa1f (diff) | |
isolate coroutine
| -rw-r--r-- | xmake/actions/build/build.lua | 20 | ||||
| -rw-r--r-- | xmake/actions/build/kinds/binary.lua | 2 | ||||
| -rw-r--r-- | xmake/actions/build/kinds/object.lua | 12 | ||||
| -rw-r--r-- | xmake/actions/build/kinds/shared.lua | 2 | ||||
| -rw-r--r-- | xmake/actions/build/kinds/static.lua | 2 | ||||
| -rw-r--r-- | xmake/core/base/os.lua | 6 | ||||
| -rw-r--r-- | xmake/core/base/scheduler.lua | 65 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/core/base/scheduler.lua | 9 | ||||
| -rw-r--r-- | xmake/modules/private/action/build/object.lua | 2 | ||||
| -rw-r--r-- | xmake/modules/private/async/jobpool.lua | 4 | ||||
| -rw-r--r-- | xmake/modules/private/async/runjobs.lua | 20 |
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 |
