Use the atomic integer operations for GMainContext and GMainLoop reference
authorSebastian Wilhelmi <seppi@seppi.de>
Thu, 4 Mar 2004 10:12:55 +0000 (10:12 +0000)
committerSebastian Wilhelmi <wilhelmi@src.gnome.org>
Thu, 4 Mar 2004 10:12:55 +0000 (10:12 +0000)
2004-03-04  Sebastian Wilhelmi  <seppi@seppi.de>

* glib/gmain.c: Use the atomic integer operations for GMainContext
and GMainLoop reference counting.

* glib/gmain.c: Hold the main_context_list lock, when iterating
the list. Only call g_main_context_wakeup for positive reference
count.

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
glib/gmain.c

index 3bc409aa466d75b42202909421b4e3d819e7f64d..8e530d70343de146cd25d1a44b3bbddc0cefad27 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2004-03-04  Sebastian Wilhelmi  <seppi@seppi.de>
+
+       * glib/gmain.c: Use the atomic integer operations for GMainContext
+       and GMainLoop reference counting.
+
+       * glib/gmain.c: Hold the main_context_list lock, when iterating
+       the list. Only call g_main_context_wakeup for positive reference
+       count.
+
 2004-03-03  Tor Lillqvist  <tml@iki.fi>
 
        * glibconfig.h.win32.in: Update to match a configure-generated
index 3bc409aa466d75b42202909421b4e3d819e7f64d..8e530d70343de146cd25d1a44b3bbddc0cefad27 100644 (file)
@@ -1,3 +1,12 @@
+2004-03-04  Sebastian Wilhelmi  <seppi@seppi.de>
+
+       * glib/gmain.c: Use the atomic integer operations for GMainContext
+       and GMainLoop reference counting.
+
+       * glib/gmain.c: Hold the main_context_list lock, when iterating
+       the list. Only call g_main_context_wakeup for positive reference
+       count.
+
 2004-03-03  Tor Lillqvist  <tml@iki.fi>
 
        * glibconfig.h.win32.in: Update to match a configure-generated
index 3bc409aa466d75b42202909421b4e3d819e7f64d..8e530d70343de146cd25d1a44b3bbddc0cefad27 100644 (file)
@@ -1,3 +1,12 @@
+2004-03-04  Sebastian Wilhelmi  <seppi@seppi.de>
+
+       * glib/gmain.c: Use the atomic integer operations for GMainContext
+       and GMainLoop reference counting.
+
+       * glib/gmain.c: Hold the main_context_list lock, when iterating
+       the list. Only call g_main_context_wakeup for positive reference
+       count.
+
 2004-03-03  Tor Lillqvist  <tml@iki.fi>
 
        * glibconfig.h.win32.in: Update to match a configure-generated
index 3bc409aa466d75b42202909421b4e3d819e7f64d..8e530d70343de146cd25d1a44b3bbddc0cefad27 100644 (file)
@@ -1,3 +1,12 @@
+2004-03-04  Sebastian Wilhelmi  <seppi@seppi.de>
+
+       * glib/gmain.c: Use the atomic integer operations for GMainContext
+       and GMainLoop reference counting.
+
+       * glib/gmain.c: Hold the main_context_list lock, when iterating
+       the list. Only call g_main_context_wakeup for positive reference
+       count.
+
 2004-03-03  Tor Lillqvist  <tml@iki.fi>
 
        * glibconfig.h.win32.in: Update to match a configure-generated
index 3bc409aa466d75b42202909421b4e3d819e7f64d..8e530d70343de146cd25d1a44b3bbddc0cefad27 100644 (file)
@@ -1,3 +1,12 @@
+2004-03-04  Sebastian Wilhelmi  <seppi@seppi.de>
+
+       * glib/gmain.c: Use the atomic integer operations for GMainContext
+       and GMainLoop reference counting.
+
+       * glib/gmain.c: Hold the main_context_list lock, when iterating
+       the list. Only call g_main_context_wakeup for positive reference
+       count.
+
 2004-03-03  Tor Lillqvist  <tml@iki.fi>
 
        * glibconfig.h.win32.in: Update to match a configure-generated
index 3bc409aa466d75b42202909421b4e3d819e7f64d..8e530d70343de146cd25d1a44b3bbddc0cefad27 100644 (file)
@@ -1,3 +1,12 @@
+2004-03-04  Sebastian Wilhelmi  <seppi@seppi.de>
+
+       * glib/gmain.c: Use the atomic integer operations for GMainContext
+       and GMainLoop reference counting.
+
+       * glib/gmain.c: Hold the main_context_list lock, when iterating
+       the list. Only call g_main_context_wakeup for positive reference
+       count.
+
 2004-03-03  Tor Lillqvist  <tml@iki.fi>
 
        * glibconfig.h.win32.in: Update to match a configure-generated
index c5b18033020cbeeac04a9ad21911078f5dbe49e1..ea1f9f47c36e686866e68803e7606c9f012016be 100644 (file)
@@ -103,7 +103,7 @@ struct _GMainContext
   GSList *waiters;
 #endif  
 
