Re: [gtk-list] thread safe gtk?



Sami Juhani Kallio <samik@eiffel.com> writes:

[ Who maintains the FAQ?  I think this has come up enough that it
should be in there (or the tutorial) somewhere.  The following
response (after some editing) might be worth considering.  If the doc
maintainer's interested, I'd be willing help. ]

> We are considering using GTK in developing commercial software. One
> important issue is multithreaded GUI applications and the only
> reference on the topic I found was at http://www.humanfactor.com/gpk/.

This has come up on the list a few times.  There have been at least a
couple of messages from me on this over the past year or so.  But
here's another one...

We use gtk and threads here for some real-time multi-input vision
work, and it works fine.  There are basically two main approaches.  In
the first, you just make sure that *all* X interactions are handled by
one, and only one, thread.  Any other thread that wants to draw
something has to somehow notify the "X" thread, and let it handle the
actual work.

This wouldn't work for our purposes.  The second approach allows you
to call gtk (or X) functions from any thread, but it requires some
careful synchronization.  The basic idea is that you create an X
protection mutex, and *no one* may make *any* X calls without first
acquiring this mutex.  So if you want to draw a line, you have to say:

  pthread_mutex_lock(my_global_x_guard);
  gdk_draw_line(...);
  pthread_mutex_unlock(my_global_x_guard);

Note that this is a little effort, but it allows you to be potentially
more efficient than a completely thread safe gtk.  *You* get to decide
the granularity of the thread locking.  So you can say:

  pthread_mutex_lock(my_global_x_guard);
  gdk_draw_line(...);
  gdk_draw_line(...);
  gdk_draw_line(...);
  gdk_draw_line(...);
  gdk_draw_line(...);
  pthread_mutex_unlock(my_global_x_guard);

In any case, this mutex locking alone is not enough.  You also have to
make sure that the thread that calls gtk_main is holding the lock when
it calls gtk_main like this:

  pthread_mutex_lock(my_global_x_guard);
  gtk_main();
  pthread_mutex_unlock(my_global_x_guard);
  gtk_exit(_exit_status);

and actually, this isn't strictly correct since you just called
gtk_exit when you weren't holding the guard.  What you really want is
to make sure that the unlock happens here after *all* gtk stuff is
done.  Since gtk_exit doesn't return, you might be able to do this
with a C "atexit()" handler.

Here, we handle it with C++isms:

  THREAD_SPECIFIC(TokenHolder guard(_xprotect));
  gtk_main ();
  gtk_exit(_exit_status);

TokenHolder is a class that locks the mutex it's given (in this case
_xprotect) in its constructor and unlocks it in its destructor.  This
means that whenever gtk_exit gets around to cleaning up this stack
frame (because it calls exit() or whatever) C++ guarantees that the
destructor for guard will fire, releasing _xprotect.

The last thing to worry about is that since you were holding the
global mutex when you entered gtk_main, all callbacks will also be
holding it.  This means that the callback must release it if it's
going to call any other code that might reacquire it.  Otherwise
you'll get deadlock.  Also, you *must* be holding the mutex when you
finally return from the callback.

> I am thinking that why cannot GTK be thread safe by default? Is this
> a stupid idea?

Complexity, overhead, and manpower.  The proportion of threaded
programs is still reasonably small, and getting thread safety right is
both quite difficult and takes valuable time away from the main work
of getting a good graphics library finished.  It would be nice to have
gtk thread safe "out of the box, but that's not practical right now,
and it also might make gtk substantially less efficient if not handled
carefully.

Regardless, it's especially not a priority since relatively good
workarounds exist.

Hope this helps.

-- 
Rob Browning <rlb@cs.utexas.edu>
PGP fingerprint = E8 0E 0D 04 F5 21 A0 94  53 2B 97 F5 D6 4E 39 30



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