Use the atomic integer operations for GMainContext and GMainLoop reference

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.
This commit is contained in:
Sebastian Wilhelmi 2004-03-04 10:12:55 +00:00 committed by Sebastian Wilhelmi
parent 6e521087ad
commit c40b15fc6b
7 changed files with 100 additions and 75 deletions

View 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

View 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

View 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

View 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

View 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

View 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

View 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);
g_return_if_fail (g_atomic_int_get (&context->ref_count) > 0);
LOCK_CONTEXT (context);
context->ref_count++;
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;
}