gobject.idle_add, timeout_add gdk-thread-safe?

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

gobject.idle_add, timeout_add gdk-thread-safe?

Dan-4
Hi,

I can't find any documentation(*) stating positively whether
gobject.idle_add and timeout_add are safe to call from a non-main
thread (e.g. a gstreamer message callback). Specifically,

def work(*args):
  # (1) gtk.gdk.threads_enter() ??
  self.ui.change_some_label()
  # (2) gtk.gdk.threads_leave() ??

# (3) gtk.gdk.threads_enter() ??
gobject.idle_add (work)
# (4) gtk.gdk.threads_leave() ??

Are (1)/(2) and/or (3)/(4) necessary? And for which pygtk versions
does this apply? I am targetting separately 2.12 (on an embedded
platform) and 2.24 (on the desktop).


(*) Except https://developer.gnome.org/gdk/unstable/gdk-Threads.html
which seems to be from 1999 and implies that __for gtk, not pygtk__
the g_idle_add requires both (1)/(2) and (3)/(4). I can't actually
find any recent GTK+ documentation that unambiguously resolves the
issue.

Thanks,
Dan
_______________________________________________
pygtk mailing list   [hidden email]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/
Reply | Threaded
Open this post in threaded view
|

Re: gobject.idle_add, timeout_add gdk-thread-safe?

Tim Evans-2
On 2013-11-30 00:38, Dan wrote:

> Hi,
>
> I can't find any documentation(*) stating positively whether
> gobject.idle_add and timeout_add are safe to call from a non-main
> thread (e.g. a gstreamer message callback). Specifically,
>
> def work(*args):
>    # (1) gtk.gdk.threads_enter() ??
>    self.ui.change_some_label()
>    # (2) gtk.gdk.threads_leave() ??
>
> # (3) gtk.gdk.threads_enter() ??
> gobject.idle_add (work)
> # (4) gtk.gdk.threads_leave() ??
>
> Are (1)/(2) and/or (3)/(4) necessary? And for which pygtk versions
> does this apply? I am targetting separately 2.12 (on an embedded
> platform) and 2.24 (on the desktop).
>
>
> (*) Except https://developer.gnome.org/gdk/unstable/gdk-Threads.html
> which seems to be from 1999 and implies that __for gtk, not pygtk__
> the g_idle_add requires both (1)/(2) and (3)/(4). I can't actually
> find any recent GTK+ documentation that unambiguously resolves the
> issue.

Both idle_add and timeout_add are thread safe, as are all GLib mainloop
functions AFAIK. It's the GTK and GDK functions you have to be careful
with. You don't need (3)/(4). You should still have (1)/(2), or "with
gtk.gdk.lock:" if your version of gtk is new enough. It may be easier to
create your own wrappers around idle_add and timeout_add like this:

   def _callback_wrapper(func, *args, **kw):
       gtk.gdk.threads_enter()
       try:
           return func(*args, **kw)
       finally:
           gtk.gdk.threads_leave()

   def idle_add_lock(func, *args, **kw):
       return gobject.idle_add(_callback_wrapper, func, *args, **kw)

   def timeout_add_lock(milliseconds, func, *args, **kw):
       return gobject.timeout_add(milliseconds,
                                  _callback_wrapper, func, *args, **kw)

--
Tim Evans
_______________________________________________
pygtk mailing list   [hidden email]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/
Reply | Threaded
Open this post in threaded view
|

Re: gobject.idle_add, timeout_add gdk-thread-safe?

Hrvoje Niksic-2
On 12/01/2013 10:19 PM, Tim Evans wrote:
> It's the GTK and GDK functions you have to be careful
> with. You don't need (3)/(4). You should still have (1)/(2),

Why? I thought the whole point of using g_idle_add from the other thread
is to have the callbacks invoked in the GUI thread (the thread that runs
the GTK main loop). If the GTK API is only ever accessed from a single
thread, then no locking should be necessary.

_______________________________________________
pygtk mailing list   [hidden email]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/
Reply | Threaded
Open this post in threaded view
|

Re: gobject.idle_add, timeout_add gdk-thread-safe?

Dan-4
In reply to this post by Tim Evans-2
Hi Tim, thanks for your reply.

> Both idle_add and timeout_add are thread safe, as are all GLib mainloop
> functions AFAIK. It's the GTK and GDK functions you have to be careful
> with. You don't need (3)/(4). You should still have (1)/(2), or "with
> gtk.gdk.lock:" if your version of gtk is new enough. It may be easier to

That's great; too bad this essential bit of info is missing from the
pygtk docs (at least the online one).

Also, related to Hrvoje Niksic's comment, is it safe to use GDK calls
from other threads at all (as long as you guard them with the
appropriate incantations)? Or do you absolutely have to schedule all
GUI work to the GUI thread? If the latter, then I also don't see the
point of locking in the callback.
_______________________________________________
pygtk mailing list   [hidden email]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://faq.pygtk.org/
Reply | Threaded
Open this post in threaded view
|

Re: gobject.idle_add, timeout_add gdk-thread-safe?

Hrvoje Niksic-2
On 12/02/2013 09:50 AM, Dan wrote:
> Also, related to Hrvoje Niksic's comment, is it safe to use GDK calls
> from other threads at all (as long as you guard them with the
> appropriate incantations)? Or do you absolutely have to schedule all
> GUI work to the GUI thread?

According to https://developer.gnome.org/gdk3/stable/gdk3-Threads.html,
GDK calls from other threads are unsafe in non-X11 backends, even with
locks around the calls. When using the X11 backend, the documentation
warns that combining the GDK lock with other locks, such as Python's
"GIL" can be complicated, and that such locking is deprecated in GTK 3.

Judging by the documentation, it seems best to keep GDK calls to a
single thread, unless you only use X11 and really know what you are doing.

> If the latter, then I also don't see the
> point of locking in the callback.

Ah, so the point of locking in the callback would be to prevent a race
condition between the GUI thread calling into GTK and other threads
doing the same?

But in that case, requirement for g_idle_add callbacks locking stands
for *all* calls to g_idle_add in the application (including those
performed by GTK itself, if any), not only those coming from another
thread. After all, whichever thread g_idle_add is called from, the
callback will end up running in the same thread, the GUI thread that
runs the main loop.

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