X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=glib%2Fgmain.c;h=45ed40250b7a2565b04edde9ff62e757e24d9a76;hb=49b59e5ac4428a6a99a85d699c3662f96efc4e9d;hp=a9ddabf9b9de2d743a7a28344642251104eec9d9;hpb=6147d15ea256ff0aabf11fb854ef07cf0e0e3a62;p=platform%2Fupstream%2Fglib.git diff --git a/glib/gmain.c b/glib/gmain.c index a9ddabf..45ed402 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -240,11 +240,12 @@ struct _GMainContext gint ref_count; + GHashTable *sources; /* guint -> GSource */ + GPtrArray *pending_dispatches; gint timeout; /* Timeout for current iteration */ guint next_id; - GHashTable *overflow_used_source_ids; /* set */ GList *source_lists; gint in_check_or_prepare; @@ -546,8 +547,7 @@ g_main_context_unref (GMainContext *context) } g_list_free (context->source_lists); - if (context->overflow_used_source_ids) - g_hash_table_destroy (context->overflow_used_source_ids); + g_hash_table_destroy (context->sources); g_mutex_clear (&context->mutex); @@ -602,6 +602,7 @@ g_main_context_new (void) g_mutex_init (&context->mutex); g_cond_init (&context->cond); + context->sources = g_hash_table_new (NULL, NULL); context->owner = NULL; context->waiters = NULL; @@ -1059,61 +1060,6 @@ source_remove_from_context (GSource *source, context->source_lists = g_list_remove (context->source_lists, source_list); g_slice_free (GSourceList, source_list); } - - if (context->overflow_used_source_ids) - g_hash_table_remove (context->overflow_used_source_ids, - GUINT_TO_POINTER (source->source_id)); - -} - -static void -assign_source_id_unlocked (GMainContext *context, - GSource *source) -{ - guint id; - - /* Are we about to overflow back to 0? - * See https://bugzilla.gnome.org/show_bug.cgi?id=687098 - */ - if (G_UNLIKELY (context->next_id == G_MAXUINT && - context->overflow_used_source_ids == NULL)) - { - GSourceIter iter; - GSource *source; - - context->overflow_used_source_ids = g_hash_table_new (NULL, NULL); - - g_source_iter_init (&iter, context, FALSE); - while (g_source_iter_next (&iter, &source)) - { - g_hash_table_add (context->overflow_used_source_ids, - GUINT_TO_POINTER (source->source_id)); - } - id = G_MAXUINT; - g_hash_table_add (context->overflow_used_source_ids, GUINT_TO_POINTER (id)); - } - else if (context->overflow_used_source_ids == NULL) - { - id = context->next_id++; - } - else - { - /* - * If we overran G_MAXUINT, we fall back to randomly probing the - * source ids for the current context. This will be slower the more - * sources there are, but we're mainly concerned right now about - * correctness and code size. There's time for a more clever solution - * later. - */ - do - id = g_random_int (); - while (id == 0 || - g_hash_table_contains (context->overflow_used_source_ids, - GUINT_TO_POINTER (id))); - g_hash_table_add (context->overflow_used_source_ids, GUINT_TO_POINTER (id)); - } - - source->source_id = id; } static guint @@ -1122,10 +1068,21 @@ g_source_attach_unlocked (GSource *source, gboolean do_wakeup) { GSList *tmp_list; + guint id; + + /* The counter may have wrapped, so we must ensure that we do not + * reuse the source id of an existing source. + */ + do + id = context->next_id++; + while (id == 0 || g_hash_table_contains (context->sources, GUINT_TO_POINTER (id))); source->context = context; - assign_source_id_unlocked (context, source); + source->source_id = id; source->ref_count++; + + g_hash_table_insert (context->sources, GUINT_TO_POINTER (id), source); + source_add_to_context (source, context); if (!SOURCE_BLOCKED (source)) @@ -1335,6 +1292,9 @@ g_source_get_context (GSource *source) * the @revents field in the #GPollFD struct and return %TRUE if events need * to be processed. * + * This API is only intended to be used by implementations of #GSource. + * Do not call this API on a #GSource that you did not create. + * * Using this API forces the linear scanning of event sources on each * main loop iteration. Newly-written event sources should try to use * g_source_add_unix_fd() instead of this API. @@ -1371,6 +1331,9 @@ g_source_add_poll (GSource *source, * * Removes a file descriptor from the set of file descriptors polled for * this source. + * + * This API is only intended to be used by implementations of #GSource. + * Do not call this API on a #GSource that you did not create. **/ void g_source_remove_poll (GSource *source, @@ -1417,6 +1380,9 @@ g_source_remove_poll (GSource *source, * @source will hold a reference on @child_source while @child_source * is attached to it. * + * This API is only intended to be used by implementations of #GSource. + * Do not call this API on a #GSource that you did not create. + * * Since: 2.28 **/ void @@ -1473,6 +1439,9 @@ g_child_source_remove_internal (GSource *child_source, * * Detaches @child_source from @source and destroys it. * + * This API is only intended to be used by implementations of #GSource. + * Do not call this API on a #GSource that you did not create. + * * Since: 2.28 **/ void @@ -1768,6 +1737,9 @@ g_source_get_priority (GSource *source) * for both sources is reached during the same main context iteration * then the order of dispatch is undefined. * + * This API is only intended to be used by implementations of #GSource. + * Do not call this API on a #GSource that you did not create. + * * Since: 2.36 **/ void @@ -2006,6 +1978,8 @@ g_source_unref_internal (GSource *source, if (!SOURCE_DESTROYED (source)) g_warning (G_STRLOC ": ref_count == 0, but source was still attached to a context!"); source_remove_from_context (source, context); + + g_hash_table_remove (context->sources, GUINT_TO_POINTER (source->source_id)); } if (source->source_funcs->finalize) @@ -2065,37 +2039,30 @@ g_source_unref (GSource *source) /** * g_main_context_find_source_by_id: * @context: (allow-none): a #GMainContext (if %NULL, the default context will be used) - * @source_id: the source ID, as returned by g_source_get_id(). - * + * @source_id: the source ID, as returned by g_source_get_id(). + * * Finds a #GSource given a pair of context and ID. - * + * * Returns: (transfer none): the #GSource if found, otherwise, %NULL **/ GSource * g_main_context_find_source_by_id (GMainContext *context, - guint source_id) + guint source_id) { - GSourceIter iter; GSource *source; - + g_return_val_if_fail (source_id > 0, NULL); if (context == NULL) context = g_main_context_default (); - - LOCK_CONTEXT (context); - - g_source_iter_init (&iter, context, FALSE); - while (g_source_iter_next (&iter, &source)) - { - if (!SOURCE_DESTROYED (source) && - source->source_id == source_id) - break; - } - g_source_iter_clear (&iter); + LOCK_CONTEXT (context); + source = g_hash_table_lookup (context->sources, GUINT_TO_POINTER (source_id)); UNLOCK_CONTEXT (context); + if (source && SOURCE_DESTROYED (source)) + source = NULL; + return source; } @@ -2299,6 +2266,9 @@ g_source_remove_by_funcs_user_data (GSourceFuncs *funcs, * It is not necessary to remove the fd before destroying the source; it * will be cleaned up automatically. * + * This API is only intended to be used by implementations of #GSource. + * Do not call this API on a #GSource that you did not create. + * * As the name suggests, this function is not available on Windows. * * Returns: an opaque tag @@ -2351,6 +2321,9 @@ g_source_add_unix_fd (GSource *source, * If you want to remove a fd, don't set its event mask to zero. * Instead, call g_source_remove_unix_fd(). * + * This API is only intended to be used by implementations of #GSource. + * Do not call this API on a #GSource that you did not create. + * * As the name suggests, this function is not available on Windows. * * Since: 2.36 @@ -2386,6 +2359,9 @@ g_source_modify_unix_fd (GSource *source, * watched while keeping the same source around. In the normal case you * will just want to destroy the source. * + * This API is only intended to be used by implementations of #GSource. + * Do not call this API on a #GSource that you did not create. + * * As the name suggests, this function is not available on Windows. * * Since: 2.36 @@ -2430,6 +2406,9 @@ g_source_remove_unix_fd (GSource *source, * The return value of this function is only defined when the function * is called from the check or dispatch functions for @source. * + * This API is only intended to be used by implementations of #GSource. + * Do not call this API on a #GSource that you did not create. + * * As the name suggests, this function is not available on Windows. * * Returns: the conditions reported on the fd