diff options
author | Zac Medico <zmedico@gentoo.org> | 2009-06-22 16:43:52 +0000 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2009-06-22 16:43:52 +0000 |
commit | d057d91f391981fb0564873c471d550f2f62edf5 (patch) | |
tree | d6cd416fc5e9389806ec98a02ae236c99e876e4b /pym/_emerge/CompositeTask.py | |
parent | 28184c982a0688ed9bc4d82df407d4e400f6318c (diff) | |
download | portage-d057d91f391981fb0564873c471d550f2f62edf5.tar.gz portage-d057d91f391981fb0564873c471d550f2f62edf5.tar.bz2 portage-d057d91f391981fb0564873c471d550f2f62edf5.zip |
Bug #275047 - Split _emerge/__init__.py into smaller pieces. Thanks to
Sebastian Mingramm (few) <s.mingramm@gmx.de> for this patch.
svn path=/main/trunk/; revision=13663
Diffstat (limited to 'pym/_emerge/CompositeTask.py')
-rw-r--r-- | pym/_emerge/CompositeTask.py | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/pym/_emerge/CompositeTask.py b/pym/_emerge/CompositeTask.py new file mode 100644 index 000000000..92a441bab --- /dev/null +++ b/pym/_emerge/CompositeTask.py @@ -0,0 +1,115 @@ +from _emerge.AsynchronousTask import AsynchronousTask +import os +class CompositeTask(AsynchronousTask): + + __slots__ = ("scheduler",) + ("_current_task",) + + def isAlive(self): + return self._current_task is not None + + def cancel(self): + self.cancelled = True + if self._current_task is not None: + self._current_task.cancel() + + def _poll(self): + """ + This does a loop calling self._current_task.poll() + repeatedly as long as the value of self._current_task + keeps changing. It calls poll() a maximum of one time + for a given self._current_task instance. This is useful + since calling poll() on a task can trigger advance to + the next task could eventually lead to the returncode + being set in cases when polling only a single task would + not have the same effect. + """ + + prev = None + while True: + task = self._current_task + if task is None or task is prev: + # don't poll the same task more than once + break + task.poll() + prev = task + + return self.returncode + + def _wait(self): + + prev = None + while True: + task = self._current_task + if task is None: + # don't wait for the same task more than once + break + if task is prev: + # Before the task.wait() method returned, an exit + # listener should have set self._current_task to either + # a different task or None. Something is wrong. + raise AssertionError("self._current_task has not " + \ + "changed since calling wait", self, task) + task.wait() + prev = task + + return self.returncode + + def _assert_current(self, task): + """ + Raises an AssertionError if the given task is not the + same one as self._current_task. This can be useful + for detecting bugs. + """ + if task is not self._current_task: + raise AssertionError("Unrecognized task: %s" % (task,)) + + def _default_exit(self, task): + """ + Calls _assert_current() on the given task and then sets the + composite returncode attribute if task.returncode != os.EX_OK. + If the task failed then self._current_task will be set to None. + Subclasses can use this as a generic task exit callback. + + @rtype: int + @returns: The task.returncode attribute. + """ + self._assert_current(task) + if task.returncode != os.EX_OK: + self.returncode = task.returncode + self._current_task = None + return task.returncode + + def _final_exit(self, task): + """ + Assumes that task is the final task of this composite task. + Calls _default_exit() and sets self.returncode to the task's + returncode and sets self._current_task to None. + """ + self._default_exit(task) + self._current_task = None + self.returncode = task.returncode + return self.returncode + + def _default_final_exit(self, task): + """ + This calls _final_exit() and then wait(). + + Subclasses can use this as a generic final task exit callback. + + """ + self._final_exit(task) + return self.wait() + + def _start_task(self, task, exit_handler): + """ + Register exit handler for the given task, set it + as self._current_task, and call task.start(). + + Subclasses can use this as a generic way to start + a task. + + """ + task.addExitListener(exit_handler) + self._current_task = task + task.start() + |