Add global_event_loop() and GlibEventLoop.
authorZac Medico <zmedico@gentoo.org>
Thu, 9 Feb 2012 20:04:42 +0000 (12:04 -0800)
committerZac Medico <zmedico@gentoo.org>
Thu, 9 Feb 2012 20:04:42 +0000 (12:04 -0800)
This causes all PollScheduler instances within a given process to share
a singleton EventLoop instance, and also makes it possible to swap in
glib's main loop for all portage event loops in the main process.

pym/_emerge/PollScheduler.py
pym/portage/util/_eventloop/EventLoop.py
pym/portage/util/_eventloop/GlibEventLoop.py [new file with mode: 0644]
pym/portage/util/_eventloop/global_event_loop.py [new file with mode: 0644]

index 165c618d1245feb9e53617e3ba6f2ff0a461d6d5..3b86fa08e572940b022690006b186e11eafd3eaf 100644 (file)
@@ -12,7 +12,7 @@ except ImportError:
 from portage import _encodings
 from portage import _unicode_encode
 from portage.util import writemsg_level
-from portage.util._eventloop.EventLoop import EventLoop
+from portage.util._eventloop.global_event_loop import global_event_loop
 
 from _emerge.SlotObject import SlotObject
 from _emerge.getloadavg import getloadavg
@@ -32,7 +32,7 @@ class PollScheduler(object):
                self._jobs = 0
                self._scheduling = False
                self._background = False
-               self._event_loop = EventLoop()
+               self._event_loop = global_event_loop()
                self.sched_iface = self._sched_iface_class(
                        idle_add=self._event_loop.idle_add,
                        io_add_watch=self._event_loop.io_add_watch,
index 3f4d354455372e572aad2f973fafc553c13f0953..aa78ccd15bd9a12a7cc40ee1315cda53755f4b18 100644 (file)
@@ -13,6 +13,8 @@ from _emerge.PollSelectAdapter import PollSelectAdapter
 
 class EventLoop(object):
 
+       supports_multiprocessing = True
+
        class _idle_callback_class(SlotObject):
                __slots__ = ("args", "callback", "source_id")
 
diff --git a/pym/portage/util/_eventloop/GlibEventLoop.py b/pym/portage/util/_eventloop/GlibEventLoop.py
new file mode 100644 (file)
index 0000000..b35772e
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright 2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import portage
+portage.proxy.lazyimport.lazyimport(globals(),
+       'glib',
+)
+
+class GlibEventLoop(object):
+
+       # TODO: Support multiprocessing by using a separate glib.MainContext
+       # instance for each process.
+       supports_multiprocessing = False
+
+       def __init__(self):
+               self.iteration = glib.main_context_default().iteration
+               self.idle_add = glib.idle_add
+               self.io_add_watch = glib.io_add_watch
+               self.timeout_add = glib.timeout_add
+               self.source_remove = glib.source_remove
diff --git a/pym/portage/util/_eventloop/global_event_loop.py b/pym/portage/util/_eventloop/global_event_loop.py
new file mode 100644 (file)
index 0000000..0f0c53f
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright 2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+import os
+
+from portage.util._eventloop.EventLoop import EventLoop
+
+_default_constructor = EventLoop
+#from portage.util._eventloop.GlibEventLoop \
+#      import GlibEventLoop as _default_constructor
+
+# If _default_constructor doesn't support multiprocessing,
+# then _multiprocessing_constructor is used in subprocesses.
+_multiprocessing_constructor = EventLoop
+
+_MAIN_PID = os.getpid()
+_instances = {}
+
+def global_event_loop():
+       """
+       Get a global EventLoop (or compatible object) instance which
+       belongs exclusively to the current process.
+       """
+
+       pid = os.getpid()
+       instance = _instances.get(pid)
+       if instance is not None:
+               return instance
+
+       constructor = _default_constructor
+       if not constructor.supports_multiprocessing and pid != _MAIN_PID:
+               constructor = _multiprocessing_constructor
+
+       instance = constructor()
+       _instances[pid] = instance
+       return instance