-  guint ref_count;
+  gint ref_count;
 
   GPtrArray *pending_dispatches;
   gint timeout;                        /* Timeout for current iteration */
@@ -153,7 +153,7 @@ struct _GMainLoop
 {
   GMainContext *context;
   gboolean is_running;
-  guint ref_count;
+  gint ref_count;
 };
 
 struct _GTimeoutSource
@@ -171,8 +171,8 @@ struct _GChildWatchSource
 #ifdef G_OS_WIN32
   GPollFD     poll;
 #else /* G_OS_WIN32 */
-   gint        count;
-   gboolean    child_exited;
+  gint        count;
+  gboolean    child_exited;
 #endif /* G_OS_WIN32 */
 };
 
@@ -589,13 +589,9 @@ void
 g_main_context_ref (GMainContext *context)
 {
   g_return_if_fail (context != NULL);
-  g_return_if_fail (context->ref_count > 0); 
-
-  LOCK_CONTEXT (context);
-  
-  context->ref_count++;
+  g_return_if_fail (g_atomic_int_get (&context->ref_count) > 0); 
 
-  UNLOCK_CONTEXT (context);
+  g_atomic_int_inc (&context->ref_count);
 }
 
 /* If DISABLE_MEM_POOLS is defined, then freeing the
@@ -618,18 +614,22 @@ poll_rec_list_free (GMainContext *context,
 }
 #endif /* DISABLE_MEM_POOLS */
 
-static void
-g_main_context_unref_and_unlock (GMainContext *context)
+/**
+ * g_main_context_unref:
+ * @context: a #GMainContext
+ * 
+ * Decreases the reference count on a #GMainContext object by one. If
+ * the result is zero, free the context and free all associated memory.
+ **/
+void
+g_main_context_unref (GMainContext *context)
 {
   GSource *source;
+  g_return_if_fail (context != NULL);
+  g_return_if_fail (g_atomic_int_get (&context->ref_count) > 0); 
 
-  context->ref_count--;
-
-  if (context->ref_count != 0)
-    {
-      UNLOCK_CONTEXT (context);
-      return;
-    }
+  if (!g_atomic_int_dec_and_test (&context->ref_count))
+    return;
 
   G_LOCK (main_context_list);
   main_context_list = g_slist_remove (main_context_list, context);
@@ -642,7 +642,6 @@ g_main_context_unref_and_unlock (GMainContext *context)
       g_source_destroy_internal (source, context, TRUE);
       source = next;
     }
-  UNLOCK_CONTEXT (context);
 
 #ifdef G_THREADS_ENABLED  
   g_static_mutex_free (&context->mutex);
@@ -677,23 +676,6 @@ g_main_context_unref_and_unlock (GMainContext *context)
   g_free (context);
 }
 
-/**
- * g_main_context_unref:
- * @context: a #GMainContext
- * 
- * Decreases the reference count on a #GMainContext object by one. If
- * the result is zero, free the context and free all associated memory.
- **/
-void
-g_main_context_unref (GMainContext *context)
-{
-  g_return_if_fail (context != NULL);
-  g_return_if_fail (context->ref_count > 0); 
-
-  LOCK_CONTEXT (context);
-  g_main_context_unref_and_unlock (context);
-}
-
 #ifdef G_THREADS_ENABLED
 static void 
 g_main_context_init_pipe (GMainContext *context)
@@ -2636,31 +2618,13 @@ GMainLoop *
 g_main_loop_ref (GMainLoop *loop)
 {
   g_return_val_if_fail (loop != NULL, NULL);
-  g_return_val_if_fail (loop->ref_count > 0, NULL);
+  g_return_val_if_fail (g_atomic_int_get (&loop->ref_count) > 0, NULL);
 
-  LOCK_CONTEXT (loop->context);
-  loop->ref_count++;
-  UNLOCK_CONTEXT (loop->context);
+  g_atomic_int_inc (&loop->ref_count);
 
   return loop;
 }
 
