Switch GMainLoop to be ref/unref, use to make dropping reference to

Wed Jan  3 14:10:49 2001  Owen Taylor  <otaylor@redhat.com>

	* gmain.[ch]: Switch GMainLoop to be ref/unref, use to
	make dropping reference to running loop safe.
This commit is contained in:
Owen Taylor 2001-01-03 20:18:40 +00:00 committed by Owen Taylor
parent b1d840c20a
commit 3ae4c59e3f
12 changed files with 216 additions and 64 deletions

View File

@ -1,3 +1,8 @@
Wed Jan 3 14:10:49 2001 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Switch GMainLoop to be ref/unref, use to
make dropping reference to running loop safe.
Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com> Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_unref_internal): Unref callback->cb_data * gmain.c (g_source_unref_internal): Unref callback->cb_data

View File

@ -1,3 +1,8 @@
Wed Jan 3 14:10:49 2001 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Switch GMainLoop to be ref/unref, use to
make dropping reference to running loop safe.
Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com> Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_unref_internal): Unref callback->cb_data * gmain.c (g_source_unref_internal): Unref callback->cb_data

View File

@ -1,3 +1,8 @@
Wed Jan 3 14:10:49 2001 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Switch GMainLoop to be ref/unref, use to
make dropping reference to running loop safe.
Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com> Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_unref_internal): Unref callback->cb_data * gmain.c (g_source_unref_internal): Unref callback->cb_data

View File

@ -1,3 +1,8 @@
Wed Jan 3 14:10:49 2001 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Switch GMainLoop to be ref/unref, use to
make dropping reference to running loop safe.
Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com> Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_unref_internal): Unref callback->cb_data * gmain.c (g_source_unref_internal): Unref callback->cb_data

View File

@ -1,3 +1,8 @@
Wed Jan 3 14:10:49 2001 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Switch GMainLoop to be ref/unref, use to
make dropping reference to running loop safe.
Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com> Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_unref_internal): Unref callback->cb_data * gmain.c (g_source_unref_internal): Unref callback->cb_data

View File

@ -1,3 +1,8 @@
Wed Jan 3 14:10:49 2001 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Switch GMainLoop to be ref/unref, use to
make dropping reference to running loop safe.
Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com> Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_unref_internal): Unref callback->cb_data * gmain.c (g_source_unref_internal): Unref callback->cb_data

View File

@ -1,3 +1,8 @@
Wed Jan 3 14:10:49 2001 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Switch GMainLoop to be ref/unref, use to
make dropping reference to running loop safe.
Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com> Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_unref_internal): Unref callback->cb_data * gmain.c (g_source_unref_internal): Unref callback->cb_data

View File

@ -1,3 +1,8 @@
Wed Jan 3 14:10:49 2001 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Switch GMainLoop to be ref/unref, use to
make dropping reference to running loop safe.
Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com> Wed Dec 13 20:41:49 2000 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_unref_internal): Unref callback->cb_data * gmain.c (g_source_unref_internal): Unref callback->cb_data

View File

