plash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Plash] [DRAFT] [PATCH] plash.comms.event_loop: Add timeout argument to


From: James Ascroft-Leigh
Subject: [Plash] [DRAFT] [PATCH] plash.comms.event_loop: Add timeout argument to once(); Workaround for Gtk global lock issues
Date: Fri, 29 Feb 2008 18:15:13 +0000

There are two changes here:

1. Add a timeout argument to the once() method in
plash.comms.event_loop.EventLoop().

2. Add a workaround for the Gtk global lock to GlibEventLoop to drop the
lock when entering the event loop and reclaim the lock while entering
event handlers, as event handlers can expect to use Gtk and may re-enter
the event loop themselves when performing a synchronous call.  This is
not the ideal solution because it is Gtk specific, while GlibEventLoop
only depended on Glib before (though Glib is wrapped by python-gtk
anyway).

Attached is a tool for testing whether a program is using the Gtk global
lock correctly.

--- plash/comms/event_loop.py   2008/02/07 12:06:51     1.1
+++ plash/comms/event_loop.py   2008/02/07 15:06:02     1.2
@@ -21,6 +21,7 @@
 import sys
 
 import gobject
+import gtk
 

 class ExcepthookProxy(object):
@@ -129,21 +130,25 @@
         # Always re-register the event handler otherwise glib will
         # refuse to re-enter the handler if the callback should happen
         # to start a nested event loop.
-        self.register()
-        relevant_flags = flags & self._flags
-        if relevant_flags != 0:
-            try:
-                self._callback(relevant_flags)
-            except:
-                self._excepthook(*sys.exc_info())
+        gtk.gdk.threads_enter()
+        try:
+            self.register()
+            relevant_flags = flags & self._flags
+            if relevant_flags != 0:
+                try:
+                    self._callback(relevant_flags)
+                except:
+                    self._excepthook(*sys.exc_info())
+                    self.remove_watch()
+            if flags & ERROR_FLAGS != 0:
+                try:
+                    self._error_callback(flags & ERROR_FLAGS)
+                except:
+                    self._excepthook(*sys.exc_info())
                 self.remove_watch()
-        if flags & ERROR_FLAGS != 0:
-            try:
-                self._error_callback(flags & ERROR_FLAGS)
-            except:
-                self._excepthook(*sys.exc_info())
-            self.remove_watch()
-        return False # remove handler
+            return False # remove handler
+        finally:
+            gtk.gdk.threads_leave()
 
     def remove_watch(self):
         if not self.destroyed:
@@ -181,6 +186,9 @@
 assert gobject.IO_HUP == select.POLLHUP
 assert gobject.IO_NVAL == select.POLLNVAL
 
+NEVER_BLOCK_TIMEOUT = 0
+MAY_BLOCK_FOREVER = None
+
 
 class EventLoopBase(object):
 
@@ -255,32 +263,28 @@
             did_something = True
         return did_something
 
-    def _iteration(self, may_block):
+    def _iteration(self, timeout):
         did_something = self._run_call_queue()
-        if may_block:
-            timeout = None
-        else:
-            timeout = 0
         ready = dict(self._poll_fds(self._get_fd_flags(), timeout))
         if len(ready) > 0:
             self._process_ready(ready)
             did_something = True
         return did_something
 
-    def once(self):
-        self._iteration(may_block=True)
+    def once(self, timeout=MAY_BLOCK_FOREVER):
+        self._iteration(timeout)
 
     def once_safely(self):
-        did_something = self._iteration(may_block=False)
+        did_something = self._iteration(NEVER_BLOCK_TIMEOUT)
         assert did_something, self._get_fd_flags()
 
     def run(self):
         while True:
-            self._iteration(may_block=True)
+            self._iteration(MAY_BLOCK_FOREVER)
 
     def run_awhile(self):
         while True:
-            did_something = self._iteration(may_block=False)
+            did_something = self._iteration(NEVER_BLOCK_TIMEOUT)
             if not did_something:
                 break
 
@@ -324,8 +328,12 @@
         self._excepthook.set(func)
 
     def _iteration(self, may_block):
-        did_something =
gobject.main_context_default().iteration(may_block)
-        return did_something
+        gtk.gdk.threads_leave()
+        try:
+            did_something =
gobject.main_context_default().iteration(may_block)
+            return did_something
+        finally:
+            gtk.gdk.threads_enter()
 
     def once(self):
         self._iteration(may_block=True)

-- 
J. W. Ascroft-Leigh
Software Engineer

Cmed Technology Ltd.
Registered in England and Wales No. 3869835
Registered Office and Address for Communication:
Holmwood, Broadlands Business Campus,
Langhurstwood Road, Horsham, RH12 4QP, United Kingdom

T +44 (0)1403 755634
F +44 (0)1403 755051
E address@hidden
W www.cmedresearch.com
__________________________________________________________

Driven by technology. Guided by experience.
__________________________________________________________

Attachment: gtk-lock.tar
Description: Unix tar archive

Attachment: smime.p7s
Description: S/MIME cryptographic signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]