📄 gsignal.c
字号:
g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE); if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { SIGNAL_LOCK (); n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, closure, func, data, g_signal_handler_block); SIGNAL_UNLOCK (); } return n_handlers;}guintg_signal_handlers_unblock_matched (gpointer instance, GSignalMatchType mask, guint signal_id, GQuark detail, GClosure *closure, gpointer func, gpointer data){ guint n_handlers = 0; g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE); if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { SIGNAL_LOCK (); n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, closure, func, data, g_signal_handler_unblock); SIGNAL_UNLOCK (); } return n_handlers;}guintg_signal_handlers_disconnect_matched (gpointer instance, GSignalMatchType mask, guint signal_id, GQuark detail, GClosure *closure, gpointer func, gpointer data){ guint n_handlers = 0; g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE); if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { SIGNAL_LOCK (); n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, closure, func, data, g_signal_handler_disconnect); SIGNAL_UNLOCK (); } return n_handlers;}gbooleang_signal_has_handler_pending (gpointer instance, guint signal_id, GQuark detail, gboolean may_be_blocked){ HandlerMatch *mlist; gboolean has_pending; g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); g_return_val_if_fail (signal_id > 0, FALSE); SIGNAL_LOCK (); if (detail) { SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); if (!(node->flags & G_SIGNAL_DETAILED)) { g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); SIGNAL_UNLOCK (); return FALSE; } } mlist = handlers_find (instance, (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)), signal_id, detail, NULL, NULL, NULL, TRUE); if (mlist) { has_pending = TRUE; handler_match_free1_R (mlist, instance); } else has_pending = FALSE; SIGNAL_UNLOCK (); return has_pending;}voidg_signal_emitv (const GValue *instance_and_params, guint signal_id, GQuark detail, GValue *return_value){ const GValue *param_values; gpointer instance; SignalNode *node;#ifdef G_ENABLE_DEBUG guint i;#endif g_return_if_fail (instance_and_params != NULL); instance = g_value_peek_pointer (instance_and_params); g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (signal_id > 0); param_values = instance_and_params + 1; SIGNAL_LOCK (); node = LOOKUP_SIGNAL_NODE (signal_id); if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) { g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); SIGNAL_UNLOCK (); return; }#ifdef G_ENABLE_DEBUG if (detail && !(node->flags & G_SIGNAL_DETAILED)) { g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); SIGNAL_UNLOCK (); return; } for (i = 0; i < node->n_params; i++) if (!G_TYPE_CHECK_VALUE_TYPE (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) { g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'", G_STRLOC, type_debug_name (node->param_types[i]), i, node->name, G_VALUE_TYPE_NAME (param_values + i)); SIGNAL_UNLOCK (); return; } if (node->return_type != G_TYPE_NONE) { if (!return_value) { g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)", G_STRLOC, type_debug_name (node->return_type), node->name); SIGNAL_UNLOCK (); return; } else if (!node->accumulator && !G_TYPE_CHECK_VALUE_TYPE (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) { g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'", G_STRLOC, type_debug_name (node->return_type), node->name, G_VALUE_TYPE_NAME (return_value)); SIGNAL_UNLOCK (); return; } } else return_value = NULL;#endif /* G_ENABLE_DEBUG */ SIGNAL_UNLOCK (); signal_emit_unlocked_R (node, detail, instance, return_value, instance_and_params);}voidg_signal_emit_valist (gpointer instance, guint signal_id, GQuark detail, va_list var_args){ GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL; GType signal_return_type; GValue *param_values; SignalNode *node; guint i, n_params; g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (signal_id > 0); SIGNAL_LOCK (); node = LOOKUP_SIGNAL_NODE (signal_id); if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) { g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); SIGNAL_UNLOCK (); return; }#ifndef G_DISABLE_CHECKS if (detail && !(node->flags & G_SIGNAL_DETAILED)) { g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); SIGNAL_UNLOCK (); return; }#endif /* !G_DISABLE_CHECKS */ n_params = node->n_params; signal_return_type = node->return_type; if (node->n_params < MAX_STACK_VALUES) instance_and_params = stack_values; else { free_me = g_new (GValue, node->n_params + 1); instance_and_params = free_me; } param_values = instance_and_params + 1; for (i = 0; i < node->n_params; i++) { gchar *error; GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE; gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE; param_values[i].g_type = 0; SIGNAL_UNLOCK (); g_value_init (param_values + i, ptype); G_VALUE_COLLECT (param_values + i, var_args, static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, &error); if (error) { g_warning ("%s: %s", G_STRLOC, error); g_free (error); /* we purposely leak the value here, it might not be * in a sane state if an error condition occoured */ while (i--) g_value_unset (param_values + i); g_free (free_me); return; } SIGNAL_LOCK (); } 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); if (signal_return_type == G_TYPE_NONE) signal_emit_unlocked_R (node, detail, instance, NULL, instance_and_params); else { GValue return_value = { 0, }; gchar *error = NULL; GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE; gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE; g_value_init (&return_value, rtype); signal_emit_unlocked_R (node, detail, instance, &return_value, instance_and_params); G_VALUE_LCOPY (&return_value, var_args, static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, &error); if (!error) g_value_unset (&return_value); else { g_warning ("%s: %s", G_STRLOC, error); g_free (error); /* we purposely leak the value here, it might not be * in a sane state if an error condition occoured */ } } for (i = 0; i < n_params; i++) g_value_unset (param_values + i); g_value_unset (instance_and_params); if (free_me) g_free (free_me);}voidg_signal_emit (gpointer instance, guint signal_id, GQuark detail, ...){ va_list var_args; va_start (var_args, detail); g_signal_emit_valist (instance, signal_id, detail, var_args); va_end (var_args);}voidg_signal_emit_by_name (gpointer instance, const gchar *detailed_signal, ...){ GQuark detail = 0; guint signal_id; g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (detailed_signal != NULL); SIGNAL_LOCK (); signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE); SIGNAL_UNLOCK (); if (signal_id) { va_list var_args; va_start (var_args, detailed_signal); g_signal_emit_valist (instance, signal_id, detail, var_args); va_end (var_args); } else g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);}static inline gbooleanaccumulate (GSignalInvocationHint *ihint, GValue *return_accu, GValue *handler_return, SignalAccumulator *accumulator){ gboolean continue_emission; if (!accumulator) return TRUE; continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data); g_value_reset (handler_return); return continue_emission;}static gbooleansignal_emit_unlocked_R (SignalNode *node, GQuark detail, gpointer instance, GValue *emission_return, const GValue *instance_and_params){ SignalAccumulator *accumulator; Emission emission; GClosure *class_closure; HandlerList *hlist; Handler *handler_list = NULL; GValue *return_accu, accu = { 0, }; guint signal_id; gulong max_sequential_handler_number; gboolean return_value_altered = FALSE; #ifdef G_ENABLE_DEBUG IF_DEBUG (SIGNALS, g_trace_instance_signals == instance || g_trap_instance_signals == instance) { g_message ("%s::%s(%u) emitted (instance=%p, signal-node=%p)", g_type_name (G_TYPE_FROM_INSTANCE (instance)), node->name, detail, instance, node); if (g_trap_instance_signals == instance) G_BREAKPOINT (); }#endif /* G_ENABLE_DEBUG */ SIGNAL_LOCK (); signal_id = node->signal_id; if (node->flags & G_SIGNAL_NO_RECURSE) { Emission *node = emission_find (g_restart_emissions, signal_id, detail, instance); if (node) { node->state = EMISSION_RESTART; SIGNAL_UNLOCK (); return return_value_altered; } } accumulator = node->accumulator; if (accumulator) { SIGNAL_UNLOCK (); g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); return_accu = &accu; SIGNAL_LOCK (); } else return_accu = emission_return; emission.instance = instance; emission.ihint.signal_id = node->signal_id; emission.ihint.detail = detail; 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); class_closure = signal_lookup_closure (node, instance); EMIT_RESTART: if (handler_list) handler_unref_R (signal_id, instance, handler_list); max_sequential_handler_number = g_handler_sequential_number; hlist = handler_list_lookup (signal_id, instance); handler_list = hlist ? hlist->handlers : NULL; if (handler_list) handler_ref (handler_list); emission.ihint.run_type = G_SIGNAL_RUN_FIRST; if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure) { emission.state = EMISSION_RUN; emission.chain_type = G_TYPE_FROM_INSTANCE (instance); SIGNAL_UNLOCK (); g_closure_invoke (class_closure, return_accu, node->n_params + 1, instance_and_params, &emission.ihint); if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && emission.state == EMISSION_RUN) emission.state = EMISSION_STOP; SIGNAL_LOCK (); emission.chain_type = G_TYPE_NONE; return_value_altered = TRUE; if (emission.state == EMISSION_STOP) goto EMIT_CLEANUP; else if (emission.state == EMISSION_RESTART) goto EMIT_RESTART; } if (node->emission_hooks) { gboolean need_destroy, was_in_call, may_recurse = TRUE; GHook *hook; emission.state = EMISSION_HOOK; hook = g_hook_first_valid (node->emission_hooks, may_recurse); while (hook) { SignalHook *signal_hook = SIGNAL_HOOK (hook); if (!signal_hook->detail || signal_hook->detail == detail)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -