📄 gsignal.c
字号:
} mask = ~mask; for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next) if (handler->sequential_number && ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && handler->closure->meta_marshal == 0 && ((GCClosure*) handler->closure)->callback == func))) { mlist = handler_match_prepend (mlist, handler, signal_id); if (one_and_only) return mlist; } } else { GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); mask = ~mask; if (hlbsa) { guint i; for (i = 0; i < hlbsa->n_nodes; i++) { HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i); SignalNode *node = NULL; Handler *handler; if (!(mask & G_SIGNAL_MATCH_FUNC)) { node = LOOKUP_SIGNAL_NODE (hlist->signal_id); if (!node->c_marshaller) continue; } for (handler = hlist->handlers; handler; handler = handler->next) if (handler->sequential_number && ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && handler->closure->meta_marshal == 0 && ((GCClosure*) handler->closure)->callback == func))) { mlist = handler_match_prepend (mlist, handler, hlist->signal_id); if (one_and_only) return mlist; } } } } return mlist;}static inline Handler*handler_new (gboolean after){ Handler *handler = g_generic_node_alloc (&g_handler_ts, sizeof (Handler), HANDLER_PRE_ALLOC);#ifndef G_DISABLE_CHECKS if (g_handler_sequential_number < 1) g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);#endif handler->sequential_number = g_handler_sequential_number++; handler->prev = NULL; handler->next = NULL; handler->detail = 0; handler->ref_count = 1; handler->block_count = 0; handler->after = after != FALSE; handler->closure = NULL; return handler;}static inline voidhandler_ref (Handler *handler){ g_return_if_fail (handler->ref_count > 0); #ifndef G_DISABLE_CHECKS if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1) g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);#endif handler->ref_count += 1;}static inline voidhandler_unref_R (guint signal_id, gpointer instance, Handler *handler){ g_return_if_fail (handler->ref_count > 0); handler->ref_count -= 1; if (!handler->ref_count) { if (handler->next) handler->next->prev = handler->prev; if (handler->prev) /* watch out for g_signal_handlers_destroy()! */ handler->prev->next = handler->next; else { HandlerList *hlist = handler_list_lookup (signal_id, instance); hlist->handlers = handler->next; } SIGNAL_UNLOCK (); g_closure_unref (handler->closure); SIGNAL_LOCK (); g_generic_node_free (&g_handler_ts, handler); }}static voidhandler_insert (guint signal_id, gpointer instance, Handler *handler){ HandlerList *hlist; g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */ hlist = handler_list_ensure (signal_id, instance); if (!hlist->handlers) hlist->handlers = handler; else if (hlist->handlers->after && !handler->after) { handler->next = hlist->handlers; hlist->handlers->prev = handler; hlist->handlers = handler; } else { Handler *tmp = hlist->handlers; if (handler->after) while (tmp->next) tmp = tmp->next; else while (tmp->next && !tmp->next->after) tmp = tmp->next; if (tmp->next) tmp->next->prev = handler; handler->next = tmp->next; handler->prev = tmp; tmp->next = handler; }}static inline voidemission_push (Emission **emission_list_p, Emission *emission){ emission->next = *emission_list_p; *emission_list_p = emission;}static inline voidemission_pop (Emission **emission_list_p, Emission *emission){ Emission *node, *last = NULL; for (node = *emission_list_p; node; last = node, node = last->next) if (node == emission) { if (last) last->next = node->next; else *emission_list_p = node->next; return; } g_assert_not_reached ();}static inline Emission*emission_find (Emission *emission_list, guint signal_id, GQuark detail, gpointer instance){ Emission *emission; for (emission = emission_list; emission; emission = emission->next) if (emission->instance == instance && emission->ihint.signal_id == signal_id && emission->ihint.detail == detail) return emission; return NULL;}static inline Emission*emission_find_innermost (gpointer instance){ Emission *emission, *s = NULL, *c = NULL; 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) 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);}static gintsignal_key_cmp (gconstpointer node1, gconstpointer node2){ const SignalKey *key1 = node1, *key2 = node2; if (key1->itype == key2->itype) return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark); else return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);}voidg_signal_init (void) /* sync with gtype.c */{ SIGNAL_LOCK (); if (!g_n_signal_nodes) { /* handler_id_node_prepend() requires this */ g_assert (sizeof (GList) == sizeof (HandlerMatch)); /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */ g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL); g_signal_key_bsa = g_bsearch_array_new (&g_signal_key_bconfig); /* invalid (0) signal_id */ g_n_signal_nodes = 1; g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); g_signal_nodes[0] = NULL; } SIGNAL_UNLOCK ();}void_g_signals_destroy (GType itype){ guint i; SIGNAL_LOCK (); for (i = 1; i < g_n_signal_nodes; i++) { SignalNode *node = g_signal_nodes[i]; if (node->itype == itype) { if (node->destroyed) g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed", node->name, type_debug_name (node->itype)); else signal_destroy_R (node); } } SIGNAL_UNLOCK ();}voidg_signal_stop_emission (gpointer instance, guint signal_id, GQuark detail){ SignalNode *node; 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 && 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; } 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); 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 id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); SIGNAL_UNLOCK ();}static voidsignal_finalize_hook (GHookList *hook_list, GHook *hook){ GDestroyNotify destroy = hook->destroy; if (destroy) { hook->destroy = NULL; SIGNAL_UNLOCK (); destroy (hook->data); SIGNAL_LOCK (); }}gulongg_signal_add_emission_hook (guint signal_id, GQuark detail, GSignalEmissionHook hook_func, gpointer hook_data, GDestroyNotify data_destroy){ static gulong seq_hook_id = 1; SignalNode *node; GHook *hook; SignalHook *signal_hook; g_return_val_if_fail (signal_id > 0, 0); g_return_val_if_fail (hook_func != NULL, 0); SIGNAL_LOCK (); node = LOOKUP_SIGNAL_NODE (signal_id); if (!node || node->destroyed || (node->flags & G_SIGNAL_NO_HOOKS)) { g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id); SIGNAL_UNLOCK (); return 0; } 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 0; } if (!node->emission_hooks) { node->emission_hooks = g_new (GHookList, 1); g_hook_list_init (node->emission_hooks, sizeof (SignalHook)); node->emission_hooks->finalize_hook = signal_finalize_hook; } hook = g_hook_alloc (node->emission_hooks); hook->data = hook_data; hook->func = (gpointer) hook_func; hook->destroy = data_destroy; signal_hook = SIGNAL_HOOK (hook); signal_hook->detail = detail; node->emission_hooks->seq_id = seq_hook_id; g_hook_append (node->emission_hooks, hook); seq_hook_id = node->emission_hooks->seq_id; SIGNAL_UNLOCK (); return hook->hook_id;}voidg_signal_remove_emission_hook (guint signal_id, gulong hook_id){ SignalNode *node; g_return_if_fail (signal_id > 0); g_return_if_fail (hook_id > 0); SIGNAL_LOCK (); node = LOOKUP_SIGNAL_NODE (signal_id); if (!node || node->destroyed) g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id); else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id)) g_warning ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id); SIGNAL_UNLOCK ();}static inline guintsignal_parse_name (const gchar *name, GType itype, GQuark *detail_p, gboolean force_quark){ const gchar *colon = strchr (name, ':'); guint signal_id; if (!colon) { signal_id = signal_id_lookup (g_quark_try_string (name), itype); if (signal_id && detail_p) *detail_p = 0; } else if (colon[1] == ':') { gchar buffer[32]; guint l = colon - name; if (l < 32) { memcpy (buffer, name, l); buffer[l] = 0; signal_id = signal_id_lookup (g_quark_try_string (buffer), itype); } else { gchar *signal = g_new (gchar, l + 1); memcpy (signal, name, l); signal[l] = 0; signal_id = signal_id_lookup (g_quark_try_string (signal), itype); g_free (signal); } if (signal_id && detail_p) *detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0; } else signal_id = 0; return signal_id;}gbooleang_signal_parse_name (const gchar *detailed_signal, GType itype, guint *signal_id_p, GQuark *detail_p, gboolean force_detail_quark){ SignalNode *node; GQuark detail = 0; guint signal_id; g_return_val_if_fail (detailed_signal != NULL, FALSE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -