Release the main_loop lock around calls to prepare() and check() so that
[platform/upstream/glib.git] / gmain.c
diff --git a/gmain.c b/gmain.c
index 9da4fa0..312402f 100644 (file)
--- a/gmain.c
+++ b/gmain.c
@@ -400,7 +400,7 @@ g_source_compare (GHook *a,
   return (source_a->priority < source_b->priority) ? -1 : 1;
 }
 
-/* HOLDS: main_loop_lock */
+/* HOLDS: main_loop lock */
 static void
 g_source_destroy_func (GHookList *hook_list,
                       GHook     *hook)
@@ -435,11 +435,14 @@ g_source_add (gint           priority,
   G_LOCK (main_loop);
 
   if (!source_list.is_setup)
-    g_hook_list_init (&source_list, sizeof(GSource));
+    {
+      g_hook_list_init (&source_list, sizeof (GSource));
 
-  source_list.hook_destroy = g_source_destroy_func;
+      source_list.hook_destroy = G_HOOK_DEFERRED_DESTROY;
+      source_list.hook_free = g_source_destroy_func;
+    }
 
-  source = (GSource *)g_hook_alloc (&source_list);
+  source = (GSource*) g_hook_alloc (&source_list);
   source->priority = priority;
   source->source_data = source_data;
   source->hook.func = funcs;
@@ -729,16 +732,27 @@ g_main_iterate (gboolean block,
          continue;
        }
 
-      in_check_or_prepare++;
-      if (hook->flags & G_SOURCE_READY ||
-         ((GSourceFuncs *) hook->func)->prepare (source->source_data,
-                                                 &current_time,
-                                                 &source_timeout))
+      if (!(hook->flags & G_SOURCE_READY))
        {
+         gboolean (*prepare)  (gpointer  source_data, 
+                               GTimeVal *current_time,
+                               gint     *timeout);
+
+         prepare = ((GSourceFuncs *) hook->func)->prepare;
+         in_check_or_prepare++;
+         G_UNLOCK (main_loop);
+
+         if ((*prepare) (source->source_data, &current_time, &source_timeout))
+           hook->flags |= G_SOURCE_READY;
+         
+         G_LOCK (main_loop);
          in_check_or_prepare--;
+       }
+
+      if (hook->flags & G_SOURCE_READY)
+       {
          if (!dispatch)
            {
-             hook->flags |= G_SOURCE_READY;
              g_hook_unref (&source_list, hook);
              G_UNLOCK (main_loop);
 
@@ -746,14 +760,11 @@ g_main_iterate (gboolean block,
            }
          else
            {
-             hook->flags |= G_SOURCE_READY;
              n_ready++;
              current_priority = source->priority;
              timeout = 0;
            }
        }
-      else
-       in_check_or_prepare--;
       
       if (source_timeout >= 0)
        {
@@ -790,12 +801,24 @@ g_main_iterate (gboolean block,
          continue;
        }
 
-      in_check_or_prepare++;
-      if (hook->flags & G_SOURCE_READY ||
-         ((GSourceFuncs *) hook->func)->check (source->source_data,
-                                               &current_time))
+      if (!(hook->flags & G_SOURCE_READY))
        {
+         gboolean (*check) (gpointer  source_data,
+                            GTimeVal *current_time);
+
+         check = ((GSourceFuncs *) hook->func)->check;
+         in_check_or_prepare++;
+         G_UNLOCK (main_loop);
+         
+         if ((*check) (source->source_data, &current_time))
+           hook->flags |= G_SOURCE_READY;
+
+         G_LOCK (main_loop);
          in_check_or_prepare--;
+       }
+
+      if (hook->flags & G_SOURCE_READY)
+       {
          if (dispatch)
            {
              hook->flags &= ~G_SOURCE_READY;
@@ -812,8 +835,6 @@ g_main_iterate (gboolean block,
              return TRUE;
            }
        }
-      else
-       in_check_or_prepare--;
       
       hook = g_hook_next_valid (&source_list, hook, TRUE);
     }
@@ -849,7 +870,7 @@ g_main_iteration (gboolean block)
   if (in_check_or_prepare)
     {
       g_warning ("g_main_iteration(): called recursively from within a source's check() or "
-                "prepare() member, iteration not possible");
+                "prepare() member or from a second thread, iteration not possible");
       return FALSE;
     }
   else
@@ -875,7 +896,7 @@ g_main_run (GMainLoop *loop)
   if (in_check_or_prepare)
     {
       g_warning ("g_main_run(): called recursively from within a source's check() or "
-                "prepare() member, iteration not possible");
+                "prepare() member or from a second thread, iteration not possible");
       return;
     }
 
@@ -1116,7 +1137,7 @@ g_timeout_dispatch (gpointer source_data,
 {
   GTimeoutData *data = source_data;
 
-  if (data->callback(user_data))
+  if (data->callback (user_data))
     {
       guint seconds = data->interval / 1000;
       guint msecs = data->interval - seconds * 1000;