2
0
mirror of https://gitlab.com/ita1024/waf.git synced 2024-11-25 11:19:52 +01:00

Rework the priority system

- Have Task.weight apply to the current task only
- Do not rely on object addresses to set the build order
- Introduce tg.tg_idx_count to count task generators
- Enable propagating/non-propagating weights through Task.tree_weight/Task.weight
This commit is contained in:
Thomas Nagy 2017-06-15 23:23:48 +02:00
parent 0b5202a88b
commit f49f162817
3 changed files with 40 additions and 17 deletions

View File

@ -228,8 +228,6 @@ class Parallel(object):
elif not self.count:
tasks = next(self.biter)
ready, waiting = self.prio_and_split(tasks)
# We cannot use a priority queue because the implementation
# must be able to handle postponed dependencies
self.outstanding.extend(ready)
self.incomplete.update(waiting)
self.total = self.bld.total()
@ -447,6 +445,11 @@ class Parallel(object):
dependency cycles are found quickly, and builds should be more efficient.
A high priority number means that a task is processed first.
This method can be overridden to disable the priority system::
def prio_and_split(self, tasks):
return tasks, []
:return: A pair of task lists
:rtype: tuple
"""
@ -476,15 +479,17 @@ class Parallel(object):
if n.visited == 0:
n.visited = 1
if n in reverse:
rev = reverse[n]
n.__order = n.priority() + len(rev) + sum(visit(k) for k in rev)
n.prio_order = n.tree_weight + len(rev) + sum(visit(k) for k in rev)
else:
n.__order = n.priority()
n.prio_order = n.tree_weight
n.visited = 2
elif n.visited == 1:
raise Errors.WafError('Dependency cycle found!')
return n.__order
return n.prio_order
for x in tasks:
if x.visited != 0:

View File

@ -153,7 +153,20 @@ class Task(evil):
This may be useful for certain extensions but it can a lot of memory.
"""
__slots__ = ('hasrun', 'generator', 'env', 'inputs', 'outputs', 'dep_nodes', 'run_after', '__order')
weight = 0
"""Optional weight to tune the priority for task instances.
The higher, the earlier. The weight only applies to single task objects."""
tree_weight = 0
"""Optional weight to tune the priority of task instances and whole subtrees.
The higher, the earlier."""
prio_order = 0
"""Priority order set by the scheduler on instances during the build phase.
You most likely do not need to set it.
"""
__slots__ = ('hasrun', 'generator', 'env', 'inputs', 'outputs', 'dep_nodes', 'run_after')
def __init__(self, *k, **kw):
self.hasrun = NOT_RUN
@ -177,16 +190,14 @@ class Task(evil):
self.run_after = set()
"""Set of tasks that must be executed before this one"""
self.__order = 0
def __lt__(self, other):
return self.__order > other.__order or id(self) > id(other)
return self.priority() > other.priority()
def __le__(self, other):
return self.__order >= other.__order or id(self) >= id(other)
return self.priority() >= other.priority()
def __gt__(self, other):
return self.__order < other.__order or id(self) < id(other)
return self.priority() < other.priority()
def __ge__(self, other):
return self.__order <= other.__order or id(self) <= id(other)
return self.priority() <= other.priority()
def get_cwd(self):
"""
@ -222,12 +233,12 @@ class Task(evil):
def priority(self):
"""
The default priority for this task instance
Priority of execution; the higher, the earlier
:return: a numeric value representing the urgency of running this task (the higher, the sooner)
:rtype: int
:return: the priority value
:rtype: a tuple of numeric values
"""
return getattr(self, 'weight', 0)
return (self.weight + self.prio_order, - self.generator.tg_idx_count)
def split_argfile(self, cmd):
"""

View File

@ -76,13 +76,20 @@ class task_gen(object):
self.env = self.bld.env.derive()
self.path = self.bld.path # emulate chdir when reading scripts
# provide a unique id
# Provide a unique index per folder
# This is part of a measure to prevent output file name collisions
try:
self.idx = self.bld.idx[self.path] = self.bld.idx.get(self.path, 0) + 1
except AttributeError:
self.bld.idx = {}
self.idx = self.bld.idx[self.path] = 1
# Record the global task generator count
try:
self.tg_idx_count = self.bld.tg_idx_count = self.bld.tg_idx_count + 1
except AttributeError:
self.tg_idx_count = self.bld.tg_idx_count = 1
for key, val in kw.items():
setattr(self, key, val)