> 
> It has nothing to do with short or long but with interactivity with
> other threads. Like a thread that can be canceled by clicking a
> button.
> 
> Take the following kind of code:
> 
>   class Buzy(Threading):
> 
>     def run(self):
>       while not self.is_canceled:
>         calculate_step()
>         gtk.gdk.threads_enter()
>         show_incremental_result()
>         gtk.gdk.threads_leave()
> 
>     def cancel(self):
>       self.is_canceled = True
> 
>   buzy = Buzy()
> 
>   def On_Click():
>     buzy.cancel()
>     buzy.join()
> 
> 
> Not look at the following scenario. buzy is calculating a step.
> The user cancels the thread, so gtk acquires the lock and calls
> On_Click which calls buzy.cancel. buzy wants to acquire the lock
> but is blocked. gtk wants to join buzy and is blocked too: Deadlock.
> 
> In order to solve this I have to write On_Click as follows:
> 
>   def On_Click():
>     gtk.gdk.threads_leave()
>     buzy.cancel()
>     buzy.join()
>     gtk.gdk.threads_enter()
> 
> 
> So here we have a litle event handler that doesn't the lock, but
> that gets in anyway and not releasing the lock will cause a deadlock.

I see your point in this case, but writing it in this way is going to
cause you even more problems if you try to make it cross platform, ie
if you want to make it work on Windows.  This is neither a deficency
of Windows nor of GTK, just a by product of how Windows deals with
events in different threads and the way that X deals with events. (BTW
I know for sure this is a problem with wxWidgets as well, and I would
suspect that the same is true for Qt)

In this case I would be updating the UI from one thread.  It means
that you have to push some data over to the UI thread, but you do get
rid of all of your nasty threads_enter, threads_leave conditions.

In the case above I would define run something like:
    def run(self):
     while not self.is_canceled:
       calculate_step()
       data = collect_data_for_ui()
       gtk.gdk.threads_enter()
       gobject.idle_add(update_ui, data)
       gtk.gdk.threads_leave()

    def update_ui(data):
         #perform ui updating here
         
         return False

Apparently you do not need the threads_enter/threads_leave pair around
the idle_add call.  I always put it in because it has never broken
anything and I don't want to mess with success.

I personally think it is a clean separation to have UI code in one
thread and processing code in another and would do things like that on
Unix even if I was never intending to port the app to Windows.

-Chris

-- 
Christopher Lambacher
[EMAIL PROTECTED]
_______________________________________________
pygtk mailing list   pygtk@daa.com.au
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to