diff options
Diffstat (limited to 'portage_with_autodep/pym/_emerge/SequentialTaskQueue.py')
-rw-r--r-- | portage_with_autodep/pym/_emerge/SequentialTaskQueue.py | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/portage_with_autodep/pym/_emerge/SequentialTaskQueue.py b/portage_with_autodep/pym/_emerge/SequentialTaskQueue.py new file mode 100644 index 0000000..c1c98c4 --- /dev/null +++ b/portage_with_autodep/pym/_emerge/SequentialTaskQueue.py @@ -0,0 +1,89 @@ +# Copyright 1999-2009 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +import sys +from _emerge.SlotObject import SlotObject +from collections import deque +class SequentialTaskQueue(SlotObject): + + __slots__ = ("max_jobs", "running_tasks") + \ + ("_dirty", "_scheduling", "_task_queue") + + def __init__(self, **kwargs): + SlotObject.__init__(self, **kwargs) + self._task_queue = deque() + self.running_tasks = set() + if self.max_jobs is None: + self.max_jobs = 1 + self._dirty = True + + def add(self, task): + self._task_queue.append(task) + self._dirty = True + + def addFront(self, task): + self._task_queue.appendleft(task) + self._dirty = True + + def schedule(self): + + if not self._dirty: + return False + + if not self: + return False + + if self._scheduling: + # Ignore any recursive schedule() calls triggered via + # self._task_exit(). + return False + + self._scheduling = True + + task_queue = self._task_queue + running_tasks = self.running_tasks + max_jobs = self.max_jobs + state_changed = False + + while task_queue and \ + (max_jobs is True or len(running_tasks) < max_jobs): + task = task_queue.popleft() + cancelled = getattr(task, "cancelled", None) + if not cancelled: + running_tasks.add(task) + task.addExitListener(self._task_exit) + task.start() + state_changed = True + + self._dirty = False + self._scheduling = False + + return state_changed + + def _task_exit(self, task): + """ + Since we can always rely on exit listeners being called, the set of + running tasks is always pruned automatically and there is never any need + to actively prune it. + """ + self.running_tasks.remove(task) + if self._task_queue: + self._dirty = True + + def clear(self): + self._task_queue.clear() + running_tasks = self.running_tasks + while running_tasks: + task = running_tasks.pop() + task.removeExitListener(self._task_exit) + task.cancel() + self._dirty = False + + def __bool__(self): + return bool(self._task_queue or self.running_tasks) + + if sys.hexversion < 0x3000000: + __nonzero__ = __bool__ + + def __len__(self): + return len(self._task_queue) + len(self.running_tasks) |