From mboxrd@z Thu Jan  1 00:00:00 1970
Received: from pigeon.gentoo.org ([208.92.234.80] helo=lists.gentoo.org)
	by finch.gentoo.org with esmtp (Exim 4.60)
	(envelope-from <gentoo-commits+bounces-424716-garchives=archives.gentoo.org@lists.gentoo.org>)
	id 1RuuOx-00020y-9R
	for garchives@archives.gentoo.org; Tue, 07 Feb 2012 23:24:43 +0000
Received: from pigeon.gentoo.org (localhost [127.0.0.1])
	by pigeon.gentoo.org (Postfix) with SMTP id 02690E0676;
	Tue,  7 Feb 2012 23:24:35 +0000 (UTC)
Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183])
	by pigeon.gentoo.org (Postfix) with ESMTP id B18A4E0676
	for <gentoo-commits@lists.gentoo.org>; Tue,  7 Feb 2012 23:24:35 +0000 (UTC)
Received: from pelican.gentoo.org (unknown [66.219.59.40])
	(using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by smtp.gentoo.org (Postfix) with ESMTPS id B3AE11B4031
	for <gentoo-commits@lists.gentoo.org>; Tue,  7 Feb 2012 23:24:34 +0000 (UTC)
Received: from localhost.localdomain (localhost [127.0.0.1])
	by pelican.gentoo.org (Postfix) with ESMTP id 153E980043
	for <gentoo-commits@lists.gentoo.org>; Tue,  7 Feb 2012 23:24:34 +0000 (UTC)
From: "Zac Medico" <zmedico@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Content-type: text/plain; charset=UTF-8
Reply-To: gentoo-dev@lists.gentoo.org, "Zac Medico" <zmedico@gentoo.org>
Message-ID: <a3162633773ce5efd3b1cc459df147c93877d953.zmedico@gentoo>
Subject: [gentoo-commits] proj/portage:master commit in: pym/_emerge/
X-VCS-Repository: proj/portage
X-VCS-Files: pym/_emerge/JobStatusDisplay.py pym/_emerge/PollScheduler.py pym/_emerge/Scheduler.py
X-VCS-Directories: pym/_emerge/
X-VCS-Committer: zmedico
X-VCS-Committer-Name: Zac Medico
X-VCS-Revision: a3162633773ce5efd3b1cc459df147c93877d953
Date: Tue,  7 Feb 2012 23:24:34 +0000 (UTC)
Precedence: bulk
List-Post: <mailto:gentoo-commits@lists.gentoo.org>
List-Help: <mailto:gentoo-commits+help@lists.gentoo.org>
List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org>
List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org>
List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org>
X-BeenThere: gentoo-commits@lists.gentoo.org
Content-Transfer-Encoding: quoted-printable
X-Archives-Salt: a1cabd0f-cb9b-47f3-b887-4cd52d4d77e8
X-Archives-Hash: abca670adf928065e91e36bf2519425e

commit:     a3162633773ce5efd3b1cc459df147c93877d953
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Tue Feb  7 19:40:55 2012 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Tue Feb  7 23:23:59 2012 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=3Dproj/portage.git;a=
=3Dcommit;h=3Da3162633

PollScheduler: timeouts regardless of IO events

Now PollScheduler will execute timeouts predictably, even when there
no IO events being generated. This allows the Scheduler's display
updates to be handled via timeout_add.

---
 pym/_emerge/JobStatusDisplay.py |   10 ++++--
 pym/_emerge/PollScheduler.py    |   59 +++++++++++++++++++++++++++++++++=
------
 pym/_emerge/Scheduler.py        |   46 ++----------------------------
 3 files changed, 59 insertions(+), 56 deletions(-)

diff --git a/pym/_emerge/JobStatusDisplay.py b/pym/_emerge/JobStatusDispl=
ay.py
index 877a0c9..d84d1b0 100644
--- a/pym/_emerge/JobStatusDisplay.py
+++ b/pym/_emerge/JobStatusDisplay.py
@@ -209,24 +209,26 @@ class JobStatusDisplay(object):
 	def display(self):
 		"""
 		Display status on stdout, but only if something has
-		changed since the last call.
+		changed since the last call. This always returns True,
+		for continuous scheduling via timeout_add.
 		"""
=20
 		if self.quiet:
-			return
+			return True
=20
 		current_time =3D time.time()
 		time_delta =3D current_time - self._last_display_time
 		if self._displayed and \
 			not self._changed:
 			if not self._isatty:
-				return
+				return True
 			if time_delta < self._min_display_latency:
-				return
+				return True
=20
 		self._last_display_time =3D current_time
 		self._changed =3D False
 		self._display_status()
+		return True
=20
 	def _display_status(self):
 		# Don't use len(self._completed_tasks) here since that also

diff --git a/pym/_emerge/PollScheduler.py b/pym/_emerge/PollScheduler.py
index fd57359..519a370 100644
--- a/pym/_emerge/PollScheduler.py
+++ b/pym/_emerge/PollScheduler.py
@@ -43,6 +43,7 @@ class PollScheduler(object):
 		# Increment id for each new handler.
 		self._event_handler_id =3D 0
 		self._timeout_handlers =3D {}
+		self._timeout_interval =3D None
 		self._poll_obj =3D create_poll_instance()
 		self._polling =3D False
 		self._scheduling =3D False
@@ -142,18 +143,51 @@ class PollScheduler(object):
 		return True
=20
 	def _poll(self, timeout=3DNone):
-		"""
-		All poll() calls pass through here. The poll events
-		are added directly to self._poll_event_queue.
-		In order to avoid endless blocking, this raises
-		StopIteration if timeout is None and there are
-		no file descriptors to poll.
-		"""
 		if self._polling:
 			return
 		self._polling =3D True
 		try:
-			self._do_poll(timeout=3Dtimeout)
+			if self._timeout_interval is None:
+				self._run_timeouts()
+				self._do_poll(timeout=3Dtimeout)
+
+			elif timeout is None:
+				while True:
+					self._run_timeouts()
+					previous_count =3D len(self._poll_event_queue)
+					self._do_poll(timeout=3Dself._timeout_interval)
+					if previous_count !=3D len(self._poll_event_queue):
+						break
+
+			elif timeout <=3D self._timeout_interval:
+				self._run_timeouts()
+				self._do_poll(timeout=3Dtimeout)
+
+			else:
+				remaining_timeout =3D timeout
+				start_time =3D time.time()
+				while True:
+					self._run_timeouts()
+					# _timeout_interval can change each time
+					# _run_timeouts is called
+					min_timeout =3D remaining_timeout
+					if self._timeout_interval is not None and \
+						self._timeout_interval < min_timeout:
+						min_timeout =3D self._timeout_interval
+
+					previous_count =3D len(self._poll_event_queue)
+					self._do_poll(timeout=3Dmin_timeout)
+					if previous_count !=3D len(self._poll_event_queue):
+						break
+					elapsed_time =3D time.time() - start_time
+					if elapsed_time < 0:
+						# The system clock has changed such that start_time
+						# is now in the future, so just assume that the
+						# timeout has already elapsed.
+						break
+					remaining_timeout =3D timeout - 1000 * elapsed_time
+					if remaining_timeout <=3D 0:
+						break
 		finally:
 			self._polling =3D False
=20
@@ -165,7 +199,6 @@ class PollScheduler(object):
 		StopIteration if timeout is None and there are
 		no file descriptors to poll.
 		"""
-		self._run_timeouts()
 		if not self._poll_event_handlers:
 			self._schedule()
 			if timeout is None and \
@@ -273,6 +306,8 @@ class PollScheduler(object):
 			self._timeout_handler_class(
 				interval=3Dinterval, function=3Dfunction, args=3Dargs,
 				source_id=3Dsource_id, timestamp=3Dtime.time())
+		if self._timeout_interval is None or self._timeout_interval < interval=
:
+			self._timeout_interval =3D interval
 		return source_id
=20
 	def _run_timeouts(self):
@@ -320,6 +355,12 @@ class PollScheduler(object):
 		"""
 		timeout_handler =3D self._timeout_handlers.pop(reg_id, None)
 		if timeout_handler is not None:
+			if timeout_handler.interval =3D=3D self._timeout_interval:
+				if self._timeout_handlers:
+					self._timeout_interval =3D \
+						min(x.interval for x in self._timeout_handlers.values())
+				else:
+					self._timeout_interval =3D None
 			return True
 		f =3D self._poll_event_handler_ids.pop(reg_id, None)
 		if f is None:

diff --git a/pym/_emerge/Scheduler.py b/pym/_emerge/Scheduler.py
index 5b56650..e6f3e0e 100644
--- a/pym/_emerge/Scheduler.py
+++ b/pym/_emerge/Scheduler.py
@@ -196,6 +196,8 @@ class Scheduler(PollScheduler):
=20
 		self._status_display =3D JobStatusDisplay(
 			xterm_titles=3D('notitles' not in settings.features))
+		self._timeout_add(self._max_display_latency,
+			self._status_display.display)
 		self._max_load =3D myopts.get("--load-average")
 		max_jobs =3D myopts.get("--jobs")
 		if max_jobs is None:
@@ -352,50 +354,8 @@ class Scheduler(PollScheduler):
 		gc.collect()
=20
 	def _poll(self, timeout=3DNone):
-
 		self._schedule()
-
-		if timeout is None:
-			while True:
-				if not self._poll_event_handlers:
-					self._schedule()
-					if not self._poll_event_handlers:
-						raise StopIteration(
-							"timeout is None and there are no poll() event handlers")
-				previous_count =3D len(self._poll_event_queue)
-				PollScheduler._poll(self, timeout=3Dself._max_display_latency)
-				self._status_display.display()
-				if previous_count !=3D len(self._poll_event_queue):
-					break
-
-		elif timeout <=3D self._max_display_latency:
-			PollScheduler._poll(self, timeout=3Dtimeout)
-			if timeout =3D=3D 0:
-				# The display is updated by _schedule() above, so it would be
-				# redundant to update it here when timeout is 0.
-				pass
-			else:
-				self._status_display.display()
-
-		else:
-			remaining_timeout =3D timeout
-			start_time =3D time.time()
-			while True:
-				previous_count =3D len(self._poll_event_queue)
-				PollScheduler._poll(self,
-					timeout=3Dmin(self._max_display_latency, remaining_timeout))
-				self._status_display.display()
-				if previous_count !=3D len(self._poll_event_queue):
-					break
-				elapsed_time =3D time.time() - start_time
-				if elapsed_time < 0:
-					# The system clock has changed such that start_time
-					# is now in the future, so just assume that the
-					# timeout has already elapsed.
-					break
-				remaining_timeout =3D timeout - 1000 * elapsed_time
-				if remaining_timeout <=3D 0:
-					break
+		PollScheduler._poll(self, timeout=3Dtimeout)
=20
 	def _set_max_jobs(self, max_jobs):
 		self._max_jobs =3D max_jobs