X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gobject%2Fgsignal.c;h=257fc8d4c38f6a6c2df5b71aab7b10ad1e460e5d;hb=2a53b4d0e2c98a14aedf31e38f0ad1fb2e8fe26f;hp=317a8f1879619a1f35c722f05c6783b030ef52f5;hpb=078dbda148a81af1b3a76fbda72f089b963087f1;p=platform%2Fupstream%2Fglib.git diff --git a/gobject/gsignal.c b/gobject/gsignal.c index 317a8f1..257fc8d 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -43,56 +43,56 @@ * and a general purpose notification mechanism * @title: Signals * - * The basic concept of the signal system is that of the - * emission of a signal. Signals are introduced - * per-type and are identified through strings. Signals introduced - * for a parent type are available in derived types as well, so - * basically they are a per-type facility that is inherited. A signal - * emission mainly involves invocation of a certain set of callbacks - * in precisely defined manner. There are two main categories of such - * callbacks, per-object ones and user provided ones. + * The basic concept of the signal system is that of the emission + * of a signal. Signals are introduced per-type and are identified + * through strings. Signals introduced for a parent type are available + * in derived types as well, so basically they are a per-type facility + * that is inherited. + * + * A signal emission mainly involves invocation of a certain set of + * callbacks in precisely defined manner. There are two main categories + * of such callbacks, per-object ones and user provided ones. * (Although signals can deal with any kind of instantiatable type, I'm * referring to those types as "object types" in the following, simply * because that is the context most users will encounter signals in.) * The per-object callbacks are most often referred to as "object method * handler" or "default (signal) handler", while user provided callbacks are * usually just called "signal handler". + * * The object method handler is provided at signal creation time (this most * frequently happens at the end of an object class' creation), while user - * provided handlers are frequently connected and disconnected to/from a certain - * signal on certain object instances. + * provided handlers are frequently connected and disconnected to/from a + * certain signal on certain object instances. * * A signal emission consists of five stages, unless prematurely stopped: - * - * - * 1 - Invocation of the object method handler for %G_SIGNAL_RUN_FIRST signals - * - * - * 2 - Invocation of normal user-provided signal handlers (after flag %FALSE) - * - * - * 3 - Invocation of the object method handler for %G_SIGNAL_RUN_LAST signals - * - * - * 4 - Invocation of user provided signal handlers, connected with an after flag of %TRUE - * - * - * 5 - Invocation of the object method handler for %G_SIGNAL_RUN_CLEANUP signals - * - * + * + * 1. Invocation of the object method handler for %G_SIGNAL_RUN_FIRST signals + * + * 2. Invocation of normal user-provided signal handlers (where the @after + * flag is not set) + * + * 3. Invocation of the object method handler for %G_SIGNAL_RUN_LAST signals + * + * 4. Invocation of user provided signal handlers (where the @after flag is set) + * + * 5. Invocation of the object method handler for %G_SIGNAL_RUN_CLEANUP signals + * The user-provided signal handlers are called in the order they were * connected in. + * * All handlers may prematurely stop a signal emission, and any number of * handlers may be connected, disconnected, blocked or unblocked during * a signal emission. + * * There are certain criteria for skipping user handlers in stages 2 and 4 * of a signal emission. - * First, user handlers may be blocked, blocked handlers are omitted - * during callback invocation, to return from the "blocked" state, a - * handler has to get unblocked exactly the same amount of times - * it has been blocked before. + * + * First, user handlers may be blocked. Blocked handlers are omitted during + * callback invocation, to return from the blocked state, a handler has to + * get unblocked exactly the same amount of times it has been blocked before. + * * Second, upon emission of a %G_SIGNAL_DETAILED signal, an additional - * "detail" argument passed in to g_signal_emit() has to match the detail + * @detail argument passed in to g_signal_emit() has to match the detail * argument of the signal handler currently subject to invocation. * Specification of no detail argument for signal handlers (omission of the * detail part of the signal specification upon connection) serves as a @@ -153,12 +153,9 @@ static inline void handler_unref_R (guint signal_id, Handler *handler); static gint handler_lists_cmp (gconstpointer node1, gconstpointer node2); -static inline void emission_push (Emission **emission_list_p, - Emission *emission); -static inline void emission_pop (Emission **emission_list_p, - Emission *emission); -static inline Emission* emission_find (Emission *emission_list, - guint signal_id, +static inline void emission_push (Emission *emission); +static inline void emission_pop (Emission *emission); +static inline Emission* emission_find (guint signal_id, GQuark detail, gpointer instance); static gint class_closures_cmp (gconstpointer node1, @@ -289,8 +286,7 @@ static GBSearchConfig g_class_closure_bconfig = { 0, }; static GHashTable *g_handler_list_bsa_ht = NULL; -static Emission *g_recursive_emissions = NULL; -static Emission *g_restart_emissions = NULL; +static Emission *g_emissions = NULL; static gulong g_handler_sequential_number = 1; G_LOCK_DEFINE_STATIC (g_signal_mutex); #define SIGNAL_LOCK() G_LOCK (g_signal_mutex) @@ -302,7 +298,7 @@ static guint g_n_signal_nodes = 0; static SignalNode **g_signal_nodes = NULL; static inline SignalNode* -LOOKUP_SIGNAL_NODE (register guint signal_id) +LOOKUP_SIGNAL_NODE (guint signal_id) { if (signal_id < g_n_signal_nodes) return g_signal_nodes[signal_id]; @@ -731,40 +727,37 @@ node_update_single_va_closure (SignalNode *node) } static inline void -emission_push (Emission **emission_list_p, - Emission *emission) +emission_push (Emission *emission) { - emission->next = *emission_list_p; - *emission_list_p = emission; + emission->next = g_emissions; + g_emissions = emission; } static inline void -emission_pop (Emission **emission_list_p, - Emission *emission) +emission_pop (Emission *emission) { Emission *node, *last = NULL; - for (node = *emission_list_p; node; last = node, node = last->next) + for (node = g_emissions; node; last = node, node = last->next) if (node == emission) { if (last) last->next = node->next; else - *emission_list_p = node->next; + g_emissions = node->next; return; } g_assert_not_reached (); } static inline Emission* -emission_find (Emission *emission_list, - guint signal_id, +emission_find (guint signal_id, GQuark detail, gpointer instance) { Emission *emission; - for (emission = emission_list; emission; emission = emission->next) + for (emission = g_emissions; emission; emission = emission->next) if (emission->instance == instance && emission->ihint.signal_id == signal_id && emission->ihint.detail == detail) @@ -775,26 +768,13 @@ emission_find (Emission *emission_list, static inline Emission* emission_find_innermost (gpointer instance) { - Emission *emission, *s = NULL, *c = NULL; + Emission *emission; - for (emission = g_restart_emissions; emission; emission = emission->next) - if (emission->instance == instance) - { - s = emission; - break; - } - for (emission = g_recursive_emissions; emission; emission = emission->next) + for (emission = g_emissions; emission; emission = emission->next) if (emission->instance == instance) - { - c = emission; - break; - } - if (!s) - return c; - else if (!c) - return s; - else - return G_HAVE_GROWING_STACK ? MAX (c, s) : MIN (c, s); + return emission; + + return NULL; } static gint @@ -884,8 +864,7 @@ g_signal_stop_emission (gpointer instance, } if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) { - Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions; - Emission *emission = emission_find (emission_list, signal_id, detail, instance); + Emission *emission = emission_find (signal_id, detail, instance); if (emission) { @@ -1149,8 +1128,7 @@ g_signal_stop_emission_by_name (gpointer instance, G_STRLOC, detailed_signal, instance, g_type_name (itype)); else { - Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions; - Emission *emission = emission_find (emission_list, signal_id, detail, instance); + Emission *emission = emission_find (signal_id, detail, instance); if (emission) { @@ -1365,9 +1343,8 @@ g_signal_query (guint signal_id, * be used, but they cannot be mixed. * * If 0 is used for @class_offset subclasses cannot override the class handler - * in their class_init method by doing - * super_class->signal_handler = my_signal_handler. Instead they - * will have to use g_signal_override_class_handler(). + * in their class_init method by doing super_class->signal_handler = my_signal_handler. + * Instead they will have to use g_signal_override_class_handler(). * * If c_marshaller is %NULL, g_cclosure_marshal_generic() will be used as * the marshaller for this signal. @@ -1437,7 +1414,7 @@ g_signal_new (const gchar *signal_name, * * See g_signal_new() for information about signal names. * - * If c_marshaller is %NULL @g_cclosure_marshal_generic will be used as + * If c_marshaller is %NULL, g_cclosure_marshal_generic() will be used as * the marshaller for this signal. * * Returns: the signal id @@ -1565,7 +1542,7 @@ signal_add_class_closure (SignalNode *node, * * See g_signal_new() for details on allowed signal names. * - * If c_marshaller is %NULL @g_cclosure_marshal_generic will be used as + * If c_marshaller is %NULL, g_cclosure_marshal_generic() will be used as * the marshaller for this signal. * * Returns: the signal id @@ -1869,8 +1846,7 @@ signal_destroy_R (SignalNode *signal_node) { Emission *emission; - for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions; - emission; emission = emission->next) + for (emission = g_emissions; emission; emission = emission->next) if (emission->ihint.signal_id == node.signal_id) g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance '%p')", node.name, emission->instance); @@ -2158,8 +2134,7 @@ g_signal_chain_from_overridden_handler (gpointer instance, SIGNAL_UNLOCK (); instance_and_params->g_type = 0; - g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (instance)); - g_value_set_instance (instance_and_params, instance); + g_value_init_from_instance (instance_and_params, instance); SIGNAL_LOCK (); emission->chain_type = chain_type; @@ -2401,8 +2376,8 @@ node_check_deprecated (const SignalNode *node) * Connects a #GCallback function to a signal for a particular object. Similar * to g_signal_connect(), but allows to provide a #GClosureNotify for the data * which will be called when the signal handler is disconnected and no longer - * used. Specify @connect_flags if you need ..._after() or - * ..._swapped() variants of this function. + * used. Specify @connect_flags if you need `..._after()` or + * `..._swapped()` variants of this function. * * Returns: the handler id (always greater than 0 for successful connections) */ @@ -2610,7 +2585,11 @@ g_signal_handler_is_connected (gpointer instance, /** * g_signal_handlers_destroy: - * @instance: (type GObject.Object): The instance where a signal handler is sought. + * @instance: (type GObject.Object): The instance whose signal handlers are destroyed + * + * Destroy all signal handlers of a type instance. This function is + * an implementation detail of the #GObject dispose implementation, + * and should not be used outside of the type system. */ void g_signal_handlers_destroy (gpointer instance) @@ -2888,6 +2867,12 @@ g_signal_handlers_disconnect_matched (gpointer instance, * Returns whether there are any handlers connected to @instance for the * given signal id and detail. * + * If @detail is 0 then it will only match handlers that were connected + * without detail. If @detail is non-zero then it will match handlers + * connected both without detail and with the given detail. This is + * consistent with how a signal emitted with @detail would be delivered + * to those handlers. + * * One example of when you might use this is when the arguments to the * signal are difficult to compute. A class implementor may opt to not * emit the signal if no one is attached anyway, thus saving the cost @@ -3195,7 +3180,7 @@ g_signal_emit_valist (gpointer instance, emission.ihint.run_type = run_type; emission.state = EMISSION_RUN; emission.chain_type = instance_type; - emission_push (&g_recursive_emissions, &emission); + emission_push (&emission); if (fastpath_handler) handler_ref (fastpath_handler); @@ -3225,7 +3210,7 @@ g_signal_emit_valist (gpointer instance, SIGNAL_LOCK (); emission.chain_type = G_TYPE_NONE; - emission_pop (&g_recursive_emissions, &emission); + emission_pop (&emission); if (fastpath_handler) handler_unref_R (signal_id, instance, fastpath_handler); @@ -3302,8 +3287,7 @@ g_signal_emit_valist (gpointer instance, } instance_and_params->g_type = 0; - g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (instance)); - g_value_set_instance (instance_and_params, instance); + g_value_init_from_instance (instance_and_params, instance); if (signal_return_type == G_TYPE_NONE) signal_emit_unlocked_R (node, detail, instance, NULL, instance_and_params); else @@ -3433,7 +3417,7 @@ signal_emit_unlocked_R (SignalNode *node, if (node->flags & G_SIGNAL_NO_RECURSE) { - Emission *node = emission_find (g_restart_emissions, signal_id, detail, instance); + Emission *node = emission_find (signal_id, detail, instance); if (node) { @@ -3458,7 +3442,7 @@ signal_emit_unlocked_R (SignalNode *node, emission.ihint.run_type = 0; emission.state = 0; emission.chain_type = G_TYPE_NONE; - emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission); + emission_push (&emission); class_closure = signal_lookup_closure (node, instance); EMIT_RESTART: @@ -3682,7 +3666,7 @@ signal_emit_unlocked_R (SignalNode *node, if (handler_list) handler_unref_R (signal_id, instance, handler_list); - emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission); + emission_pop (&emission); SIGNAL_UNLOCK (); if (accumulator) g_value_unset (&accu); @@ -3754,8 +3738,8 @@ type_debug_name (GType type) * that a return of %TRUE stops the signal emission: no further * callbacks will be invoked, while a return of %FALSE allows * the emission to continue. The idea here is that a %TRUE return - * indicates that the callback handled the signal, - * and no further handling is needed. + * indicates that the callback handled the signal, and no further + * handling is needed. * * Since: 2.4 *