@ -131,6 +131,7 @@ struct _GMainLoop
{ {
GMainContext *context; GMainContext *context;
gboolean is_running; gboolean is_running;
guint ref_count;
#ifdef G_THREADS_ENABLED #ifdef G_THREADS_ENABLED
GMutex *mutex; GMutex *mutex;
@ -2012,6 +2013,7 @@ g_main_loop_new (GMainContext *context,
loop = g_new0 (GMainLoop, 1); loop = g_new0 (GMainLoop, 1);
loop->context = context; loop->context = context;
loop->is_running = is_running != FALSE; loop->is_running = is_running != FALSE;
loop->ref_count = 1;
#ifdef G_THREADS_ENABLED #ifdef G_THREADS_ENABLED
if (g_thread_supported ()) if (g_thread_supported ())
@ -2024,6 +2026,66 @@ g_main_loop_new (GMainContext *context,
return loop; return loop;
} }
/**
* g_main_loop_ref:
* @loop: a #GMainLoop
*
* Increase the reference count on a #GMainLoop object by one.
*
* Return value: @loop
**/
GMainLoop *
g_main_loop_ref (GMainLoop *loop)
{
g_return_val_if_fail (loop != NULL, NULL);
LOCK_LOOP (loop);
loop->ref_count++;
UNLOCK_LOOP (loop);
return loop;
}
static void
main_loop_destroy (GMainLoop *loop)
{
#ifdef G_THREADS_ENABLED
g_mutex_free (loop->mutex);
if (loop->sem_cond)
g_cond_free (loop->sem_cond);
#endif /* G_THREADS_ENABLED */
g_free (loop);
}
/**
* g_main_loop_unref:
* @loop: a #GMainLoop
*
* Decreases the reference count on a #GMainLoop object by one. If
* the result is zero, free the loop and free all associated memory.
**/
void
g_main_loop_unref (GMainLoop *loop)
{
g_return_if_fail (loop != NULL);
g_return_if_fail (loop->ref_count > 0);
LOCK_LOOP (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.
*/
UNLOCK_LOOP (loop);
main_loop_destroy (loop);
}
else
UNLOCK_LOOP (loop);
}
/** /**
* g_main_loop_run: * g_main_loop_run:
* @loop: a #GMainLoop * @loop: a #GMainLoop
@ -2038,11 +2100,16 @@ g_main_loop_run (GMainLoop *loop)
{ {
g_return_if_fail (loop != NULL); g_return_if_fail (loop != NULL);
/* The assumption here is that a reference is held to the loop
* until we recursively iterate
*/
#ifdef G_THREADS_ENABLED #ifdef G_THREADS_ENABLED
if (loop->context->thread != g_thread_self ()) if (loop->context->thread != g_thread_self ())
{ {
LOCK_LOOP (loop); LOCK_LOOP (loop);
loop->ref_count++;
if (!g_thread_supported ()) if (!g_thread_supported ())
{ {
g_warning ("g_main_loop_run() was called from second thread but" g_warning ("g_main_loop_run() was called from second thread but"
@ -2059,8 +2126,6 @@ g_main_loop_run (GMainLoop *loop)
while (loop->is_running) while (loop->is_running)
g_cond_wait (loop->sem_cond, loop->mutex); g_cond_wait (loop->sem_cond, loop->mutex);
} }
UNLOCK_LOOP (loop);
} }
else else
#endif /* G_THREADS_ENABLED */ #endif /* G_THREADS_ENABLED */
@ -2076,6 +2141,7 @@ g_main_loop_run (GMainLoop *loop)
LOCK_LOOP (loop); LOCK_LOOP (loop);
loop->ref_count++;
loop->is_running = TRUE; loop->is_running = TRUE;
while (loop->is_running) while (loop->is_running)
{ {
@ -2083,8 +2149,19 @@ g_main_loop_run (GMainLoop *loop)
g_main_context_iterate (loop->context, TRUE, TRUE); g_main_context_iterate (loop->context, TRUE, TRUE);
LOCK_LOOP (loop); LOCK_LOOP (loop);
} }
UNLOCK_LOOP (loop);
} }
/* We inline this here rather than calling g_main_loop_unref() to
* avoid an extra unlock/lock.
*/
loop->ref_count--;
if (loop->ref_count == 0)
{
UNLOCK_LOOP (loop);
main_loop_destroy (loop);
}
else
UNLOCK_LOOP (loop);
} }
/** /**
@ -2115,28 +2192,6 @@ g_main_loop_quit (GMainLoop *loop)
UNLOCK_CONTEXT (loop->context); UNLOCK_CONTEXT (loop->context);
} }
/**
* g_main_loop_destroy:
* @loop: a #GMainLoop
*
* Destroy a #GMainLoop object and free all associated memory.
* The loop must not currently be running via g_main_run().
**/
void
g_main_loop_destroy (GMainLoop *loop)
{
g_return_if_fail (loop != NULL);
g_return_if_fail (!loop->is_running);
#ifdef G_THREADS_ENABLED
g_mutex_free (loop->mutex);
if (loop->sem_cond)
g_cond_free (loop->sem_cond);
#endif /* G_THREADS_ENABLED */
g_free (loop);
}
/** /**
* g_main_loop_is_running: * g_main_loop_is_running:
* @loop: a #GMainLoop. * @loop: a #GMainLoop.

View File

@ -174,7 +174,8 @@ GMainLoop *g_main_loop_new (GMainContext *context,
gboolean is_running); gboolean is_running);
void g_main_loop_run (GMainLoop *loop); void g_main_loop_run (GMainLoop *loop);
void g_main_loop_quit (GMainLoop *loop); void g_main_loop_quit (GMainLoop *loop);
void g_main_loop_destroy (GMainLoop *loop); GMainLoop *g_main_loop_ref (GMainLoop *loop);
void g_main_loop_unref (GMainLoop *loop);
gboolean g_main_loop_is_running (GMainLoop *loop); gboolean g_main_loop_is_running (GMainLoop *loop);
/* GSource: */ /* GSource: */
@ -237,7 +238,7 @@ void g_get_current_time (GTimeVal *result);
#define g_main_new(is_running) g_main_loop_new (NULL, is_running); #define g_main_new(is_running) g_main_loop_new (NULL, is_running);
#define g_main_run(loop) g_main_loop_run(loop) #define g_main_run(loop) g_main_loop_run(loop)
#define g_main_quit(loop) g_main_loop_quit(loop) #define g_main_quit(loop) g_main_loop_quit(loop)
#define g_main_destroy(loop) g_main_loop_destroy(loop) #define g_main_destroy(loop) g_main_loop_unref(loop)
#define g_main_is_running(loop) g_main_loop_is_running(loop) #define g_main_is_running(loop) g_main_loop_is_running(loop)
/* Source manipulation by ID */ /* Source manipulation by ID */

