From 15a5d41a961628db7e7e3f9a8b8214ea3111a880 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Thu, 10 Jul 2008 03:40:39 +0000 Subject: * Fix AsynchronousTask._wait_hook() to prevent potential recursive calls triggered when calling exit listeners. * Make SequentialTaskQueue use exit listeners to trigger scheduling as soon as a task exits. This makes it possible for the queues to automatically schedule new tasks while scheduler remains in it's poll() loop. svn path=/main/trunk/; revision=11008 --- pym/_emerge/__init__.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'pym/_emerge/__init__.py') diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index a1a3d6fe7..163e606a7 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -1545,7 +1545,14 @@ class AsynchronousTask(SlotObject): """ if self.returncode is not None and \ self._exit_listeners is not None: - for f in self._exit_listeners: + + # This prevents recursion, in case one of the + # exit handlers triggers this method again by + # calling wait(). + exit_listeners = self._exit_listeners + self._exit_listeners = None + + for f in exit_listeners: f(self) self._exit_listeners = None @@ -7604,7 +7611,7 @@ class PollSelectAdapter(PollConstants): class SequentialTaskQueue(SlotObject): - __slots__ = ("max_jobs", "running_tasks", "_task_queue") + __slots__ = ("max_jobs", "running_tasks", "_task_queue", "_scheduling") def __init__(self, **kwargs): SlotObject.__init__(self, **kwargs) @@ -7624,6 +7631,13 @@ class SequentialTaskQueue(SlotObject): 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 @@ -7640,12 +7654,18 @@ class SequentialTaskQueue(SlotObject): task = task_queue.popleft() cancelled = getattr(task, "cancelled", None) if not cancelled: + task.addExitListener(self._task_exit) task.start() running_tasks.add(task) state_changed = True + self._scheduling = False + return state_changed + def _task_exit(self, task): + self.schedule() + def clear(self): self._task_queue.clear() running_tasks = self.running_tasks -- cgit v1.2.3-1-g7c22