On Feb 20, 2011, at 10:09 PM, Robert Schroll wrote:

> On 02/20/2011 03:08 PM, Stephen Langer wrote:
>> This is what we do:
>> 
>> class IdleBlockCallback:
>>      def __init__(self, func, args=(), kwargs={}):
>>           self.func = func
>>           self.args = args
>>           self.kwargs = kwargs
>>           self.event = threading.Event()
>>           self.result = None
>>      def __call__(self):
>>           gtk.gdk.threads_enter()
>>           try:
>>                self.result = self.func(*self.args, **self.kwargs)
>>           finally:
>>                gtk.gdk.flush()
>>                gtk.gdk.threads_leave()
>>                self.event.set()
>>           return False              # don't repeat
>> 
>> def runBlock(func, args=(), kwargs={}):
>>      callbackobj = OOFIdleBlockCallback(func, args, kwargs)
>>      callbackobj.event.clear()
>>      gobject.idle_add(callbackobj, priority=gobject.PRIORITY_LOW)
>>      callbackobj.event.wait()
>>      return callbackobj.result
>> 
> 
> Thank you, thank you, thank you - this is exactly what I was looking 
> for.  For some reason, I didn't think to look in Python's threading 
> module.  Two questions:
> 
> 1) Since all GTK stuff is happening in the mainloop thread, I'm only 
> calling gobject.threads_init(), not gtk.gdk.threads_init() (as suggested 
> here: http://library.gnome.org/devel/gtk-faq/stable/x499.html)  Am I 
> correct in understanding that I don't need to call 
> gtk.gdk.threads_enter() and _leave() in the callback?  (I've taken them 
> out, and nothing seemed to break.)

My impression is that they're required within idle callbacks.

>  What about the flush()?

It's probably to prevent race conditions in our code, but I don't remember the 
specific reason.

> 2) I'd like to use this code in a project to be released under the BSD 
> license.  Is that okay with you?

Sure.  It's from the NIST OOF project, http://www.ctcms.nist.gov/oof/oof2, 
which is not copyrighted.  


> 
>> Call runBlock on the worker thread.  Be sure that you're really on the 
>> worker thread, because if you call it on the main thread it will hang.
> 
> If I understand things correctly (unlikely), gobject.main_depth() will 
> be greater than zero in the main loop thread and zero in the worker 
> threads.  (At least if I only start the main loop in one thread.)  So 
> I've written this function to ensure code is called in the main loop. 
> Limited testing suggests it's working.
> 
> def run_in_main_loop(func, *args, **kwargs):
>     if gobject.main_depth():
>         # In the main loop already
>         return func(*args, **kwargs)
>     callbackobj = IdleBlockCallback(func, args, kwargs)
>     callbackobj.event.clear()
>     gobject.idle_add(callbackobj, priority=gobject.PRIORITY_LOW)
>     callbackobj.event.wait()
>     return callbackobj.result

I haven't used main_depth.  We do a similar thing with a different mechanism.  
Each thread has a unique id which can be compared to the main thread's id to 
see if the function is being called by the main thread.

 -- Steve

--
-- stephen.lan...@nist.gov                    Tel: (301) 975-5423 --
-- http://math.nist.gov/mcsd/Staff/SLanger/   Fax: (301) 975-3553 --
-- NIST, 100 Bureau Drive, Stop 8910, Gaithersburg, Md 20899-8910 --

-- "I don't think this will work.  That's why it's science."      --
--                     Naomi Langer (age 6),  17 Feb 2003         --





_______________________________________________
pygtk mailing list   pygtk@daa.com.au
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/

Reply via email to