105
gmain.c
View File

@ -131,6 +131,7 @@ struct _GMainLoop
{ {
GMainContext *context; GMainContext *context;
gboolean is_running; gboolean is_running;
guint ref_count;
#ifdef G_THREADS_ENABLED #ifdef G_THREADS_ENABLED
GMutex *mutex; GMutex *mutex;
@ -2012,6 +2013,7 @@ g_main_loop_new (GMainContext *context,
loop = g_new0 (GMainLoop, 1); loop = g_new0 (GMainLoop, 1);
loop->context = context; loop->context = context;
loop->is_running = is_running != FALSE; loop->is_running = is_running != FALSE;
loop->ref_count = 1;
#ifdef G_THREADS_ENABLED #ifdef G_THREADS_ENABLED
if (g_thread_supported ()) if (g_thread_supported ())
@ -2024,6 +2026,66 @@ g_main_loop_new (GMainContext *context,
return loop; return loop;
} }
/**
* g_main_loop_ref:
* @loop: a #GMainLoop
*
* Increase the reference count on a #GMainLoop object by one.
*
* Return value: @loop
**/
GMainLoop *
g_main_loop_ref (GMainLoop *loop)
{
g_return_val_if_fail (loop != NULL, NULL);
LOCK_LOOP (loop);
loop->ref_count++;
UNLOCK_LOOP (loop);
return loop;
}
static void
main_loop_destroy (GMainLoop *loop)
{
#ifdef G_THREADS_ENABLED
g_mutex_free (loop->mutex);
if (loop->sem_cond)
g_cond_free (loop->sem_cond);
#endif /* G_THREADS_ENABLED */
g_free (loop);
}
/**
* g_main_loop_unref:
* @loop: a #GMainLoop
*
* Decreases the reference count on a #GMainLoop object by one. If
* the result is zero, free the loop and free all associated memory.
**/
void
g_main_loop_unref (GMainLoop *loop)
{
g_return_if_fail (loop != NULL);
g_return_if_fail (loop->ref_count > 0);
LOCK_LOOP (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.
*/
UNLOCK_LOOP (loop);
main_loop_destroy (loop);
}
else
UNLOCK_LOOP (loop);
}
/** /**
* g_main_loop_run: * g_main_loop_run:
* @loop: a #GMainLoop * @loop: a #GMainLoop
@ -2038,11 +2100,16 @@ g_main_loop_run (GMainLoop *loop)
{ {
g_return_if_fail (loop != NULL); g_return_if_fail (loop != NULL);
/* The assumption here is that a reference is held to the loop
* until we recursively iterate
*/
#ifdef G_THREADS_ENABLED #ifdef G_THREADS_ENABLED
if (loop->context->thread != g_thread_self ()) if (loop->context->thread != g_thread_self ())
{ {
LOCK_LOOP (loop); LOCK_LOOP (loop);
loop->ref_count++;
if (!g_thread_supported ()) if (!g_thread_supported ())
{ {
g_warning ("g_main_loop_run() was called from second thread but" g_warning ("g_main_loop_run() was called from second thread but"
@ -2059,8 +2126,6 @@ g_main_loop_run (GMainLoop *loop)
while (loop->is_running) while (loop->is_running)
g_cond_wait (loop->sem_cond, loop->mutex); g_cond_wait (loop->sem_cond, loop->mutex);
} }
UNLOCK_LOOP (loop);
} }
else else
#endif /* G_THREADS_ENABLED */ #endif /* G_THREADS_ENABLED */
@ -2076,6 +2141,7 @@ g_main_loop_run (GMainLoop *loop)
LOCK_LOOP (loop); LOCK_LOOP (loop);
loop->ref_count++;
loop->is_running = TRUE; loop->is_running = TRUE;
while (loop->is_running) while (loop->is_running)
{ {
@ -2083,8 +2149,19 @@ g_main_loop_run (GMainLoop *loop)
g_main_context_iterate (loop->context, TRUE, TRUE); g_main_context_iterate (loop->context, TRUE, TRUE);
LOCK_LOOP (loop); LOCK_LOOP (loop);
} }
UNLOCK_LOOP (loop);
} }
/* We inline this here rather than calling g_main_loop_unref() to
* avoid an extra unlock/lock.
*/
loop->ref_count--;
if (loop->ref_count == 0)
{
UNLOCK_LOOP (loop);
main_loop_destroy (loop);
}
else
UNLOCK_LOOP (loop);
} }
/** /**
@ -2115,28 +2192,6 @@ g_main_loop_quit (GMainLoop *loop)
UNLOCK_CONTEXT (loop->context); UNLOCK_CONTEXT (loop->context);
} }
/**
* g_main_loop_destroy:
* @loop: a #GMainLoop
*
* Destroy a #GMainLoop object and free all associated memory.
* The loop must not currently be running via g_main_run().
**/
void
g_main_loop_destroy (GMainLoop *loop)
{
g_return_if_fail (loop != NULL);
g_return_if_fail (!loop->is_running);
#ifdef G_THREADS_ENABLED
g_mutex_free (loop->mutex);
if (loop->sem_cond)
g_cond_free (loop->sem_cond);
#endif /* G_THREADS_ENABLED */
g_free (loop);
}
/** /**
* g_main_loop_is_running: * g_main_loop_is_running:
* @loop: a #GMainLoop. * @loop: a #GMainLoop.

View File

@ -174,7 +174,8 @@ GMainLoop *g_main_loop_new (GMainContext *context,
gboolean is_running); gboolean is_running);
void g_main_loop_run (GMainLoop *loop); void g_main_loop_run (GMainLoop *loop);
void g_main_loop_quit (GMainLoop *loop); void g_main_loop_quit (GMainLoop *loop);
void g_main_loop_destroy (GMainLoop *loop); GMainLoop *g_main_loop_ref (GMainLoop *loop);
void g_main_loop_unref (GMainLoop *loop);
gboolean g_main_loop_is_running (GMainLoop *loop); gboolean g_main_loop_is_running (GMainLoop *loop);
/* GSource: */ /* GSource: */
@ -237,7 +238,7 @@ void g_get_current_time (GTimeVal *result);
#define g_main_new(is_running) g_main_loop_new (NULL, is_running); #define g_main_new(is_running) g_main_loop_new (NULL, is_running);
#define g_main_run(loop) g_main_loop_run(loop) #define g_main_run(loop) g_main_loop_run(loop)
#define g_main_quit(loop) g_main_loop_quit(loop) #define g_main_quit(loop) g_main_loop_quit(loop)
#define g_main_destroy(loop) g_main_loop_destroy(loop) #define g_main_destroy(loop) g_main_loop_unref(loop)
#define g_main_is_running(loop) g_main_loop_is_running(loop) #define g_main_is_running(loop) g_main_loop_is_running(loop)
/* Source manipulation by ID */ /* Source manipulation by ID */