summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2012-06-22 22:21:05 -0400
committerDan Winship <danw@gnome.org>2012-06-26 08:40:31 -0400
commitaaaaab91de10445a178e8183a95d98189249e868 (patch)
treebb8ea0608081633b48441dd8afca57fc52c85d0a
parent8e65c304315a7f54addd9c2771d20eca007f9d6a (diff)
downloadglib-aaaaab91de10445a178e8183a95d98189249e868.tar.gz
gmain: add GSourceIter
add an explicit iterator for GMainContext sources https://bugzilla.gnome.org/show_bug.cgi?id=619329
-rw-r--r--glib/gmain.c154
1 files changed, 92 insertions, 62 deletions
diff --git a/glib/gmain.c b/glib/gmain.c
index 21b3a7245..dea2f3ac0 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -309,6 +309,13 @@ struct _GSourcePrivate
GSource *parent_source;
};
+typedef struct _GSourceIter
+{
+ GMainContext *context;
+ gboolean may_modify;
+ GSource *source;
+} GSourceIter;
+
#define LOCK_CONTEXT(context) g_mutex_lock (&context->mutex)
#define UNLOCK_CONTEXT(context) g_mutex_unlock (&context->mutex)
#define G_THREAD_SELF g_thread_self ()
@@ -347,6 +354,13 @@ static void g_main_context_add_poll_unlocked (GMainContext *context,
static void g_main_context_remove_poll_unlocked (GMainContext *context,
GPollFD *fd);
+static void g_source_iter_init (GSourceIter *iter,
+ GMainContext *context,
+ gboolean may_modify);
+static gboolean g_source_iter_next (GSourceIter *iter,
+ GSource **source);
+static void g_source_iter_clear (GSourceIter *iter);
+
static gboolean g_timeout_prepare (GSource *source,
gint *timeout);
static gboolean g_timeout_check (GSource *source);
@@ -472,7 +486,9 @@ poll_rec_list_free (GMainContext *context,
void
g_main_context_unref (GMainContext *context)
{
+ GSourceIter iter;
GSource *source;
+
g_return_if_fail (context != NULL);
g_return_if_fail (g_atomic_int_get (&context->ref_count) > 0);
@@ -483,13 +499,9 @@ g_main_context_unref (GMainContext *context)
main_context_list = g_slist_remove (main_context_list, context);
G_UNLOCK (main_context_list);
- source = context->source_list;
- while (source)
- {
- GSource *next = source->next;
- g_source_destroy_internal (source, context, FALSE);
- source = next;
- }
+ g_source_iter_init (&iter, context, TRUE);
+ while (g_source_iter_next (&iter, &source))
+ g_source_destroy_internal (source, context, FALSE);
g_mutex_clear (&context->mutex);
@@ -804,6 +816,53 @@ g_source_new (GSourceFuncs *source_funcs,
return source;
}
+/* Holds context's lock */
+static void
+g_source_iter_init (GSourceIter *iter,
+ GMainContext *context,
+ gboolean may_modify)
+{
+ iter->context = context;
+ iter->source = NULL;
+ iter->may_modify = may_modify;
+}
+
+/* Holds context's lock */
+static gboolean
+g_source_iter_next (GSourceIter *iter, GSource **source)
+{
+ GSource *next_source;
+
+ if (iter->source)
+ {
+ next_source = iter->source->next;
+ if (iter->may_modify)
+ SOURCE_UNREF (iter->source, iter->context);
+ }
+ else
+ next_source = iter->context->source_list;
+
+ iter->source = next_source;
+ if (iter->source && iter->may_modify)
+ iter->source->ref_count++;
+
+ *source = iter->source;
+ return *source != NULL;
+}
+
+/* Holds context's lock. Only necessary to call if you broke out of
+ * the g_source_iter_next() loop early.
+ */
+static void
+g_source_iter_clear (GSourceIter *iter)
+{
+ if (iter->source && iter->may_modify)
+ {
+ SOURCE_UNREF (iter->source, iter->context);
+ iter->source = NULL;
+ }
+}
+
/* Holds context's lock
*/
static void
@@ -1702,6 +1761,7 @@ GSource *
g_main_context_find_source_by_id (GMainContext *context,
guint source_id)
{
+ GSourceIter iter;
GSource *source;
g_return_val_if_fail (source_id > 0, NULL);
@@ -1711,14 +1771,14 @@ g_main_context_find_source_by_id (GMainContext *context,
LOCK_CONTEXT (context);
- source = context->source_list;
- while (source)
+ g_source_iter_init (&iter, context, FALSE);
+ while (g_source_iter_next (&iter, &source))
{
if (!SOURCE_DESTROYED (source) &&
source->source_id == source_id)
break;
- source = source->next;
}
+ g_source_iter_clear (&iter);
UNLOCK_CONTEXT (context);
@@ -1742,6 +1802,7 @@ g_main_context_find_source_by_funcs_user_data (GMainContext *context,
GSourceFuncs *funcs,
gpointer user_data)
{
+ GSourceIter iter;
GSource *source;
g_return_val_if_fail (funcs != NULL, NULL);
@@ -1751,8 +1812,8 @@ g_main_context_find_source_by_funcs_user_data (GMainContext *context,
LOCK_CONTEXT (context);
- source = context->source_list;
- while (source)
+ g_source_iter_init (&iter, context, FALSE);
+ while (g_source_iter_next (&iter, &source))
{
if (!SOURCE_DESTROYED (source) &&
source->source_funcs == funcs &&
@@ -1766,8 +1827,8 @@ g_main_context_find_source_by_funcs_user_data (GMainContext *context,
if (callback_data == user_data)
break;
}
- source = source->next;
}
+ g_source_iter_clear (&iter);
UNLOCK_CONTEXT (context);
@@ -1789,6 +1850,7 @@ GSource *
g_main_context_find_source_by_user_data (GMainContext *context,
gpointer user_data)
{
+ GSourceIter iter;
GSource *source;
if (context == NULL)
@@ -1796,8 +1858,8 @@ g_main_context_find_source_by_user_data (GMainContext *context,
LOCK_CONTEXT (context);
- source = context->source_list;
- while (source)
+ g_source_iter_init (&iter, context, FALSE);
+ while (g_source_iter_next (&iter, &source))
{
if (!SOURCE_DESTROYED (source) &&
source->callback_funcs)
@@ -1810,8 +1872,8 @@ g_main_context_find_source_by_user_data (GMainContext *context,
if (callback_data == user_data)
break;
}
- source = source->next;
}
+ g_source_iter_clear (&iter);
UNLOCK_CONTEXT (context);
@@ -2562,30 +2624,6 @@ g_main_dispatch (GMainContext *context)
g_ptr_array_set_size (context->pending_dispatches, 0);
}
-/* Holds context's lock */
-static inline GSource *
-next_valid_source (GMainContext *context,
- GSource *source)
-{
- GSource *new_source = source ? source->next : context->source_list;
-
- while (new_source)
- {
- if (!SOURCE_DESTROYED (new_source))
- {
- new_source->ref_count++;
- break;
- }
-
- new_source = new_source->next;
- }
-
- if (source)
- SOURCE_UNREF (source, context);
-
- return new_source;
-}
-
/**
* g_main_context_acquire:
* @context: a #GMainContext
@@ -2761,6 +2799,7 @@ g_main_context_prepare (GMainContext *context,
gint n_ready = 0;
gint current_priority = G_MAXINT;
GSource *source;
+ GSourceIter iter;
if (context == NULL)
context = g_main_context_default ();
@@ -2802,18 +2841,15 @@ g_main_context_prepare (GMainContext *context,
context->timeout = -1;
- source = next_valid_source (context, NULL);
- while (source)
+ g_source_iter_init (&iter, context, TRUE);
+ while (g_source_iter_next (&iter, &source))
{
gint source_timeout = -1;
+ if (SOURCE_DESTROYED (source) || SOURCE_BLOCKED (source))
+ continue;
if ((n_ready > 0) && (source->priority > current_priority))
- {
- SOURCE_UNREF (source, context);
- break;
- }
- if (SOURCE_BLOCKED (source))
- goto next;
+ break;
if (!(source->flags & G_SOURCE_READY))
{
@@ -2856,10 +2892,8 @@ g_main_context_prepare (GMainContext *context,
else
context->timeout = MIN (context->timeout, source_timeout);
}
-
- next:
- source = next_valid_source (context, source);
}
+ g_source_iter_clear (&iter);
UNLOCK_CONTEXT (context);
@@ -2954,6 +2988,7 @@ g_main_context_check (GMainContext *context,
gint n_fds)
{
GSource *source;
+ GSourceIter iter;
GPollRec *pollrec;
gint n_ready = 0;
gint i;
@@ -2991,16 +3026,13 @@ g_main_context_check (GMainContext *context,
i++;
}
- source = next_valid_source (context, NULL);
- while (source)
+ g_source_iter_init (&iter, context, TRUE);
+ while (g_source_iter_next (&iter, &source))
{
+ if (SOURCE_DESTROYED (source) || SOURCE_BLOCKED (source))
+ continue;
if ((n_ready > 0) && (source->priority > max_priority))
- {
- SOURCE_UNREF (source, context);
- break;
- }
- if (SOURCE_BLOCKED (source))
- goto next;
+ break;
if (!(source->flags & G_SOURCE_READY))
{
@@ -3041,10 +3073,8 @@ g_main_context_check (GMainContext *context,
*/
max_priority = source->priority;
}
-
- next:
- source = next_valid_source (context, source);
}
+ g_source_iter_clear (&iter);
UNLOCK_CONTEXT (context);