1 /* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 2000 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General
15 * Public License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17 * Boston, MA 02111-1307, USA.
19 * this code is based on the original GtkSignal implementation
20 * for the Gtk+ library by Peter Mattis <petm@xcf.berkeley.edu>
26 #include "gbsearcharray.h"
29 /* pre allocation configurations
31 #define BSA_PRE_ALLOC (20)
32 #define HANDLER_PRE_ALLOC (48)
33 #define EMISSION_PRE_ALLOC (16)
35 #define TIGHT_MEMORY (1)
37 #define REPORT_BUG "please report occourance circumstances to gtk-devel-list@gnome.org"
40 /* --- generic allocation --- */
41 /* we can special case allocations generically by replacing
42 * these functions with more speed/memory aware variants
44 static inline gpointer
45 g_generic_node_alloc (GTrashStack **trash_stack_p,
47 guint nodes_pre_alloc)
49 gpointer node = g_trash_stack_pop (trash_stack_p);
55 nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
56 block = g_malloc (sizeof_node * nodes_pre_alloc);
57 while (--nodes_pre_alloc)
59 g_trash_stack_push (trash_stack_p, block);
68 g_generic_node_free (GTrashStack **trash_stack_p,
71 g_trash_stack_push (trash_stack_p, node);
75 /* --- typedefs --- */
76 typedef struct _SignalNode SignalNode;
77 typedef struct _SignalKey SignalKey;
78 typedef struct _Emission Emission;
79 typedef struct _Handler Handler;
80 typedef struct _HandlerList HandlerList;
81 typedef struct _HandlerMatch HandlerMatch;
91 /* --- prototypes --- */
92 static inline guint signal_id_lookup (GQuark quark,
94 static void signal_destroy_R (SignalNode *signal_node);
95 static inline HandlerList* handler_list_ensure (guint signal_id,
97 static inline HandlerList* handler_list_lookup (guint signal_id,
99 static inline Handler* handler_new (gboolean after);
100 static void handler_insert (guint signal_id,
103 static Handler* handler_lookup (gpointer instance,
106 static inline HandlerMatch* handler_match_prepend (HandlerMatch *list,
109 static inline HandlerMatch* handler_match_free1_R (HandlerMatch *node,
111 static HandlerMatch* handlers_find (gpointer instance,
112 GSignalMatchType mask,
118 gboolean one_and_only);
119 static inline void handler_ref (Handler *handler);
120 static inline void handler_unref_R (guint signal_id,
123 static inline void emission_push (Emission **emission_list_p,
127 EmissionState *state_p);
128 static inline void emission_pop (Emission **emission_list_p,
129 EmissionState *state_p);
130 static inline Emission* emission_find (Emission *emission_list,
134 static void signal_emit_R (SignalNode *node,
137 GValue *return_value,
138 const GValue *instance_and_params);
141 /* --- structures --- */
144 /* permanent portion */
150 /* reinitializable portion */
155 GClosure *class_closure;
156 GSignalAccumulator accumulator;
157 GSignalCMarshaller c_marshaller;
158 GHookList *emission_hooks;
174 EmissionState *state_p;
188 guint ref_count : 16;
189 #define HANDLER_MAX_REF_COUNT (1 << 16)
190 guint block_count : 12;
191 #define HANDLER_MAX_BLOCK_COUNT (1 << 12)
206 /* --- variables --- */
207 static GBSearchArray g_signal_key_bsa = { NULL, 0, 0, 0, NULL };
208 static GHashTable *g_handler_list_bsa_ht = NULL;
209 static Emission *g_recursive_emissions = NULL;
210 static Emission *g_restart_emissions = NULL;
211 static GTrashStack *g_bsa_ts = NULL;
212 static GTrashStack *g_handler_ts = NULL;
213 static GTrashStack *g_emission_ts = NULL;
214 G_LOCK_DEFINE_STATIC (g_signal_mutex);
217 /* --- signal nodes --- */
218 static guint g_n_signal_nodes = 0;
219 static SignalNode **g_signal_nodes = NULL;
221 static inline SignalNode*
222 LOOKUP_SIGNAL_NODE (register guint signal_id)
224 if (signal_id < g_n_signal_nodes)
225 return g_signal_nodes[signal_id];
231 /* --- functions --- */
233 signal_id_lookup (GQuark quark,
238 SignalKey key, *signal_key;
243 signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
246 return signal_key->signal_id;
248 itype = g_type_parent (itype);
256 handler_lists_cmp (gconstpointer node1,
259 const HandlerList *hlist1 = node1, *hlist2 = node2;
261 return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
264 static inline HandlerList*
265 handler_list_ensure (guint signal_id,
268 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
273 hlbsa = g_generic_node_alloc (&g_bsa_ts,
274 sizeof (GBSearchArray),
276 hlbsa->cmp_func = handler_lists_cmp;
277 hlbsa->sizeof_node = sizeof (HandlerList);
278 hlbsa->flags = G_BSEARCH_DEFER_SHRINK;
281 g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
283 key.signal_id = signal_id;
286 return g_bsearch_array_insert (hlbsa, &key, FALSE);
289 static inline HandlerList*
290 handler_list_lookup (guint signal_id,
293 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
296 key.signal_id = signal_id;
298 return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL;
302 handler_lookup (gpointer instance,
306 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
312 for (i = 0; i < hlbsa->n_nodes; i++)
314 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
317 for (handler = hlist->handlers; handler; handler = handler->next)
318 if (handler->id == handler_id)
321 *signal_id_p = hlist->signal_id;
331 static inline HandlerMatch*
332 handler_match_prepend (HandlerMatch *list,
338 /* yeah, we could use our own memchunk here, introducing yet more
339 * rarely used cached nodes and extra allocation overhead.
340 * instead, we use GList* nodes, since they are exactly the size
341 * we need and are already cached. g_signal_init() asserts this.
343 node = (HandlerMatch*) g_list_alloc ();
344 node->handler = handler;
346 node->d.signal_id = signal_id;
347 handler_ref (handler);
351 static inline HandlerMatch*
352 handler_match_free1_R (HandlerMatch *node,
355 HandlerMatch *next = node->next;
357 handler_unref_R (node->d.signal_id, instance, node->handler);
358 g_list_free_1 ((GList*) node);
364 handlers_find (gpointer instance,
365 GSignalMatchType mask,
371 gboolean one_and_only)
373 HandlerMatch *mlist = NULL;
375 if (mask & G_SIGNAL_MATCH_ID)
377 HandlerList *hlist = handler_list_lookup (signal_id, instance);
379 SignalNode *node = NULL;
381 if (!(mask & G_SIGNAL_MATCH_FUNC))
383 node = LOOKUP_SIGNAL_NODE (signal_id);
384 if (!node || !node->c_marshaller)
389 for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
391 ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
392 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
393 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
394 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
395 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
396 handler->closure->meta_marshal == 0 &&
397 ((GCClosure*) handler->closure)->callback == func)))
399 mlist = handler_match_prepend (mlist, handler, signal_id);
406 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
413 for (i = 0; i < hlbsa->n_nodes; i++)
415 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
416 SignalNode *node = NULL;
419 if (!(mask & G_SIGNAL_MATCH_FUNC))
421 node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
422 if (!node->c_marshaller)
426 for (handler = hlist->handlers; handler; handler = handler->next)
428 ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
429 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
430 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
431 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
432 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
433 handler->closure->meta_marshal == 0 &&
434 ((GCClosure*) handler->closure)->callback == func)))
436 mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
447 static inline Handler*
448 handler_new (gboolean after)
450 static guint handler_id = 1;
451 Handler *handler = g_generic_node_alloc (&g_handler_ts,
454 #ifndef G_DISABLE_CHECKS
456 g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
459 handler->id = handler_id++;
460 handler->prev = NULL;
461 handler->next = NULL;
463 handler->ref_count = 1;
464 handler->block_count = 0;
465 handler->after = after != FALSE;
466 handler->closure = NULL;
472 handler_ref (Handler *handler)
474 g_return_if_fail (handler->ref_count > 0);
476 #ifndef G_DISABLE_CHECKS
477 if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
478 g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
481 handler->ref_count += 1;
485 handler_unref_R (guint signal_id,
489 g_return_if_fail (handler->ref_count > 0);
491 handler->ref_count -= 1;
492 if (!handler->ref_count)
495 handler->next->prev = handler->prev;
496 if (handler->prev) /* watch out for g_signal_handlers_destroy()! */
497 handler->prev->next = handler->next;
500 HandlerList *hlist = handler_list_lookup (signal_id, instance);
502 hlist->handlers = handler->next;
504 G_UNLOCK (g_signal_mutex);
505 g_closure_unref (handler->closure);
506 G_LOCK (g_signal_mutex);
507 g_generic_node_free (&g_handler_ts, handler);
512 handler_insert (guint signal_id,
518 g_assert (handler->prev == NULL && handler->next == NULL); // FIXME: paranoid
520 hlist = handler_list_ensure (signal_id, instance);
521 if (!hlist->handlers)
522 hlist->handlers = handler;
523 else if (hlist->handlers->after && !handler->after)
525 handler->next = hlist->handlers;
526 hlist->handlers->prev = handler;
527 hlist->handlers = handler;
531 Handler *tmp = hlist->handlers;
537 while (tmp->next && !tmp->next->after)
540 tmp->next->prev = handler;
541 handler->next = tmp->next;
548 emission_push (Emission **emission_list_p,
552 EmissionState *state_p)
554 Emission *emission = g_generic_node_alloc (&g_emission_ts,
557 emission->next = *emission_list_p;
558 emission->signal_id = signal_id;
559 emission->detail = detail;
560 emission->instance = instance;
561 emission->state_p = state_p;
562 *emission_list_p = emission;
566 emission_pop (Emission **emission_list_p,
567 EmissionState *state_p)
569 Emission **loc = emission_list_p, *emission = *loc;
571 while (emission->state_p != state_p)
573 loc = &emission->next;
576 *loc = emission->next;
577 g_generic_node_free (&g_emission_ts, emission);
580 static inline Emission*
581 emission_find (Emission *emission_list,
588 for (emission = emission_list; emission; emission = emission->next)
589 if (emission->instance == instance &&
590 emission->signal_id == signal_id &&
591 emission->detail == detail)
597 signal_key_cmp (gconstpointer node1,
600 const SignalKey *key1 = node1, *key2 = node2;
602 if (key1->itype == key2->itype)
603 return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
605 return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
609 g_signal_init (void) /* sync with gtype.c */
611 G_LOCK (g_signal_mutex);
612 if (!g_n_signal_nodes)
614 /* handler_id_node_prepend() requires this */
615 g_assert (sizeof (GList) == sizeof (HandlerMatch));
617 /* setup signal key array */
618 g_signal_key_bsa.cmp_func = signal_key_cmp;
619 g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
620 g_signal_key_bsa.flags = 0; /* alloc-only */
622 /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
623 g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
625 /* invalid (0) signal_id */
626 g_n_signal_nodes = 1;
627 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
628 g_signal_nodes[0] = NULL;
630 G_UNLOCK (g_signal_mutex);
634 _g_signals_destroy (GType itype)
638 G_LOCK (g_signal_mutex);
639 for (i = 1; i < g_n_signal_nodes; i++)
641 SignalNode *node = g_signal_nodes[i];
643 if (node->itype == itype)
646 g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
648 g_type_name (node->itype));
650 signal_destroy_R (node);
653 G_UNLOCK (g_signal_mutex);
657 g_signal_stop_emission (gpointer instance,
663 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
664 g_return_if_fail (signal_id > 0);
666 G_LOCK (g_signal_mutex);
667 node = LOOKUP_SIGNAL_NODE (signal_id);
668 if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
670 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
671 G_UNLOCK (g_signal_mutex);
674 if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
676 Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
677 Emission *emission = emission_find (emission_list, signal_id, detail, instance);
681 if (*emission->state_p == EMISSION_HOOK)
682 g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
683 node->name, instance);
684 else if (*emission->state_p == EMISSION_RUN)
685 *emission->state_p = EMISSION_STOP;
688 g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
689 node->name, instance);
692 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
693 G_UNLOCK (g_signal_mutex);
697 signal_parse_name (const gchar *name,
700 gboolean force_quark)
702 const gchar *colon = strchr (name, ':');
707 signal_id = signal_id_lookup (g_quark_try_string (name), itype);
708 if (signal_id && detail_p)
711 else if (colon[1] == ':')
714 guint l = colon - name;
718 memcpy (buffer, name, l);
720 signal_id = signal_id_lookup (g_quark_try_string (buffer), itype);
724 gchar *signal = g_new (gchar, l + 1);
726 memcpy (signal, name, l);
728 signal_id = signal_id_lookup (g_quark_try_string (signal), itype);
732 if (signal_id && detail_p)
733 *detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0;
741 g_signal_parse_name (const gchar *detailed_signal,
745 gboolean force_detail_quark)
750 g_return_val_if_fail (detailed_signal != NULL, FALSE);
751 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
753 G_LOCK (g_signal_mutex);
754 signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
755 G_UNLOCK (g_signal_mutex);
760 *signal_id_p = signal_id;
771 g_signal_lookup (const gchar *name,
776 g_return_val_if_fail (name != NULL, 0);
777 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
779 G_LOCK (g_signal_mutex);
780 signal_id = signal_id_lookup (g_quark_try_string (name), itype);
781 G_UNLOCK (g_signal_mutex);
787 g_signal_name (guint signal_id)
792 G_LOCK (g_signal_mutex);
793 node = LOOKUP_SIGNAL_NODE (signal_id);
794 name = node ? node->name : NULL;
795 G_UNLOCK (g_signal_mutex);
801 g_signal_query (guint signal_id,
806 g_return_if_fail (query != NULL);
808 G_LOCK (g_signal_mutex);
809 node = LOOKUP_SIGNAL_NODE (signal_id);
810 if (!node || node->destroyed)
811 query->signal_id = 0;
814 query->signal_id = node->signal_id;
815 query->signal_name = node->name;
816 query->itype = node->itype;
817 query->signal_flags = node->flags;
818 query->return_type = node->return_type;
819 query->n_params = node->n_params;
820 query->param_types = node->param_types;
822 G_UNLOCK (g_signal_mutex);
826 g_signal_list_ids (GType itype,
834 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
835 g_return_val_if_fail (n_ids != NULL, NULL);
837 G_LOCK (g_signal_mutex);
839 keys = g_signal_key_bsa.nodes;
840 n_nodes = g_signal_key_bsa.n_nodes;
841 result = g_array_new (FALSE, FALSE, sizeof (guint));
843 for (i = 0; i < n_nodes; i++)
844 if (keys[i].itype == itype)
846 gchar *name = g_quark_to_string (keys[i].quark);
848 /* Signal names with "_" in them are aliases to the same
849 * name with "-" instead of "_".
851 if (!strchr (name, '_'))
852 g_array_append_val (result, keys[i].signal_id);
855 *n_ids = result->len;
857 G_UNLOCK (g_signal_mutex);
859 return (guint *) g_array_free (result, FALSE);
863 g_signal_newv (const gchar *signal_name,
865 GSignalFlags signal_flags,
866 GClosure *class_closure,
867 GSignalAccumulator accumulator,
868 GSignalCMarshaller c_marshaller,
877 g_return_val_if_fail (signal_name != NULL, 0);
878 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
880 g_return_val_if_fail (param_types != NULL, 0);
881 if (return_type != G_TYPE_NONE)
882 g_return_val_if_fail (accumulator == NULL, 0);
884 name = g_strdup (signal_name);
885 g_strdelimit (name, G_STR_DELIMITERS ":^", '_'); // FIXME do character checks like for types
887 G_LOCK (g_signal_mutex);
889 signal_id = signal_id_lookup (g_quark_try_string (name), itype);
890 node = LOOKUP_SIGNAL_NODE (signal_id);
891 if (node && !node->destroyed)
893 g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
895 g_type_name (node->itype),
896 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
898 G_UNLOCK (g_signal_mutex);
901 if (node && node->itype != itype)
903 g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
906 g_type_name (node->itype));
908 G_UNLOCK (g_signal_mutex);
911 for (i = 0; i < n_params; i++)
912 if (!G_TYPE_IS_VALUE (param_types[i]) ||
913 param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */
915 g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
916 i + 1, g_type_name (param_types[i]), g_type_name (itype), name);
918 G_UNLOCK (g_signal_mutex);
921 if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type))
923 g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
924 g_type_name (param_types[i]), g_type_name (itype), name);
926 G_UNLOCK (g_signal_mutex);
930 /* setup permanent portion of signal node */
935 signal_id = g_n_signal_nodes++;
936 node = g_new (SignalNode, 1);
937 node->signal_id = signal_id;
938 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
939 g_signal_nodes[signal_id] = node;
943 key.quark = g_quark_from_string (node->name);
944 key.signal_id = signal_id;
945 g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
946 g_strdelimit (node->name, "_", '-');
947 key.quark = g_quark_from_static_string (node->name);
948 g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
950 node->destroyed = FALSE;
952 /* setup reinitializable portion */
953 node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
954 node->n_params = n_params;
955 node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
956 node->return_type = return_type;
957 node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL;
958 node->accumulator = accumulator;
959 node->c_marshaller = c_marshaller;
960 node->emission_hooks = NULL;
961 if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure))
962 g_closure_set_marshal (class_closure, node->c_marshaller);
964 G_UNLOCK (g_signal_mutex);
969 signal_destroy_R (SignalNode *signal_node)
971 SignalNode node = *signal_node;
973 signal_node->destroyed = TRUE;
975 /* reentrancy caution, zero out real contents first */
976 signal_node->n_params = 0;
977 signal_node->param_types = NULL;
978 signal_node->return_type = 0;
979 signal_node->class_closure = NULL;
980 signal_node->accumulator = NULL;
981 signal_node->c_marshaller = NULL;
982 signal_node->emission_hooks = NULL;
984 #ifndef G_DISABLE_CHECKS
985 /* check current emissions */
989 for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
990 emission; emission = emission->next)
991 if (emission->signal_id == node.signal_id)
992 g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
993 node.name, emission->instance);
997 /* free contents that need to
999 G_UNLOCK (g_signal_mutex);
1000 g_free (node.param_types);
1001 g_closure_unref (node.class_closure);
1002 if (node.emission_hooks)
1004 g_hook_list_clear (node.emission_hooks);
1005 g_free (node.emission_hooks);
1007 G_LOCK (g_signal_mutex);
1011 g_signal_connect_closure_by_id (gpointer instance,
1018 guint handler_id = 0;
1020 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1021 g_return_val_if_fail (signal_id > 0, 0);
1022 g_return_val_if_fail (closure != NULL, 0);
1024 G_LOCK (g_signal_mutex);
1025 node = LOOKUP_SIGNAL_NODE (signal_id);
1026 if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
1028 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1029 G_UNLOCK (g_signal_mutex);
1032 if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
1034 Handler *handler = handler_new (after);
1036 handler_id = handler->id;
1037 handler->detail = detail;
1038 handler->closure = g_closure_ref (closure);
1039 handler_insert (signal_id, instance, handler);
1040 if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
1041 g_closure_set_marshal (closure, node->c_marshaller);
1044 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1045 G_UNLOCK (g_signal_mutex);
1051 g_signal_handler_block (gpointer instance,
1056 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1057 g_return_if_fail (handler_id > 0);
1059 G_LOCK (g_signal_mutex);
1060 handler = handler_lookup (instance, handler_id, NULL);
1063 #ifndef G_DISABLE_CHECKS
1064 if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
1065 g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
1068 handler->block_count += 1;
1071 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1072 G_UNLOCK (g_signal_mutex);
1076 g_signal_handler_unblock (gpointer instance,
1081 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1082 g_return_if_fail (handler_id > 0);
1084 G_LOCK (g_signal_mutex);
1085 handler = handler_lookup (instance, handler_id, NULL);
1088 if (handler->block_count)
1089 handler->block_count -= 1;
1091 g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance);
1094 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1095 G_UNLOCK (g_signal_mutex);
1099 g_signal_handler_disconnect (gpointer instance,
1105 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1106 g_return_if_fail (handler_id > 0);
1108 G_LOCK (g_signal_mutex);
1109 handler = handler_lookup (instance, handler_id, &signal_id);
1113 handler->block_count = 1;
1114 handler_unref_R (signal_id, instance, handler);
1117 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1118 G_UNLOCK (g_signal_mutex);
1122 g_signal_handlers_destroy (gpointer instance)
1124 GBSearchArray *hlbsa;
1126 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1128 G_LOCK (g_signal_mutex);
1129 hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
1134 /* reentrancy caution, delete instance trace first */
1135 g_hash_table_remove (g_handler_list_bsa_ht, instance);
1137 for (i = 0; i < hlbsa->n_nodes; i++)
1139 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
1140 Handler *handler = hlist->handlers;
1144 Handler *tmp = handler;
1146 handler = tmp->next;
1147 tmp->block_count = 1;
1148 /* cruel unlink, this works because _all_ handlers vanish */
1154 handler_unref_R (0, NULL, tmp);
1158 g_free (hlbsa->nodes);
1159 g_generic_node_free (&g_bsa_ts, hlbsa);
1161 G_UNLOCK (g_signal_mutex);
1165 g_signal_handler_find (gpointer instance,
1166 GSignalMatchType mask,
1173 guint handler_id = 0;
1175 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1176 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1178 if (mask & G_SIGNAL_MATCH_MASK)
1180 HandlerMatch *mlist;
1182 G_LOCK (g_signal_mutex);
1183 mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
1186 handler_id = mlist->handler->id;
1187 handler_match_free1_R (mlist, instance);
1189 G_UNLOCK (g_signal_mutex);
1196 signal_handlers_foreach_matched_R (gpointer instance,
1197 GSignalMatchType mask,
1203 void (*callback) (gpointer instance,
1206 HandlerMatch *mlist;
1207 guint n_handlers = 0;
1209 mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
1213 G_UNLOCK (g_signal_mutex);
1214 callback (instance, mlist->handler->id);
1215 G_LOCK (g_signal_mutex);
1216 mlist = handler_match_free1_R (mlist, instance);
1223 g_signal_handlers_block_matched (gpointer instance,
1224 GSignalMatchType mask,
1231 guint n_handlers = 0;
1233 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1234 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1236 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1238 G_LOCK (g_signal_mutex);
1239 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1240 closure, func, data,
1241 g_signal_handler_block);
1242 G_UNLOCK (g_signal_mutex);
1249 g_signal_handlers_unblock_matched (gpointer instance,
1250 GSignalMatchType mask,
1257 guint n_handlers = 0;
1259 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1260 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1262 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1264 G_LOCK (g_signal_mutex);
1265 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1266 closure, func, data,
1267 g_signal_handler_unblock);
1268 G_UNLOCK (g_signal_mutex);
1275 g_signal_handlers_disconnect_matched (gpointer instance,
1276 GSignalMatchType mask,
1283 guint n_handlers = 0;
1285 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1286 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1288 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1290 G_LOCK (g_signal_mutex);
1291 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1292 closure, func, data,
1293 g_signal_handler_disconnect);
1294 G_UNLOCK (g_signal_mutex);
1301 g_signal_has_handler_pending (gpointer instance,
1304 gboolean may_be_blocked)
1306 HandlerMatch *mlist;
1307 gboolean has_pending;
1309 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1310 g_return_val_if_fail (signal_id > 0, FALSE);
1312 G_LOCK (g_signal_mutex);
1315 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1317 if (!(node->flags & G_SIGNAL_DETAILED))
1319 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1320 G_UNLOCK (g_signal_mutex);
1324 mlist = handlers_find (instance,
1325 (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
1326 signal_id, detail, NULL, NULL, NULL, TRUE);
1330 handler_match_free1_R (mlist, instance);
1333 has_pending = FALSE;
1334 G_UNLOCK (g_signal_mutex);
1340 g_signal_emitv (const GValue *instance_and_params,
1343 GValue *return_value)
1347 const GValue *param_values;
1350 g_return_if_fail (instance_and_params != NULL);
1351 instance = g_value_get_as_pointer (instance_and_params);
1352 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1353 g_return_if_fail (signal_id > 0);
1355 param_values = instance_and_params + 1;
1357 G_LOCK (g_signal_mutex);
1358 node = LOOKUP_SIGNAL_NODE (signal_id);
1359 #ifndef G_DISABLE_CHECKS
1360 if (!node || !g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
1362 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1363 G_UNLOCK (g_signal_mutex);
1366 if (detail && !(node->flags & G_SIGNAL_DETAILED))
1368 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1369 G_UNLOCK (g_signal_mutex);
1372 for (i = 0; i < node->n_params; i++)
1373 if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
1375 g_critical (G_STRLOC ": value for `%s' parameter %u for signal \"%s\" is of type `%s'",
1376 g_type_name (node->param_types[i]),
1379 G_VALUE_TYPE_NAME (param_values + i));
1380 G_UNLOCK (g_signal_mutex);
1383 if (node->return_type != G_TYPE_NONE)
1387 g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is (NULL)",
1388 g_type_name (node->return_type),
1390 G_UNLOCK (g_signal_mutex);
1393 else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
1395 g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is of type `%s'",
1396 g_type_name (node->return_type),
1398 G_VALUE_TYPE_NAME (return_value));
1399 G_UNLOCK (g_signal_mutex);
1404 return_value = NULL;
1405 #endif /* !G_DISABLE_CHECKS */
1407 signal_emit_R (node, detail, instance, return_value, instance_and_params);
1409 G_UNLOCK (g_signal_mutex);
1413 signal_emit_R (SignalNode *node,
1416 GValue *return_value,
1417 const GValue *instance_and_params)
1419 EmissionState emission_state = 0;
1420 GSignalAccumulator accumulator;
1421 GSignalInvocationHint ihint;
1422 GClosure *class_closure;
1424 Handler *handler_list = NULL;
1426 gboolean accu_used = FALSE;
1427 guint signal_id = node->signal_id;
1429 if (node->flags & G_SIGNAL_NO_RECURSE)
1431 Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance);
1435 *emission->state_p = EMISSION_RESTART;
1439 ihint.signal_id = node->signal_id;
1440 ihint.detail = detail;
1441 accumulator = node->accumulator;
1444 G_UNLOCK (g_signal_mutex);
1445 g_value_init (&accu, node->return_type);
1446 G_LOCK (g_signal_mutex);
1448 emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
1449 signal_id, detail, instance, &emission_state);
1450 class_closure = node->class_closure;
1455 handler_unref_R (signal_id, instance, handler_list);
1456 hlist = handler_list_lookup (signal_id, instance);
1457 handler_list = hlist ? hlist->handlers : NULL;
1459 handler_ref (handler_list);
1461 ihint.run_type = G_SIGNAL_RUN_FIRST;
1463 if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
1465 emission_state = EMISSION_RUN;
1467 G_UNLOCK (g_signal_mutex);
1471 g_value_reset (&accu);
1472 g_closure_invoke (class_closure,
1475 instance_and_params,
1477 if (!accumulator (&ihint, return_value, &accu) &&
1478 emission_state == EMISSION_RUN)
1479 emission_state = EMISSION_STOP;
1483 g_closure_invoke (class_closure,
1486 instance_and_params,
1488 G_LOCK (g_signal_mutex);
1490 if (emission_state == EMISSION_STOP)
1492 else if (emission_state == EMISSION_RESTART)
1496 if (node->emission_hooks)
1498 emission_state = EMISSION_HOOK;
1500 G_UNLOCK (g_signal_mutex);
1501 g_print ("emission_hooks()\n");
1502 G_LOCK (g_signal_mutex);
1504 if (emission_state == EMISSION_RESTART)
1510 Handler *handler = handler_list;
1512 emission_state = EMISSION_RUN;
1513 handler_ref (handler);
1520 handler_unref_R (signal_id, instance, handler_list);
1521 handler_list = handler;
1524 else if (!handler->block_count && (!handler->detail || handler->detail == detail))
1526 G_UNLOCK (g_signal_mutex);
1530 g_value_reset (&accu);
1531 g_closure_invoke (handler->closure,
1534 instance_and_params,
1536 if (!accumulator (&ihint, return_value, &accu) &&
1537 emission_state == EMISSION_RUN)
1538 emission_state = EMISSION_STOP;
1542 g_closure_invoke (handler->closure,
1545 instance_and_params,
1547 G_LOCK (g_signal_mutex);
1549 tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1552 tmp = handler->next;
1556 handler_unref_R (signal_id, instance, handler_list);
1557 handler_list = handler;
1562 if (emission_state == EMISSION_STOP)
1564 else if (emission_state == EMISSION_RESTART)
1568 ihint.run_type = G_SIGNAL_RUN_LAST;
1570 if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
1572 emission_state = EMISSION_RUN;
1574 G_UNLOCK (g_signal_mutex);
1578 g_value_reset (&accu);
1579 g_closure_invoke (class_closure,
1582 instance_and_params,
1584 if (!accumulator (&ihint, return_value, &accu) &&
1585 emission_state == EMISSION_RUN)
1586 emission_state = EMISSION_STOP;
1590 g_closure_invoke (class_closure,
1593 instance_and_params,
1595 G_LOCK (g_signal_mutex);
1597 if (emission_state == EMISSION_STOP)
1599 else if (emission_state == EMISSION_RESTART)
1605 Handler *handler = handler_list;
1607 emission_state = EMISSION_RUN;
1608 handler_ref (handler);
1613 if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail))
1615 G_UNLOCK (g_signal_mutex);
1619 g_value_reset (&accu);
1620 g_closure_invoke (handler->closure,
1623 instance_and_params,
1625 if (!accumulator (&ihint, return_value, &accu) &&
1626 emission_state == EMISSION_RUN)
1627 emission_state = EMISSION_STOP;
1631 g_closure_invoke (handler->closure,
1634 instance_and_params,
1636 G_LOCK (g_signal_mutex);
1638 tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1641 tmp = handler->next;
1645 handler_unref_R (signal_id, instance, handler);
1650 if (emission_state == EMISSION_STOP)
1652 else if (emission_state == EMISSION_RESTART)
1658 ihint.run_type = G_SIGNAL_RUN_CLEANUP;
1660 if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
1662 gboolean need_unset = FALSE;
1664 emission_state = EMISSION_STOP;
1666 G_UNLOCK (g_signal_mutex);
1667 if (node->return_type != G_TYPE_NONE)
1671 g_value_init (&accu, node->return_type);
1675 g_value_reset (&accu);
1677 g_closure_invoke (class_closure,
1678 node->return_type != G_TYPE_NONE ? &accu : NULL,
1680 instance_and_params,
1683 g_value_unset (&accu);
1684 G_LOCK (g_signal_mutex);
1686 if (emission_state == EMISSION_RESTART)
1691 handler_unref_R (signal_id, instance, handler_list);
1693 emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
1696 G_UNLOCK (g_signal_mutex);
1697 g_value_unset (&accu);
1698 G_LOCK (g_signal_mutex);