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 ) id 1RvE4Y-0006kF-GT for garchives@archives.gentoo.org; Wed, 08 Feb 2012 20:24:58 +0000 Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 068CBE06D8; Wed, 8 Feb 2012 20:24:50 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by pigeon.gentoo.org (Postfix) with ESMTP id BC2F5E06D8 for ; Wed, 8 Feb 2012 20:24:50 +0000 (UTC) Received: from hornbill.gentoo.org (hornbill.gentoo.org [94.100.119.163]) (using TLSv1 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 015F31B400D for ; Wed, 8 Feb 2012 20:24:50 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by hornbill.gentoo.org (Postfix) with ESMTP id 91A76E5400 for ; Wed, 8 Feb 2012 20:24:47 +0000 (UTC) From: "Zac Medico" To: gentoo-commits@lists.gentoo.org Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Zac Medico" Message-ID: Subject: [gentoo-commits] proj/portage:master commit in: pym/_emerge/ X-VCS-Repository: proj/portage X-VCS-Files: pym/_emerge/PollScheduler.py X-VCS-Directories: pym/_emerge/ X-VCS-Committer: zmedico X-VCS-Committer-Name: Zac Medico X-VCS-Revision: b41e88203cb308eb79f15961a0508b86209e2dfb Date: Wed, 8 Feb 2012 20:24:47 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: quoted-printable X-Archives-Salt: bdda05aa-5116-4392-bbca-d118ff072cf3 X-Archives-Hash: 330d3eb9749ad3fefa14188688bf8db9 commit: b41e88203cb308eb79f15961a0508b86209e2dfb Author: Zac Medico gentoo org> AuthorDate: Wed Feb 8 20:24:22 2012 +0000 Commit: Zac Medico gentoo org> CommitDate: Wed Feb 8 20:24:22 2012 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=3Dproj/portage.git;a= =3Dcommit;h=3Db41e8820 PollScheduler: split out EventLoop base class --- pym/_emerge/PollScheduler.py | 222 ++++++++++++++++++++++--------------= ------ 1 files changed, 116 insertions(+), 106 deletions(-) diff --git a/pym/_emerge/PollScheduler.py b/pym/_emerge/PollScheduler.py index 0e510b3..983bfa9 100644 --- a/pym/_emerge/PollScheduler.py +++ b/pym/_emerge/PollScheduler.py @@ -21,12 +21,8 @@ from _emerge.getloadavg import getloadavg from _emerge.PollConstants import PollConstants from _emerge.PollSelectAdapter import PollSelectAdapter =20 -class PollScheduler(object): =20 - class _sched_iface_class(SlotObject): - __slots__ =3D ("idle_add", "io_add_watch", "iteration", - "output", "register", "schedule", - "source_remove", "timeout_add", "unregister") +class EventLoop(object): =20 class _idle_callback_class(SlotObject): __slots__ =3D ("args", "callback", "source_id") @@ -39,11 +35,6 @@ class PollScheduler(object): "timestamp") =20 def __init__(self): - self._terminated =3D threading.Event() - self._terminated_tasks =3D False - self._max_jobs =3D 1 - self._max_load =3D None - self._jobs =3D 0 self._poll_event_queue =3D [] self._poll_event_handlers =3D {} self._poll_event_handler_ids =3D {} @@ -53,105 +44,11 @@ class PollScheduler(object): self._timeout_handlers =3D {} self._timeout_interval =3D None self._poll_obj =3D create_poll_instance() - self._polling =3D False - self._scheduling =3D False - self._background =3D False - self.sched_iface =3D self._sched_iface_class( - idle_add=3Dself._idle_add, - io_add_watch=3Dself._register, - iteration=3Dself._iteration, - output=3Dself._task_output, - register=3Dself._register, - schedule=3Dself._poll_loop, - source_remove=3Dself._unregister, - timeout_add=3Dself._timeout_add, - unregister=3Dself._unregister) - - def terminate(self): - """ - Schedules asynchronous, graceful termination of the scheduler - at the earliest opportunity. - - This method is thread-safe (and safe for signal handlers). - """ - self._terminated.set() - - def _terminate_tasks(self): - """ - Send signals to terminate all tasks. This is called once - from self._schedule() in the event dispatching thread. This - prevents it from being called while the _schedule_tasks() - implementation is running, in order to avoid potential - interference. All tasks should be cleaned up at the earliest - opportunity, but not necessarily before this method returns. - """ - raise NotImplementedError() - - def _schedule_tasks(self): - """ - This is called from inside the _schedule() method, which - guarantees the following: - - 1) It will not be called recursively. - 2) _terminate_tasks() will not be called while it is running. - 3) The state of the boolean _terminated_tasks variable will - not change while it is running. - - Unless this method is used to perform user interface updates, - or something like that, the first thing it should do is check - the state of _terminated_tasks and if that is True then it - should return False immediately (since there's no need to - schedule anything after _terminate_tasks() has been called). - """ - pass + self._polling =3D False =09 =20 def _schedule(self): - """ - Calls _schedule_tasks() and automatically returns early from - any recursive calls to this method that the _schedule_tasks() - call might trigger. This makes _schedule() safe to call from - inside exit listeners. - """ - if self._scheduling: - return False - self._scheduling =3D True - try: - - if self._terminated.is_set() and \ - not self._terminated_tasks: - self._terminated_tasks =3D True - self._terminate_tasks() - - return self._schedule_tasks() - finally: - self._scheduling =3D False - - def _running_job_count(self): - return self._jobs - - def _can_add_job(self): - if self._terminated_tasks: - return False - - max_jobs =3D self._max_jobs - max_load =3D self._max_load - - if self._max_jobs is not True and \ - self._running_job_count() >=3D self._max_jobs: - return False - - if max_load is not None and \ - (max_jobs is True or max_jobs > 1) and \ - self._running_job_count() >=3D 1: - try: - avg1, avg5, avg15 =3D getloadavg() - except OSError: - return False - - if avg1 >=3D max_load: - return False + pass =20 - return True =20 def _poll(self, timeout=3DNone): if self._polling: @@ -462,6 +359,119 @@ class PollScheduler(object): del self._poll_event_handlers[f] return True =20 +class PollScheduler(EventLoop): + + class _sched_iface_class(SlotObject): + __slots__ =3D ("idle_add", "io_add_watch", "iteration", + "output", "register", "schedule", + "source_remove", "timeout_add", "unregister") + + def __init__(self): + super(PollScheduler, self).__init__() + self._terminated =3D threading.Event() + self._terminated_tasks =3D False + self._max_jobs =3D 1 + self._max_load =3D None + self._jobs =3D 0 + self._scheduling =3D False + self._background =3D False + self.sched_iface =3D self._sched_iface_class( + idle_add=3Dself._idle_add, + io_add_watch=3Dself._register, + iteration=3Dself._iteration, + output=3Dself._task_output, + register=3Dself._register, + schedule=3Dself._poll_loop, + source_remove=3Dself._unregister, + timeout_add=3Dself._timeout_add, + unregister=3Dself._unregister) + + def terminate(self): + """ + Schedules asynchronous, graceful termination of the scheduler + at the earliest opportunity. + + This method is thread-safe (and safe for signal handlers). + """ + self._terminated.set() + + def _terminate_tasks(self): + """ + Send signals to terminate all tasks. This is called once + from self._schedule() in the event dispatching thread. This + prevents it from being called while the _schedule_tasks() + implementation is running, in order to avoid potential + interference. All tasks should be cleaned up at the earliest + opportunity, but not necessarily before this method returns. + """ + raise NotImplementedError() + + def _schedule_tasks(self): + """ + This is called from inside the _schedule() method, which + guarantees the following: + + 1) It will not be called recursively. + 2) _terminate_tasks() will not be called while it is running. + 3) The state of the boolean _terminated_tasks variable will + not change while it is running. + + Unless this method is used to perform user interface updates, + or something like that, the first thing it should do is check + the state of _terminated_tasks and if that is True then it + should return False immediately (since there's no need to + schedule anything after _terminate_tasks() has been called). + """ + pass + + def _schedule(self): + """ + Calls _schedule_tasks() and automatically returns early from + any recursive calls to this method that the _schedule_tasks() + call might trigger. This makes _schedule() safe to call from + inside exit listeners. + """ + if self._scheduling: + return False + self._scheduling =3D True + try: + + if self._terminated.is_set() and \ + not self._terminated_tasks: + self._terminated_tasks =3D True + self._terminate_tasks() + + return self._schedule_tasks() + finally: + self._scheduling =3D False + + def _running_job_count(self): + return self._jobs + + def _can_add_job(self): + if self._terminated_tasks: + return False + + max_jobs =3D self._max_jobs + max_load =3D self._max_load + + if self._max_jobs is not True and \ + self._running_job_count() >=3D self._max_jobs: + return False + + if max_load is not None and \ + (max_jobs is True or max_jobs > 1) and \ + self._running_job_count() >=3D 1: + try: + avg1, avg5, avg15 =3D getloadavg() + except OSError: + return False + + if avg1 >=3D max_load: + return False + + return True + def _task_output(self, msg, log_path=3DNone, background=3DNone, level=3D0, noiselevel=3D-1): """