-static void
-g_main_loop_unref_and_unlock (GMainLoop *loop)
-{
-  loop->ref_count--;
-  if (loop->ref_count == 0)
-    {
-      /* When the ref_count is 0, there can be nobody else using the
-       * loop, so it is safe to unlock before destroying.
-       */
-      g_main_context_unref_and_unlock (loop->context);
-  g_free (loop);
-    }
-  else
-    UNLOCK_CONTEXT (loop->context);
-}
-
 /**
  * g_main_loop_unref:
  * @loop: a #GMainLoop
@@ -2672,11 +2636,13 @@ void
 g_main_loop_unref (GMainLoop *loop)
 {
   g_return_if_fail (loop != NULL);
-  g_return_if_fail (loop->ref_count > 0);
+  g_return_if_fail (g_atomic_int_get (&loop->ref_count) > 0);
 
-  LOCK_CONTEXT (loop->context);
-  
-  g_main_loop_unref_and_unlock (loop);
+  if (!g_atomic_int_dec_and_test (&loop->ref_count))
+    return;
+
+  g_main_context_unref (loop->context);
+  g_free (loop);
 }
 
 /**
@@ -2694,7 +2660,7 @@ g_main_loop_run (GMainLoop *loop)
   GThread *self = G_THREAD_SELF;
 
   g_return_if_fail (loop != NULL);
-  g_return_if_fail (loop->ref_count > 0);
+  g_return_if_fail (g_atomic_int_get (&loop->ref_count) > 0);
 
 #ifdef G_THREADS_ENABLED
   if (!g_main_context_acquire (loop->context))
@@ -2711,7 +2677,7 @@ g_main_loop_run (GMainLoop *loop)
       
       LOCK_CONTEXT (loop->context);
 
-      loop->ref_count++;
+      g_atomic_int_inc (&loop->ref_count);
 
       if (!loop->is_running)
        loop->is_running = TRUE;
@@ -2746,7 +2712,7 @@ g_main_loop_run (GMainLoop *loop)
       return;
     }
 
-  loop->ref_count++;
+  g_atomic_int_inc (&loop->ref_count);
   loop->is_running = TRUE;
   while (loop->is_running)
     g_main_context_iterate (loop->context, TRUE, TRUE, self);
@@ -2771,7 +2737,7 @@ void
 g_main_loop_quit (GMainLoop *loop)
 {
   g_return_if_fail (loop != NULL);
-  g_return_if_fail (loop->ref_count > 0);
+  g_return_if_fail (g_atomic_int_get (&loop->ref_count) > 0);
 
   LOCK_CONTEXT (loop->context);
   loop->is_running = FALSE;
@@ -2797,7 +2763,7 @@ gboolean
 g_main_loop_is_running (GMainLoop *loop)
 {
   g_return_val_if_fail (loop != NULL, FALSE);
-  g_return_val_if_fail (loop->ref_count > 0, FALSE);
+  g_return_val_if_fail (g_atomic_int_get (&loop->ref_count) > 0, FALSE);
 
   return loop->is_running;
 }
@@ -2814,7 +2780,7 @@ GMainContext *
 g_main_loop_get_context (GMainLoop *loop)
 {
   g_return_val_if_fail (loop != NULL, NULL);
-  g_return_val_if_fail (loop->ref_count > 0, NULL);
+  g_return_val_if_fail (g_atomic_int_get (&loop->ref_count) > 0, NULL);
  
   return loop->context;
 }
@@ -2920,7 +2886,7 @@ g_main_context_add_poll (GMainContext *context,
   if (!context)
     context = g_main_context_default ();
   
-  g_return_if_fail (context->ref_count > 0);
+  g_return_if_fail (g_atomic_int_get (&context->ref_count) > 0);
   g_return_if_fail (fd);
 
   LOCK_CONTEXT (context);
@@ -2992,7 +2958,7 @@ g_main_context_remove_poll (GMainContext *context,
   if (!context)
     context = g_main_context_default ();
   
-  g_return_if_fail (context->ref_count > 0);
+  g_return_if_fail (g_atomic_int_get (&context->ref_count) > 0);
   g_return_if_fail (fd);
 
   LOCK_CONTEXT (context);
@@ -3094,7 +3060,7 @@ g_main_context_set_poll_func (GMainContext *context,
   if (!context)
     context = g_main_context_default ();
   
-  g_return_if_fail (context->ref_count > 0);
+  g_return_if_fail (g_atomic_int_get (&context->ref_count) > 0);
 
   LOCK_CONTEXT (context);
   
@@ -3128,7 +3094,7 @@ g_main_context_get_poll_func (GMainContext *context)
   if (!context)
     context = g_main_context_default ();
   
-  g_return_val_if_fail (context->ref_count > 0, NULL);
+  g_return_val_if_fail (g_atomic_int_get (&context->ref_count) > 0, NULL);
 
   LOCK_CONTEXT (context);
   result = context->poll_func;
@@ -3168,7 +3134,7 @@ g_main_context_wakeup (GMainContext *context)
   if (!context)
     context = g_main_context_default ();
   
-  g_return_if_fail (context->ref_count > 0);
+  g_return_if_fail (g_atomic_int_get (&context->ref_count) > 0);
 
   LOCK_CONTEXT (context);
   g_main_context_wakeup_unlocked (context);
@@ -3571,15 +3537,20 @@ child_watch_helper_thread (gpointer data)
       read (child_watch_wake_up_pipe[0], b, 20);
 
       /* We were woken up.  Wake up all other contexts in all other threads */
-      G_UNLOCK (main_context_list);
+      G_LOCK (main_context_list);
       for (list = main_context_list; list; list = list->next)
        {
          GMainContext *context;
 
          context = list->data;
-         g_main_context_wakeup (context);
+         if (g_atomic_int_get (&context->ref_count) > 0)
+           /* Due to racing conditions we can find ref_count == 0, in
+            * that case, however, the context is still not destroyed
+            * and no poll can be active, otherwise the ref_count
+            * wouldn't be 0 */
+           g_main_context_wakeup (context);
        }
-      G_LOCK (main_context_list);
+      G_UNLOCK (main_context_list);
     }
   return NULL;
 }