Add a PollScheduler._next_poll_event() method to maintain a central event
authorZac Medico <zmedico@gentoo.org>
Tue, 15 Jul 2008 02:11:39 +0000 (02:11 -0000)
committerZac Medico <zmedico@gentoo.org>
Tue, 15 Jul 2008 02:11:39 +0000 (02:11 -0000)
queue between _poll_loop() and _schedule_wait(). This solves an intermittent
KeyError from _poll_loop() which occured when an event handler called
_schedule_wait() which unregistered an event handler for an event that
_poll_loop() had already recieved but hadn't processed yet.

svn path=/main/trunk/; revision=11051

pym/_emerge/__init__.py

index a2c7b19e7c01961cc2ad8f6b3f5ae9f2113961d6..ef16f477c81feeaaebe9ab9bc9a3bbcc9c8e7302 100644 (file)
@@ -8085,6 +8085,7 @@ class PollScheduler(object):
                self._max_jobs = 1
                self._max_load = None
                self._jobs = 0
+               self._poll_event_queue = []
                self._poll_event_handlers = {}
                self._poll_event_handler_ids = {}
                # Increment id for each new handler.
@@ -8132,19 +8133,29 @@ class PollScheduler(object):
 
                return True
 
+       def _next_poll_event(self):
+               """
+               Since the _schedule_wait() loop is called by event
+               handlers from _poll_loop(), maintain a central event
+               queue for both of them to share events from a single
+               poll() call.
+               """
+               if not self._poll_event_queue:
+                       self._poll_event_queue.extend(self._poll.poll())
+               return self._poll_event_queue.pop()
+
        def _poll_loop(self):
 
                event_handlers = self._poll_event_handlers
-               poll = self._poll.poll
-               state_change = 0
+               event_handled = False
 
                while event_handlers:
-                       for f, event in poll():
-                               handler, reg_id = event_handlers[f]
-                               if not handler(f, event):
-                                       state_change += 1
+                       f, event = self._next_poll_event()
+                       handler, reg_id = event_handlers[f]
+                       handler(f, event)
+                       event_handled = True
 
-               if not state_change:
+               if not event_handled:
                        raise AssertionError("tight loop")
 
        def _register(self, f, eventmask, handler):
@@ -8177,15 +8188,18 @@ class PollScheduler(object):
                """
                event_handlers = self._poll_event_handlers
                handler_ids = self._poll_event_handler_ids
-               poll = self._poll.poll
+               event_handled = False
 
                if isinstance(wait_ids, int):
                        wait_ids = frozenset([wait_ids])
 
                while wait_ids.intersection(handler_ids):
-                       for f, event in poll():
-                               handler, reg_id = event_handlers[f]
-                               handler(f, event)
+                       f, event = self._next_poll_event()
+                       handler, reg_id = event_handlers[f]
+                       handler(f, event)
+                       event_handled = True
+
+               return event_handled
 
 class QueueScheduler(PollScheduler):