summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2020-03-08 15:18:13 +0800
committerruki <[email protected]>2020-03-08 15:18:13 +0800
commit82a72523912a398f367d4b19cf550ad8aaa1c8be (patch)
tree7984209a7faabfe0db33627283ae46b2c4138a83
parent757ab49a3eb245163080dbc59f8f95f35ee47c9a (diff)
add jobpool
-rw-r--r--tests/modules/scheduler/runjobs.lua13
-rw-r--r--xmake/actions/build/build.lua231
-rw-r--r--xmake/actions/build/kinds/binary.lua23
-rw-r--r--xmake/actions/build/kinds/object.lua41
-rw-r--r--xmake/actions/build/kinds/shared.lua23
-rw-r--r--xmake/actions/build/kinds/static.lua19
-rw-r--r--xmake/actions/build/main.lua4
-rw-r--r--xmake/modules/private/action/build/object.lua8
-rw-r--r--xmake/modules/private/async/jobpool.lua122
-rw-r--r--xmake/modules/private/async/runjobs.lua27
10 files changed, 249 insertions, 262 deletions
diff --git a/tests/modules/scheduler/runjobs.lua b/tests/modules/scheduler/runjobs.lua
index 0ef0712b7..489e221ee 100644
--- a/tests/modules/scheduler/runjobs.lua
+++ b/tests/modules/scheduler/runjobs.lua
@@ -1,4 +1,5 @@
import("core.base.scheduler")
+import("private.async.jobpool")
import("private.async.runjobs")
function _jobfunc(index, total)
@@ -20,12 +21,18 @@ function main()
-- test jobs
print("==================================== test jobs ====================================")
- local jobs = {}
+ local jobs = jobpool.new()
+ local root = jobs:addjob("job/root", function (idx, total, job)
+ _jobfunc(idx, total)
+ end)
for i = 1, 3 do
+ local job = jobs:addjob("job/" .. i, function (idx, total, job)
+ _jobfunc(idx, total)
+ end, root)
for j = 1, 50 do
- table.insert(jobs, {priority = i, run = function (idx, total, job)
+ jobs:addjob("job/" .. i .. "/" .. j, function (idx, total, job)
_jobfunc(idx, total)
- end})
+ end, job)
end
end
t = os.mclock()
diff --git a/xmake/actions/build/build.lua b/xmake/actions/build/build.lua
index 2d6e0b244..d01890c0f 100644
--- a/xmake/actions/build/build.lua
+++ b/xmake/actions/build/build.lua
@@ -23,6 +23,9 @@ import("core.base.option")
import("core.project.config")
import("core.project.project")
import("core.platform.environment")
+import("private.async.jobpool")
+import("private.async.runjobs")
+import("core.base.hashset")
-- clean target for rebuilding
function _clean_target(target)
@@ -60,186 +63,132 @@ function _on_build_target(target, opt)
end
-- build the given target
-function _build_target(target)
+function _add_buildjob_for_target(buildjobs, rootjob, target)
-- has been disabled?
if target:get("enabled") == false then
- _g.targetindex = _g.targetindex + 1
return
end
- -- enter the environments of the target packages
+ -- add after_build job for target
local oldenvs = {}
- for name, values in pairs(target:pkgenvs()) do
- oldenvs[name] = os.getenv(name)
- os.addenv(name, unpack(values))
- end
-
- -- compute the progress range
- local progress = {}
- progress.start = (_g.targetindex * 100) / _g.targetcount
- progress.stop = ((_g.targetindex + 1) * 100) / _g.targetcount
-
- -- the target scripts
- local scripts =
- {
- function (target)
-
- -- do before build for target
- local before_build = target:script("build_before")
- if before_build then
- before_build(target, {progress = progress})
- end
-
- -- do before build for rules
- for _, r in ipairs(target:orderules()) do
- local before_build = r:script("build_before")
- if before_build then
- before_build(target, {progress = progress})
- end
- end
- end
- , function (target)
+ local job_after_build = buildjobs:addjob(target:name() .. "/after_build", function (index, total, job)
- -- do build
- local on_build = target:script("build", _on_build_target)
- if on_build then
- on_build(target, {origin = _do_build_target, progress = progress})
- end
+ -- do after_build
+ local progress = (index * 100) / total
+ local after_build = target:script("build_after")
+ if after_build then
+ after_build(target, {progress = progress})
end
- , function (target)
-
- -- do after build for target
- local after_build = target:script("build_after")
+ for _, r in ipairs(target:orderules()) do
+ local after_build = r:script("build_after")
if after_build then
after_build(target, {progress = progress})
end
-
- -- do after build for rules
- for _, r in ipairs(target:orderules()) do
- local after_build = r:script("build_after")
- if after_build then
- after_build(target, {progress = progress})
- end
- end
end
- }
-
- -- clean target if rebuild
- if option.get("rebuild") then
- _clean_target(target)
- end
-
- -- run the target scripts
- for i = 1, 3 do
- local script = scripts[i]
- if script ~= nil then
- script(target)
+
+ -- leave the environments of the target packages
+ for name, values in pairs(oldenvs) do
+ os.setenv(name, values)
end
- end
-
- -- leave the environments of the target packages
- for name, values in pairs(oldenvs) do
- os.setenv(name, values)
- end
-
- -- update target index
- _g.targetindex = _g.targetindex + 1
-end
+ end, rootjob)
--- build the given target and deps
-function _build_target_and_deps(target)
+ -- add build job for target
+ local job_build = buildjobs:addjob(target:name() .. "/build", function (index, total, job)
+ local progress = (index * 100) / total
+ local on_build = target:script("build", _on_build_target)
+ if on_build then
+ on_build(target, {origin = _do_build_target, progress = progress})
+ end
+ end, job_after_build)
- -- this target have been finished?
- if _g.finished[target:name()] then
- return
- end
+ -- add before_build job for target
+ local job_before_build = buildjobs:addjob(target:name() .. "/before_build", function (index, total, job)
- -- make for all dependent targets
- for _, depname in ipairs(target:get("deps")) do
- _build_target_and_deps(project.target(depname))
- end
+ -- enter the environments of the target packages
+ for name, values in pairs(target:pkgenvs()) do
+ oldenvs[name] = os.getenv(name)
+ os.addenv(name, unpack(values))
+ end
- -- make target
- _build_target(target)
+ -- clean target if rebuild
+ if option.get("rebuild") then
+ _clean_target(target)
+ end
- -- finished
- _g.finished[target:name()] = true
+ -- do before_build
+ local progress = (index * 100) / total
+ local before_build = target:script("build_before")
+ if before_build then
+ before_build(target, {progress = progress})
+ end
+ for _, r in ipairs(target:orderules()) do
+ local before_build = r:script("build_before")
+ if before_build then
+ before_build(target, {progress = progress})
+ end
+ end
+ end, job_build)
+ return job_before_build
end
--- stats the given target and deps
-function _stat_target_count_and_deps(target)
-
- -- this target have been finished?
- if _g.finished[target:name()] then
- return
- end
-
- -- make for all dependent targets
- for _, depname in ipairs(target:get("deps")) do
- _stat_target_count_and_deps(project.target(depname))
+-- build the given target and deps
+function _add_buildjob_for_target_and_deps(buildjobs, rootjob, inserted, target)
+ if not inserted[target:name()] then
+ rootjob = _add_buildjob_for_target(buildjobs, rootjob, target)
+ for _, depname in ipairs(target:get("deps")) do
+ _add_buildjob_for_target_and_deps(buildjobs, rootjob, inserted, project.target(depname))
+ end
+ inserted[target:name()] = true
end
-
- -- update count
- _g.targetcount = _g.targetcount + 1
-
- -- finished
- _g.finished[target:name()] = true
end
--- stats targets count
-function _stat_target_count(targetname)
+-- get build jobs
+function _get_buildjobs(targetname)
- -- init finished states
- _g.finished = {}
-
- -- init targets count
- _g.targetcount = 0
-
- -- for the given target?
+ -- get root targets
+ local targets_root = {}
if targetname then
- _stat_target_count_and_deps(project.target(targetname))
+ table.insert(targets_root, project.target(targetname))
else
- -- for default or all targets
+ local depset = hashset.new()
+ local targets = {}
for _, target in pairs(project.targets()) do
local default = target:get("default")
if default == nil or default == true or option.get("all") then
- _stat_target_count_and_deps(target)
+ for _, depname in ipairs(target:get("deps")) do
+ depset:insert(depname)
+ table.insert(targets, target)
+ end
end
end
+ for _, target in pairs(targets) do
+ if not depset:has(target:name()) then
+ table.insert(targets_root, target)
+ end
+ end
+ end
+
+ -- generate build jobs for default or all targets
+ local inserted = {}
+ local buildjobs = jobpool.new()
+ for _, target in pairs(targets_root) do
+ _add_buildjob_for_target_and_deps(buildjobs, buildjobs:rootjob(), inserted, target)
end
+ return buildjobs
end
-- the main entry
function main(targetname)
- -- enter toolchains environment
- environment.enter("toolchains")
-
- -- stat targets count
- _stat_target_count(targetname)
-
- -- clear finished states
- _g.finished = {}
-
- -- init target index
- _g.targetindex = 0
-
- -- build the given target?
- if targetname then
- _build_target_and_deps(project.target(targetname))
- else
- -- build default or all targets
- for _, target in pairs(project.targets()) do
- local default = target:get("default")
- if default == nil or default == true or option.get("all") then
- _build_target_and_deps(target)
- end
- end
+ -- build all jobs
+ local buildjobs = _get_buildjobs(targetname)
+ print(buildjobs)
+ if buildjobs and buildjobs:count() > 0 then
+ environment.enter("toolchains")
+ runjobs("build", buildjobs, {comax = option.get("jobs") or 1})
+ environment.leave("toolchains")
end
-
- -- leave toolchains environment
- environment.leave("toolchains")
end
diff --git a/xmake/actions/build/kinds/binary.lua b/xmake/actions/build/kinds/binary.lua
index 13ad6e153..c11fadd7c 100644
--- a/xmake/actions/build/kinds/binary.lua
+++ b/xmake/actions/build/kinds/binary.lua
@@ -73,9 +73,9 @@ function _do_link_target(target, opt)
-- trace progress info
local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} "
if verbose then
- cprint(progress_prefix .. "${dim color.build.target}linking.$(mode) %s", opt.progress.stop, path.filename(targetfile))
+ cprint(progress_prefix .. "${dim color.build.target}linking.$(mode) %s", opt.progress, path.filename(targetfile))
else
- cprint(progress_prefix .. "${color.build.target}linking.$(mode) %s", opt.progress.stop, path.filename(targetfile))
+ cprint(progress_prefix .. "${color.build.target}linking.$(mode) %s", opt.progress, path.filename(targetfile))
end
-- trace verbose info
@@ -119,13 +119,7 @@ end
-- link target
function _link_target(target, opt)
- -- get progress
- local progress = opt.progress
- local progress_before = {start = progress.start, stop = progress.start}
- local progress_after = {start = progress.stop, stop = progress.stop}
-
-- do before link for target
- opt.progress = progress_before
local before_link = target:script("link_before")
if before_link then
before_link(target, opt)
@@ -140,11 +134,9 @@ function _link_target(target, opt)
end
-- on link
- opt.progress = progress
target:script("link", _on_link_target)(target, table.join(opt, {origin = _do_link_target}))
-- do after link for target
- opt.progress = progress_after
local after_link = target:script("link_after")
if after_link then
after_link(target, opt)
@@ -161,17 +153,6 @@ end
-- build binary target
function build(target, opt)
-
- -- separate progress
- local progress = opt.progress
- local progress_mid = math.max(progress.start, progress.stop - 1)
-
- -- build objects
- opt = table.copy(opt)
- opt.progress = {start = progress.start, stop = progress_mid}
object.build(target, opt)
-
- -- link target
- opt.progress = {start = progress_mid, stop = progress.stop}
_link_target(target, opt)
end
diff --git a/xmake/actions/build/kinds/object.lua b/xmake/actions/build/kinds/object.lua
index 141019cf3..d90820693 100644
--- a/xmake/actions/build/kinds/object.lua
+++ b/xmake/actions/build/kinds/object.lua
@@ -34,18 +34,9 @@ function _build_files_with_rule(target, sourcebatch, opt, suffix)
-- get rule instance
local ruleinst = assert(project.rule(rulename) or rule.rule(rulename), "unknown rule: %s", rulename)
- -- get progress
- local progress = opt.progress
-
-- on_build_files?
local on_build_files = ruleinst:script("build_files" .. (suffix and ("_" .. suffix) or ""))
if on_build_files then
- opt = table.copy(opt)
- if suffix == "before" then
- opt.progress = {start = progress.start, stop = progress.start}
- elseif suffix == "after" then
- opt.progress = {start = progress.stop, stop = progress.stop}
- end
on_build_files(target, sourcebatch, opt)
else
-- get the build file script
@@ -60,22 +51,11 @@ function _build_files_with_rule(target, sourcebatch, opt, suffix)
local sourcecount = #sourcebatch.sourcefiles
runjobs("build_files", function (index)
- -- force to set the current directory first because the other jobs maybe changed it
- os.cd(curdir)
-
- -- get current progress
- local progress_now = progress.start + ((index - 1) * (progress.stop - progress.start)) / sourcecount
- if suffix == "before" then
- progress_now = progress.start
- elseif suffix == "after" then
- progress_now = progress.stop
- end
-
-- get source file
local sourcefile = sourcebatch.sourcefiles[index]
-- do build file
- on_build_file(target, sourcefile, {sourcekind = sourcebatch.sourcekind, progress = progress_now})
+ on_build_file(target, sourcefile, {sourcekind = sourcebatch.sourcekind, progress = opt.progress})
end, {total = sourcecount, comax = jobs})
end
@@ -93,8 +73,6 @@ function _build_files(target, sourcebatch, opt)
-- do before build
local before_build_files = target:script("build_files_before")
if before_build_files then
- opt = table.copy(opt)
- opt.progress = {start = progress.start, stop = progress.start}
before_build_files(target, sourcebatch, opt)
end
@@ -111,8 +89,6 @@ function _build_files(target, sourcebatch, opt)
-- do after build
local after_build_files = target:script("build_files_after")
if after_build_files then
- opt = table.copy(opt)
- opt.progress = {start = progress.stop, stop = progress.stop}
after_build_files(target, sourcebatch, opt)
end
end
@@ -123,29 +99,14 @@ function build_sourcefiles(target, sourcebatches, opt)
-- init options
opt = opt or {}
- -- get progress range
- local progress = assert(opt.progress, "no build progress!")
-
-- build source batches with custom rules before building other sources
for _, sourcebatch in pairs(sourcebatches) do
_build_files_with_rule(target, sourcebatch, opt, "before")
end
-- build source batches
- local sourcestart = 0
- local sourcestop = 0
local sourcetotal = target:sourcecount()
for _, sourcebatch in pairs(sourcebatches) do
-
- -- compute the sub-progress range
- sourcestop = sourcestart + #sourcebatch.sourcefiles
- local progress_range = progress.stop - progress.start
- local progress_start = progress.start + (sourcestart * progress_range) / sourcetotal
- local progress_stop = progress.start + (sourcestop * progress_range) / sourcetotal
- opt.progress = {start = progress_start, stop = progress_stop}
- sourcestart = sourcestop
-
- -- build files
_build_files(target, sourcebatch, opt)
end
diff --git a/xmake/actions/build/kinds/shared.lua b/xmake/actions/build/kinds/shared.lua
index 9ad2541db..4625d2c5b 100644
--- a/xmake/actions/build/kinds/shared.lua
+++ b/xmake/actions/build/kinds/shared.lua
@@ -86,9 +86,9 @@ function _do_link_target(target, opt)
-- trace progress info
local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} "
if verbose then
- cprint(progress_prefix .. "${dim color.build.target}linking.$(mode) %s", opt.progress.stop, path.filename(targetfile))
+ cprint(progress_prefix .. "${dim color.build.target}linking.$(mode) %s", opt.progress, path.filename(targetfile))
else
- cprint(progress_prefix .. "${color.build.target}linking.$(mode) %s", opt.progress.stop, path.filename(targetfile))
+ cprint(progress_prefix .. "${color.build.target}linking.$(mode) %s", opt.progress, path.filename(targetfile))
end
-- trace verbose info
@@ -132,13 +132,7 @@ end
-- link target
function _link_target(target, opt)
- -- get progress
- local progress = opt.progress
- local progress_before = {start = progress.start, stop = progress.start}
- local progress_after = {start = progress.stop, stop = progress.stop}
-
-- do before link for target
- opt.progress = progress_before
local before_link = target:script("link_before")
if before_link then
before_link(target, opt)
@@ -153,11 +147,9 @@ function _link_target(target, opt)
end
-- on link
- opt.progress = progress
target:script("link", _on_link_target)(target, table.join(opt, {origin = _do_link_target}))
-- do after link for target
- opt.progress = progress_after
local after_link = target:script("link_after")
if after_link then
after_link(target, opt)
@@ -174,17 +166,6 @@ end
-- build shared target
function build(target, opt)
-
- -- separate progress
- local progress = opt.progress
- local progress_mid = math.max(progress.start, progress.stop - 1)
-
- -- build objects
- opt = table.copy(opt)
- opt.progress = {start = progress.start, stop = progress_mid}
object.build(target, opt)
-
- -- link target
- opt.progress = {start = progress_mid, stop = progress.stop}
_link_target(target, opt)
end
diff --git a/xmake/actions/build/kinds/static.lua b/xmake/actions/build/kinds/static.lua
index 6c0a9a2f8..d1bcedde6 100644
--- a/xmake/actions/build/kinds/static.lua
+++ b/xmake/actions/build/kinds/static.lua
@@ -82,9 +82,9 @@ function _do_link_target(target, opt)
-- trace progress info
local progress_prefix = "${color.build.progress}" .. theme.get("text.build.progress_format") .. ":${clear} "
if verbose then
- cprint(progress_prefix .. "${dim color.build.target}archiving.$(mode) %s", opt.progress.stop, path.filename(targetfile))
+ cprint(progress_prefix .. "${dim color.build.target}archiving.$(mode) %s", opt.progress, path.filename(targetfile))
else
- cprint(progress_prefix .. "${color.build.target}archiving.$(mode) %s", opt.progress.stop, path.filename(targetfile))
+ cprint(progress_prefix .. "${color.build.target}archiving.$(mode) %s", opt.progress, path.filename(targetfile))
end
-- trace verbose info
@@ -128,13 +128,7 @@ end
-- link target
function _link_target(target, opt)
- -- get progress
- local progress = opt.progress
- local progress_before = {start = progress.start, stop = progress.start}
- local progress_after = {start = progress.stop, stop = progress.stop}
-
-- do before link for target
- opt.progress = progress_before
local before_link = target:script("link_before")
if before_link then
before_link(target, opt)
@@ -149,11 +143,9 @@ function _link_target(target, opt)
end
-- on link
- opt.progress = progress
target:script("link", _on_link_target)(target, table.join(opt, {origin = _do_link_target}))
-- do after link for target
- opt.progress = progress_after
local after_link = target:script("link_after")
if after_link then
after_link(target, opt)
@@ -171,16 +163,9 @@ end
-- build static target
function build(target, opt)
- -- separate progress
- local progress = opt.progress
- local progress_mid = math.max(progress.start, progress.stop - 1)
-
-- build objects
- opt = table.copy(opt)
- opt.progress = {start = progress.start, stop = progress_mid}
object.build(target, opt)
-- link target
- opt.progress = {start = progress_mid, stop = progress.stop}
_link_target(target, opt)
end
diff --git a/xmake/actions/build/main.lua b/xmake/actions/build/main.lua
index 482b465a9..61ee24401 100644
--- a/xmake/actions/build/main.lua
+++ b/xmake/actions/build/main.lua
@@ -137,7 +137,5 @@ function main()
os.cd(oldir)
-- trace
- if option.get("rebuild") then
- cprint("${color.success}build ok!")
- end
+ cprint("${color.success}build ok!")
end
diff --git a/xmake/modules/private/action/build/object.lua b/xmake/modules/private/action/build/object.lua
index f439f0f37..0de2729f6 100644
--- a/xmake/modules/private/action/build/object.lua
+++ b/xmake/modules/private/action/build/object.lua
@@ -92,14 +92,8 @@ function _build_object(target, sourcebatch, index, opt)
local dependfile = sourcebatch.dependfiles[index]
local sourcekind = assert(sourcebatch.sourcekind, "%s: sourcekind not found!", sourcefile)
- -- get progress range
- local progress = assert(opt.progress, "no progress!")
-
- -- calculate progress
- local progress_now = progress.start + ((index - 1) * (progress.stop - progress.start)) / #sourcebatch.sourcefiles
-
-- init build option
- local opt = table.join(opt, {objectfile = objectfile, dependfile = dependfile, sourcekind = sourcekind, progress = progress_now})
+ local opt = table.join(opt, {objectfile = objectfile, dependfile = dependfile, sourcekind = sourcekind, progress = opt.progress})
-- do before build
local before_build_file = target:script("build_file_before")
diff --git a/xmake/modules/private/async/jobpool.lua b/xmake/modules/private/async/jobpool.lua
new file mode 100644
index 000000000..b0dc56454
--- /dev/null
+++ b/xmake/modules/private/async/jobpool.lua
@@ -0,0 +1,122 @@
+--!A cross-platform build utility based on Lua
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-- Copyright (C) 2015-2020, TBOOX Open Source Group.
+--
+-- @author ruki
+-- @file jobpool.lua
+--
+
+-- imports
+import("core.base.dlist")
+import("core.base.object")
+
+-- define module
+local jobpool = jobpool or object {_init = {"_count", "_rootjob", "_leafjobs"}}
+
+-- get jobs count
+function jobpool:count()
+ return self._count
+end
+
+-- get root job
+function jobpool:rootjob()
+ return self._rootjob
+end
+
+-- add job to the given job node
+--
+-- @param rootjob the root job node
+-- @param name the job name
+-- @param run the run command/script
+--
+function jobpool:addjob(name, run, rootjob)
+ rootjob = rootjob or self:rootjob()
+ local job = {name = name, run = run, _parent = rootjob}
+ rootjob._deps = rootjob._deps or dlist:new()
+ rootjob._deps:push(job)
+ self._count = self._count + 1
+ return job
+end
+
+-- pop job without deps at leaf node
+function jobpool:popjob()
+
+ -- no jobs?
+ if self:count() == 0 then
+ return
+ end
+
+ -- init leaf jobs first
+ local leafjobs = self._leafjobs
+ if #leafjobs == 0 then
+ self:_genleafjobs(self:rootjob(), leafjobs)
+ end
+
+ -- pop a job from the leaf jobs
+ if #leafjobs > 0 then
+
+ -- update jobs count
+ self._count = self._count - 1
+
+ -- get job
+ local job = leafjobs[#leafjobs]
+ table.remove(leafjobs, #leafjobs)
+
+ -- remove this job from the parent node
+ local priority = job._priority or 0
+ local parent = assert(job._parent, "invalid job without parent node!")
+ parent._priority = math.max(parent._priority or 0, priority + 1)
+ parent._deps:remove(job)
+ if parent._deps:empty() and self._count > 0 then
+ table.insert(leafjobs, 1, parent)
+ end
+ return job, priority
+ end
+end
+
+-- generate all leaf jobs from the given job
+function jobpool:_genleafjobs(job, leafjobs)
+ local deps = job._deps
+ if deps and not deps:empty() then
+ for dep in deps:items() do
+ self:_genleafjobs(dep, leafjobs)
+ end
+ else
+ table.insert(leafjobs, job)
+ end
+end
+
+-- generate jobs tree for the given job
+function jobpool:_gentree(job)
+ local tree = {job.name}
+ local deps = job._deps
+ if deps and not deps:empty() then
+ tree[2] = {}
+ for dep in deps:items() do
+ table.insert(tree[2], self:_gentree(dep))
+ end
+ end
+ return tree
+end
+
+-- tostring
+function jobpool:__tostring()
+ return string.serialize(self:_gentree(self:rootjob()), {indent = 2})
+end
+
+-- new a jobpool
+function new()
+ return jobpool {0, {name = "root"}, {}}
+end
diff --git a/xmake/modules/private/async/runjobs.lua b/xmake/modules/private/async/runjobs.lua
index 46a54e327..ce899bc2e 100644
--- a/xmake/modules/private/async/runjobs.lua
+++ b/xmake/modules/private/async/runjobs.lua
@@ -20,7 +20,6 @@
-- imports
import("core.base.scheduler")
-import("core.base.hashset")
-- print back characters
function _print_backchars(backnum)
@@ -61,7 +60,7 @@ function main(name, jobs, opt)
-- init options
op = opt or {}
- local total = opt.total or (type(jobs) == "table" and #jobs) or 1
+ local total = opt.total or (type(jobs) == "table" and jobs:count()) or 1
local comax = opt.comax or total
local timeout = opt.timeout or 500
local group_name = name
@@ -135,8 +134,9 @@ function main(name, jobs, opt)
-- run jobs
local index = 0
- local priority_prev = -1
- local priority_curr = -1
+ local priority_prev = 0
+ local priority_curr = 0
+ local job_pending = nil
while index < total do
running_jobs_indices = {}
scheduler.co_group_begin(group_name, function (co_group)
@@ -145,27 +145,36 @@ function main(name, jobs, opt)
local jobfunc = jobs_cb
while index < max do
- -- uses jobs queue?
+ -- uses job pool?
+ local jobname
if not jobs_cb then
-- get job priority
- local job = jobs[index + 1]
- priority_curr = job.priority or priority_prev
- assert(priority_curr >= priority_prev, "runjobs: invalid priority(%d < %d)!", priority_curr, priority_prev)
+ local job, priority = job_pending or jobs:popjob()
+ if not job then
+ break
+ end
-- priority changed? we need wait all running jobs exited
+ priority_curr = priority or priority_prev
+ assert(priority_curr >= priority_prev, "runjobs: invalid priority(%d < %d)!", priority_curr, priority_prev)
if priority_curr > priority_prev then
+ job_pending = job
break
end
+ job_pending = nil
-- get run function
jobfunc = job.run
+ jobname = job.name
+ else
+ jobname = tostring(index)
end
-- start this job
index = index + 1
table.insert(running_jobs_indices, index)
- scheduler.co_start_named(name .. '/' .. tostring(index), function(i)
+ scheduler.co_start_named(name .. '/' .. jobname, function(i)
try
{
function()