Gentoo Logo
Gentoo Spaceship

Installation:
Gentoo Handbook
Installation Docs

Documentation:
Home
Listing
About Gentoo
Philosophy
Social Contract

Resources:
Bug Tracker
Developer List
Discussion Forums
Gentoo BitTorrents
Gentoo Linux Enhancement Proposals
IRC Channels
Mailing Lists
Mirrors
Name and Logo Guidelines
Online Package Database
Security Announcements
Staffing Needs
Supporting Vendors
View our CVS

Graphics:
Logos and themes
Icons
ScreenShots

Miscellaneous Resources:
Gentoo Linux Store
Gentoo-hosted projects
IBM dW/Intel article archive




List Archive: gentoo-commits
Navigation:
Lists: gentoo-commits: < Prev By Thread Next > < Prev By Date Next >
Headers:
To: gentoo-commits@g.o
From: "Zac Medico (zmedico)" <zmedico@g.o>
Subject: portage r10940 - main/trunk/pym/_emerge
Date: Sat, 05 Jul 2008 12:21:44 +0000

 1.1

Author: zmedico
Date: 2008-07-05 12:21:43 +0000 (Sat, 05 Jul 2008)
New Revision: 10940

Modified:
   main/trunk/pym/_emerge/__init__.py
Log:
Add a new CompositeTask class which can be used to combine separate
AsynchronousTask instances into a single instance. The CompositeTask
instance used task exit listeners as a means to (asynchronously) trigger
progression from one subtask to the next. This technique is used to
group together all the ebuild phases executed by EbuildExecuter, and
should be useful for grouping many more sets of tasks into similar
composite tasks.


Modified: main/trunk/pym/_emerge/__init__.py
===================================================================
--- main/trunk/pym/_emerge/__init__.py	2008-07-05 08:52:46 UTC (rev 10939)
+++ main/trunk/pym/_emerge/__init__.py	2008-07-05 12:21:43 UTC (rev 10940)
@@ -1455,7 +1455,7 @@
 		return retval
 
 class AsynchronousTask(SlotObject):
-	__slots__ = ("cancelled", "returncode")
+	__slots__ = ("cancelled", "returncode") + ("_exit_listeners",)
 
 	def start(self):
 		"""
@@ -1470,11 +1470,91 @@
 		return self.returncode
 
 	def wait(self):
+		self._wait_hook()
 		return self.returncode
 
 	def cancel(self):
 		pass
 
+	def addExitListener(self, f):
+		"""
+		The function will be called with one argument, a reference to self.
+		"""
+		if self._exit_listeners is None:
+			self._exit_listeners = []
+		self._exit_listeners.append(f)
+
+	def removeExitListener(self, f):
+		self._exit_listeners.remove(f)
+
+	def _wait_hook(self):
+		"""
+		Call this method before returning from wait. This hook is
+		used to trigger exit listeners when the returncode first
+		becomes available.
+		"""
+		if self._exit_listeners is not None:
+			for f in self._exit_listeners:
+				f(self)
+			self._exit_listeners = None
+
+class CompositeTask(AsynchronousTask):
+	"""
+	A collection of tasks that executes sequentially. Each task
+	must have a _set_returncode() method that can be wrapped as
+	a means to trigger movement from one task to the next.
+	"""
+
+	__slots__ = ("scheduler",) + ("_current_task", "_task_queue")
+
+	def __init__(self, **kwargs):
+		AsynchronousTask.__init__(self, **kwargs)
+		self._task_queue = deque()
+
+	def add(self, task):
+		self._task_queue.append(task)
+
+	def start(self):
+		self._start_next_task()
+
+	def isAlive(self):
+		return self._current_task is not None
+
+	def cancel(self):
+		self._task_queue.clear()
+		self.cancelled = True
+		self._current_task.cancel()
+
+	def wait(self):
+
+		while True:
+			task = self._current_task
+			if task is None:
+				break
+			self.scheduler.schedule(task.reg_id)
+			task.wait()
+
+		self._wait_hook()
+		return self.returncode
+
+	def _start_next_task(self):
+		self._current_task = self._task_queue.popleft()
+		task = self._current_task
+		task.addExitListener(self._task_exit_handler)
+		task.start()
+
+	def _task_exit_handler(self, task):
+		if task is not self._current_task:
+			raise AssertionError("Unrecognized task: %s" % (task,))
+
+		if self._task_queue and \
+			task.returncode == os.EX_OK:
+			self._start_next_task()
+			return
+
+		self._current_task = None
+		self.returncode = task.returncode
+
 class SubProcess(AsynchronousTask):
 	__slots__ = ("pid",)
 
@@ -1503,6 +1583,7 @@
 		if self.returncode is not None:
 			return self.returncode
 		self._set_returncode(os.waitpid(self.pid, 0))
+		self._wait_hook()
 		return self.returncode
 
 	def _set_returncode(self, wait_retval):
@@ -1899,19 +1980,17 @@
 			2 : sys.stderr.fileno(),
 		}
 
-		for mydo in self._phases:
-			ebuild_phase = EbuildPhase(fd_pipes=fd_pipes,
-				pkg=self.pkg, phase=mydo, scheduler=self.scheduler,
-				settings=settings, tree=tree)
+		composite_task = CompositeTask(scheduler=scheduler)
 
-			ebuild_phase.start()
-			self.scheduler.schedule(ebuild_phase.reg_id)
-			retval = ebuild_phase.wait()
+		for phase in self._phases:
+			composite_task.add(EbuildPhase(fd_pipes=fd_pipes,
+				pkg=self.pkg, phase=phase, scheduler=self.scheduler,
+				settings=settings, tree=tree))
 
-			if retval != os.EX_OK:
-				return retval
+		composite_task.start()
+		retval = composite_task.wait()
 
-		return os.EX_OK
+		return retval
 
 class EbuildPhase(SubProcess):
 

-- 
gentoo-commits@g.o mailing list


Navigation:
Lists: gentoo-commits: < Prev By Thread Next > < Prev By Date Next >
Previous by thread:
gentoo-x86 commit in media-sound/gnomad: gnomad-2.8.1.ebuild
Next by thread:
gentoo-x86 commit in media-libs/libmtp: ChangeLog libmtp-0.3.0.ebuild
Previous by date:
gentoo-x86 commit in net-im/pidgin: ChangeLog pidgin-2.4.3.ebuild
Next by date:
gentoo-x86 commit in media-libs/libmtp: ChangeLog libmtp-0.3.0.ebuild


Aug 29, 2008

Donate to support our development efforts.

Gentoo Centric Hosting: vr.org

VR Hosted

Tek Alchemy

Tek Alchemy

SevenL.net

SevenL.net

php|architect

php|architect

Copyright 2001-2007 Gentoo Foundation, Inc. Questions, Comments? Email www@gentoo.org.