1 # Copyright 1999-2012 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
5 from _emerge.SlotObject import SlotObject
6 from collections import deque
7 class SequentialTaskQueue(SlotObject):
9 __slots__ = ("max_jobs", "running_tasks") + \
10 ("_dirty", "_scheduling", "_task_queue")
12 def __init__(self, **kwargs):
13 SlotObject.__init__(self, **kwargs)
14 self._task_queue = deque()
15 self.running_tasks = set()
16 if self.max_jobs is None:
21 self._task_queue.append(task)
25 def addFront(self, task):
26 self._task_queue.appendleft(task)
39 # Ignore any recursive schedule() calls triggered via
43 self._scheduling = True
45 task_queue = self._task_queue
46 running_tasks = self.running_tasks
47 max_jobs = self.max_jobs
50 while task_queue and \
51 (max_jobs is True or len(running_tasks) < max_jobs):
52 task = task_queue.popleft()
53 cancelled = getattr(task, "cancelled", None)
55 running_tasks.add(task)
56 task.addExitListener(self._task_exit)
61 self._scheduling = False
65 def _task_exit(self, task):
67 Since we can always rely on exit listeners being called, the set of
68 running tasks is always pruned automatically and there is never any need
71 self.running_tasks.remove(task)
77 self._task_queue.clear()
78 running_tasks = self.running_tasks
80 task = running_tasks.pop()
81 task.removeExitListener(self._task_exit)
86 return bool(self._task_queue or self.running_tasks)
88 if sys.hexversion < 0x3000000:
89 __nonzero__ = __bool__
92 return len(self._task_queue) + len(self.running_tasks)