Libraries that can't link with Gdk, yet want to let applications to callback while using Gdk or Gtk+

About

The page about how to use Gdk's lock tries to explain how to use the Gdk lock correctly. It has a section about how do do a library that doesn't depend on Gdk yet can let the application developer callback while using Gtk+ or Gdk subsystems in those callbacks. This, of course, requires the Gdk lock too.

Possible solutions

This is a problem that each such library, at this moment, must solve by itself. Luckily you are not alone. Some existing library projects have solved this problem for their use-cases already:

An interface

For example Tinymail (which is a library for building E-mail applications on mobile and embedded targets) solves this by allowing the application developer to implement a GTypeInterface which carries the name TnyLockable. You have a standard implementation in a libtinymailui-gtk called TnyGtkLockable that implements the lock and unlock methods using gdk_threads_enter and gdk_threads_leave. In the libraries of Tinymail that don't link with gdk, the GTypeInterface's API is used. The application developer can "inject" the TnyGtkLockable implementation on which that API will be used. It goes like this (this is a link to Tinymail's internal documentation) and this (some more specific internal documentation of Tinymail). In simplified pseudo code it looks like this:

This is a bit of a mixture of C and some sort of pseudo higher programming language that looks like Vala, C# or Java (it's not a real example)

MyLibrary.so (depends on only glib):

namespace MyLibrary 
{
   interface ILockable 
   {
     void lock();
     void unlock();
   }

   set_ui_locker (ILockable ui_lock);

   class Something 
   {
      ILockable locker;

      private Bool do_perform (MyCallback callback)
      {
        locker.lock ();
        callback ();
        locker.unlock ();
        return FALSE;
      }

      public void perform_and_callback (MyCallback callback)
      {
          g_idle_add_full (G_PRIOR.., (GSourceFunc) do_perform, 
              (gpointer) callback, do_destroy);
      }
   }
}

MyGtkSpecificLibrary.so (depends on Gtk+ and glib):

namespace MyGtkSpecificLibrary 
{
   class Lockable : ILockable 
   {
     public void lock () {
        gdk_threads_enter ();
     }
     public void unlock () {
        gdk_threads_leave ();
     }
   }
}

MyApplication:

#include <gtk/gtk.h>
#include <my-library.h>
#include <my-gtk-specific-library.h>

int main (int argc, char **argv)
{
   my_library_set_ui_locker (
      my_gtk_specific_library_new_lockable ());
}

Other libraries

Other library authors: Please feel free to add your solutions to this problem. I heard for example Pango had similar such problems. Side note from OwenTaylor: Pango does not have such problems as it has no callbacks. Pango is, however, not thread safe, so you have to use it within the Gdk lock. Future version of Pango will add internal locking so that it can be used from multiple threads, but still there will be no such issues.

Side notes from developers

Side note from OwenTaylor: The simplest way to handle this type of issue is to emit all signals callbacks from the main loop with no locks held and let the application get the Gdk lock if it needs it. The main difficulty is that you can't then emit callbacks in response to an API call made by the application but have to do them async. The only other feasible approach is (I think) what you sketched out above where you provide a way for a single "big lock" to be plugged into your library so that it can get that lock when called out of a main loop source. In general, if you design a library that has a signal/callback structure that looks a lot like GTK+, it turns out to be *very hard* to use fine-grained locking and never hold a lock over a signal/callback to application code. So you end up with a big lock. And since a fundamental "theorem" of this stuff is that you only can have one big lock in an application, that big lock needs to be the Gdk lock.

Attic/NonGdkLibsWithGdkLock (last edited 2013-11-26 21:20:44 by WilliamJonMcCann)