📄 gsignal.c
字号:
g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE); SIGNAL_LOCK (); signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark); SIGNAL_UNLOCK (); node = signal_id ? LOOKUP_SIGNAL_NODE (signal_id) : NULL; if (!node || node->destroyed || (detail && !(node->flags & G_SIGNAL_DETAILED))) return FALSE; if (signal_id_p) *signal_id_p = signal_id; if (detail_p) *detail_p = detail; return TRUE;}voidg_signal_stop_emission_by_name (gpointer instance, const gchar *detailed_signal){ guint signal_id; GQuark detail = 0; GType itype; g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (detailed_signal != NULL); SIGNAL_LOCK (); itype = G_TYPE_FROM_INSTANCE (instance); signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); if (signal_id) { SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); if (detail && !(node->flags & G_SIGNAL_DETAILED)) g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); else if (!g_type_is_a (itype, node->itype)) g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 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); if (emission) { if (emission->state == EMISSION_HOOK) g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook", node->name, instance); else if (emission->state == EMISSION_RUN) emission->state = EMISSION_STOP; } else g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'", node->name, instance); } } else g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); SIGNAL_UNLOCK ();}guintg_signal_lookup (const gchar *name, GType itype){ guint signal_id; g_return_val_if_fail (name != NULL, 0); g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); SIGNAL_LOCK (); signal_id = signal_id_lookup (g_quark_try_string (name), itype); SIGNAL_UNLOCK (); if (!signal_id) { /* give elaborate warnings */ if (!g_type_name (itype)) g_warning (G_STRLOC ": unable to lookup signal \"%s\" for invalid type id `%lu'", name, itype); else if (!G_TYPE_IS_INSTANTIATABLE (itype)) g_warning (G_STRLOC ": unable to lookup signal \"%s\" for non instantiatable type `%s'", name, g_type_name (itype)); else if (!g_type_class_peek (itype)) g_warning (G_STRLOC ": unable to lookup signal \"%s\" of unloaded type `%s'", name, g_type_name (itype)); } return signal_id;}guint*g_signal_list_ids (GType itype, guint *n_ids){ SignalKey *keys; GArray *result; guint n_nodes; guint i; g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL); g_return_val_if_fail (n_ids != NULL, NULL); SIGNAL_LOCK (); keys = G_BSEARCH_ARRAY_NODES (g_signal_key_bsa); n_nodes = g_signal_key_bsa->n_nodes; result = g_array_new (FALSE, FALSE, sizeof (guint)); for (i = 0; i < n_nodes; i++) if (keys[i].itype == itype) { const gchar *name = g_quark_to_string (keys[i].quark); /* Signal names with "_" in them are aliases to the same * name with "-" instead of "_". */ if (!strchr (name, '_')) g_array_append_val (result, keys[i].signal_id); } *n_ids = result->len; SIGNAL_UNLOCK (); if (!n_nodes) { /* give elaborate warnings */ if (!g_type_name (itype)) g_warning (G_STRLOC ": unable to list signals for invalid type id `%lu'", itype); else if (!G_TYPE_IS_INSTANTIATABLE (itype)) g_warning (G_STRLOC ": unable to list signals of non instantiatable type `%s'", g_type_name (itype)); else if (!g_type_class_peek (itype)) g_warning (G_STRLOC ": unable to list signals of unloaded type `%s'", g_type_name (itype)); } return (guint*) g_array_free (result, FALSE);}G_CONST_RETURN gchar*g_signal_name (guint signal_id){ SignalNode *node; gchar *name; SIGNAL_LOCK (); node = LOOKUP_SIGNAL_NODE (signal_id); name = node ? node->name : NULL; SIGNAL_UNLOCK (); return name;}voidg_signal_query (guint signal_id, GSignalQuery *query){ SignalNode *node; g_return_if_fail (query != NULL); SIGNAL_LOCK (); node = LOOKUP_SIGNAL_NODE (signal_id); if (!node || node->destroyed) query->signal_id = 0; else { query->signal_id = node->signal_id; query->signal_name = node->name; query->itype = node->itype; query->signal_flags = node->flags; query->return_type = node->return_type; query->n_params = node->n_params; query->param_types = node->param_types; } SIGNAL_UNLOCK ();}guintg_signal_new (const gchar *signal_name, GType itype, GSignalFlags signal_flags, guint class_offset, GSignalAccumulator accumulator, gpointer accu_data, GSignalCMarshaller c_marshaller, GType return_type, guint n_params, ...){ va_list args; guint signal_id; g_return_val_if_fail (signal_name != NULL, 0); va_start (args, n_params); signal_id = g_signal_new_valist (signal_name, itype, signal_flags, class_offset ? g_signal_type_cclosure_new (itype, class_offset) : NULL, accumulator, accu_data, c_marshaller, return_type, n_params, args); va_end (args); return signal_id;}static inline ClassClosure*signal_find_class_closure (SignalNode *node, GType itype){ GBSearchArray *bsa = node->class_closure_bsa; ClassClosure *cc; if (bsa) { ClassClosure key; /* cc->instance_type is 0 for default closure */ key.instance_type = itype; cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key); while (!cc && key.instance_type) { key.instance_type = g_type_parent (key.instance_type); cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key); } } else cc = NULL; return cc;}static inline GClosure*signal_lookup_closure (SignalNode *node, GTypeInstance *instance){ ClassClosure *cc; if (node->class_closure_bsa && node->class_closure_bsa->n_nodes == 1) cc = G_BSEARCH_ARRAY_NODES (node->class_closure_bsa); else cc = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance)); return cc ? cc->closure : NULL;}static voidsignal_add_class_closure (SignalNode *node, GType itype, GClosure *closure){ ClassClosure key; if (!node->class_closure_bsa) node->class_closure_bsa = g_bsearch_array_new (&g_class_closure_bconfig); key.instance_type = itype; key.closure = g_closure_ref (closure); node->class_closure_bsa = g_bsearch_array_insert (node->class_closure_bsa, &g_class_closure_bconfig, &key, FALSE); g_closure_sink (closure); if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (closure)) g_closure_set_marshal (closure, node->c_marshaller);}guintg_signal_newv (const gchar *signal_name, GType itype, GSignalFlags signal_flags, GClosure *class_closure, GSignalAccumulator accumulator, gpointer accu_data, GSignalCMarshaller c_marshaller, GType return_type, guint n_params, GType *param_types){ gchar *name; guint signal_id, i; SignalNode *node; g_return_val_if_fail (signal_name != NULL, 0); g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); if (n_params) g_return_val_if_fail (param_types != NULL, 0); g_return_val_if_fail ((return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == 0, 0); if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE)) g_return_val_if_fail (accumulator == NULL, 0); if (!accumulator) g_return_val_if_fail (accu_data == NULL, 0); name = g_strdup (signal_name); g_strdelimit (name, G_STR_DELIMITERS ":^", '_'); /* FIXME do character checks like for types */ SIGNAL_LOCK (); signal_id = signal_id_lookup (g_quark_try_string (name), itype); node = LOOKUP_SIGNAL_NODE (signal_id); if (node && !node->destroyed) { g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s", name, type_debug_name (node->itype), G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry"); g_free (name); SIGNAL_UNLOCK (); return 0; } if (node && node->itype != itype) { g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'", name, type_debug_name (itype), type_debug_name (node->itype)); g_free (name); SIGNAL_UNLOCK (); return 0; } for (i = 0; i < n_params; i++) if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) { g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type", i + 1, type_debug_name (param_types[i]), type_debug_name (itype), name); g_free (name); SIGNAL_UNLOCK (); return 0; } if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) { g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type", type_debug_name (return_type), type_debug_name (itype), name); g_free (name); SIGNAL_UNLOCK (); return 0; } if (return_type != G_TYPE_NONE && (signal_flags & (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP)) == G_SIGNAL_RUN_FIRST) { g_warning (G_STRLOC ": signal \"%s::%s\" has return type `%s' and is only G_SIGNAL_RUN_FIRST", type_debug_name (itype), name, type_debug_name (return_type)); g_free (name); SIGNAL_UNLOCK (); return 0; } /* setup permanent portion of signal node */ if (!node) { SignalKey key; signal_id = g_n_signal_nodes++; node = g_new (SignalNode, 1); node->signal_id = signal_id; g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); g_signal_nodes[signal_id] = node; node->itype = itype; node->name = name; key.itype = itype; key.quark = g_quark_from_string (node->name); key.signal_id = signal_id; g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key, FALSE); g_strdelimit (node->name, "_", '-'); key.quark = g_quark_from_static_string (node->name); g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key, FALSE); } node->destroyed = FALSE; /* setup reinitializable portion */ node->flags = signal_flags & G_SIGNAL_FLAGS_MASK; node->n_params = n_params; node->param_types = g_memdup (param_types, sizeof (GType) * n_params); node->return_type = return_type; node->class_closure_bsa = NULL; if (accumulator) { node->accumulator = g_new (SignalAccumulator, 1); node->accumulator->func = accumulator; node->accumulator->data = accu_data; } else node->accumulator = NULL; node->c_marshaller = c_marshaller; node->emission_hooks = NULL; if (class_closure) signal_add_class_closure (node, 0, class_closure); SIGNAL_UNLOCK (); return signal_id;}guintg_signal_new_valist (const gchar *signal_name, GType itype, GSignalFlags signal_flags, GClosure *class_closure, GSignalAccumulator accumulator, gpointer accu_data, GSignalCMarshaller c_marshaller, GType return_type, guint n_params, va_list args){ GType *param_types; guint i; guint signal_id; if (n_params > 0) { param_types = g_new (GType, n_params); for (i = 0; i < n_params; i++) param_types[i] = va_arg (args, GType); } else param_types = NULL; signal_id = g_signal_newv (signal_name, itype, signal_flags, class_closure, accumulator, accu_data, c_marshaller, return_type, n_params, param_types); g_free (param_types); return signal_id;}static voidsignal_destroy_R (SignalNode *signal_node){ SignalNode node = *signal_node; signal_node->destroyed = TRUE; /* reentrancy caution, zero out real contents first */ signal_node->n_params = 0; signal_node->param_types = NULL; signal_node->return_type = 0; signal_node->class_closure_bsa = NULL; signal_node->accumulator = NULL; signal_node->c_marshaller = NULL; signal_node->emission_hooks = NULL; #ifdef G_ENABLE_DEBUG /* check current emissions */ { Emission *emission; for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_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); }#endif /* free contents that need to */ SIGNAL_UNLOCK (); g_free (node.param_types); if (node.class_closure_bsa) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -