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;
90 /* --- prototypes --- */
91 static inline guint signal_id_lookup (GQuark quark,
93 static void signal_destroy_R (SignalNode *signal_node);
94 static inline HandlerList* handler_list_ensure (guint signal_id,
96 static inline HandlerList* handler_list_lookup (guint signal_id,
98 static inline Handler* handler_new (gboolean after);
99 static void handler_insert (guint signal_id,
102 static Handler* handler_lookup (gpointer instance,
105 static Handler* handler_find (gpointer instance,
106 GSignalMatchType mask,
112 static inline void handler_ref (Handler *handler);
113 static inline void handler_unref_R (guint signal_id,
116 static inline void emission_push (Emission **emission_list_p,
120 EmissionState *state_p);
121 static inline void emission_pop (Emission **emission_list_p,
122 EmissionState *state_p);
123 static inline Emission* emission_find (Emission *emission_list,
127 static void signal_emit_R (SignalNode *node,
130 GValue *return_value,
131 const GValue *instance_and_params);
134 /* --- structures --- */
137 /* permanent portion */
143 /* reinitializable portion */
148 GClosure *class_closure;
149 GSignalAccumulator accumulator;
150 GSignalCMarshaller c_marshaller;
151 GHookList *emission_hooks;
167 EmissionState *state_p;
182 guint ref_count : 16;
183 #define HANDLER_MAX_REF_COUNT (1 << 16)
184 guint block_count : 12;
185 #define HANDLER_MAX_BLOCK_COUNT (1 << 12)
191 /* --- variables --- */
192 static GBSearchArray g_signal_key_bsa = { NULL, 0, 0, 0, NULL };
193 static GHashTable *g_handler_list_bsa_ht = NULL;
194 static Emission *g_recursive_emissions = NULL;
195 static Emission *g_restart_emissions = NULL;
196 static GTrashStack *g_bsa_ts = NULL;
197 static GTrashStack *g_handler_ts = NULL;
198 static GTrashStack *g_emission_ts = NULL;
199 G_LOCK_DEFINE_STATIC (g_signal_mutex);
202 /* --- signal nodes --- */
203 static guint g_n_signal_nodes = 0;
204 static SignalNode **g_signal_nodes = NULL;
206 static inline SignalNode*
207 LOOKUP_SIGNAL_NODE (register guint signal_id)
209 if (signal_id < g_n_signal_nodes)
210 return g_signal_nodes[signal_id];
216 /* --- functions --- */
218 signal_id_lookup (GQuark quark,
223 SignalKey key, *signal_key;
228 signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
231 return signal_key->signal_id;
233 itype = g_type_parent (itype);
241 handler_lists_cmp (gconstpointer node1,
244 const HandlerList *hlist1 = node1, *hlist2 = node2;
246 return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
249 static inline HandlerList*
250 handler_list_ensure (guint signal_id,
253 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
258 hlbsa = g_generic_node_alloc (&g_bsa_ts,
259 sizeof (GBSearchArray),
261 hlbsa->cmp_func = handler_lists_cmp;
262 hlbsa->sizeof_node = sizeof (HandlerList);
263 hlbsa->flags = G_BSEARCH_DEFER_SHRINK;
266 g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
268 key.signal_id = signal_id;
271 return g_bsearch_array_insert (hlbsa, &key, FALSE);
274 static inline HandlerList*
275 handler_list_lookup (guint signal_id,
278 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
281 key.signal_id = signal_id;
283 return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL;
287 handler_lookup (gpointer instance,
291 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
297 for (i = 0; i < hlbsa->n_nodes; i++)
299 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
302 for (handler = hlist->handlers; handler; handler = handler->next)
303 if (handler->id == handler_id)
306 *signal_id_p = hlist->signal_id;
317 handler_find (gpointer instance,
318 GSignalMatchType mask,
325 if (mask & G_SIGNAL_MATCH_ID)
327 HandlerList *hlist = handler_list_lookup (signal_id, instance);
331 if (mask & G_SIGNAL_MATCH_FUNC)
333 node = LOOKUP_SIGNAL_NODE (signal_id);
334 if (!node || !node->c_marshaller)
339 for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
340 if (((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
341 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
342 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
343 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
344 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
345 handler->closure->meta_marshal == 0 &&
346 ((GCClosure*) handler->closure)->callback == func)))
351 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
358 for (i = 0; i < hlbsa->n_nodes; i++)
360 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
364 if (!(mask & G_SIGNAL_MATCH_FUNC))
366 node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
367 if (!node->c_marshaller)
371 for (handler = hlist->handlers; handler; handler = handler->next)
372 if (((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
373 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
374 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
375 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
376 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
377 handler->closure->meta_marshal == 0 &&
378 ((GCClosure*) handler->closure)->callback == func)))
387 static inline Handler*
388 handler_new (gboolean after)
390 static guint handler_id = 1;
391 Handler *handler = g_generic_node_alloc (&g_handler_ts,
394 #ifndef G_DISABLE_CHECKS
396 g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
399 handler->id = handler_id++;
400 handler->prev = NULL;
401 handler->next = NULL;
403 handler->ref_count = 1;
404 handler->block_count = 0;
405 handler->after = after != FALSE;
406 handler->closure = NULL;
412 handler_ref (Handler *handler)
414 g_return_if_fail (handler->ref_count > 0);
416 #ifndef G_DISABLE_CHECKS
417 if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
418 g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
421 handler->ref_count += 1;
425 handler_unref_R (guint signal_id,
429 g_return_if_fail (handler->ref_count > 0);
431 handler->ref_count -= 1;
432 if (!handler->ref_count)
435 handler->next->prev = handler->prev;
436 if (handler->prev) /* watch out for _g_signal_handlers_destroy()! */
437 handler->prev->next = handler->next;
440 HandlerList *hlist = handler_list_lookup (signal_id, instance);
442 hlist->handlers = handler->next;
444 G_UNLOCK (g_signal_mutex);
445 g_closure_unref (handler->closure);
446 G_LOCK (g_signal_mutex);
447 g_generic_node_free (&g_handler_ts, handler);
452 handler_insert (guint signal_id,
458 g_assert (handler->prev == NULL && handler->next == NULL); // FIXME: paranoid
460 hlist = handler_list_ensure (signal_id, instance);
461 if (!hlist->handlers)
462 hlist->handlers = handler;
463 else if (hlist->handlers->after && !handler->after)
465 handler->next = hlist->handlers;
466 hlist->handlers->prev = handler;
467 hlist->handlers = handler;
471 Handler *tmp = hlist->handlers;
477 while (tmp->next && !tmp->next->after)
480 tmp->next->prev = handler;
481 handler->next = tmp->next;
488 emission_push (Emission **emission_list_p,
492 EmissionState *state_p)
494 Emission *emission = g_generic_node_alloc (&g_emission_ts,
497 emission->next = *emission_list_p;
498 emission->signal_id = signal_id;
499 emission->detail = detail;
500 emission->instance = instance;
501 emission->state_p = state_p;
502 *emission_list_p = emission;
506 emission_pop (Emission **emission_list_p,
507 EmissionState *state_p)
509 Emission **loc = emission_list_p, *emission = *loc;
511 while (emission->state_p != state_p)
513 loc = &emission->next;
516 *loc = emission->next;
517 g_generic_node_free (&g_emission_ts, emission);
520 static inline Emission*
521 emission_find (Emission *emission_list,
528 for (emission = emission_list; emission; emission = emission->next)
529 if (emission->instance == instance &&
530 emission->signal_id == signal_id &&
531 emission->detail == detail)
537 signal_key_cmp (gconstpointer node1,
540 const SignalKey *key1 = node1, *key2 = node2;
542 if (key1->itype == key2->itype)
543 return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
545 return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
549 g_signal_init (void) /* sync with gtype.c */
551 G_LOCK (g_signal_mutex);
552 if (!g_n_signal_nodes)
554 /* setup signal key array */
555 g_signal_key_bsa.cmp_func = signal_key_cmp;
556 g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
557 g_signal_key_bsa.flags = 0; /* alloc-only */
559 /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
560 g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
562 /* invalid (0) signal_id */
563 g_n_signal_nodes = 1;
564 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
565 g_signal_nodes[0] = NULL;
567 G_UNLOCK (g_signal_mutex);
571 _g_signals_destroy (GType itype)
575 G_LOCK (g_signal_mutex);
576 for (i = 0; i < g_n_signal_nodes; i++)
578 SignalNode *node = g_signal_nodes[i];
580 if (node->itype == itype)
583 g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
585 g_type_name (node->itype));
587 signal_destroy_R (node);
590 G_UNLOCK (g_signal_mutex);
594 g_signal_stop_emission (gpointer instance,
600 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
601 g_return_if_fail (signal_id > 0);
603 G_LOCK (g_signal_mutex);
604 node = LOOKUP_SIGNAL_NODE (signal_id);
605 if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
607 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
608 G_UNLOCK (g_signal_mutex);
611 if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
613 Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
614 Emission *emission = emission_find (emission_list, signal_id, detail, instance);
618 if (*emission->state_p == EMISSION_HOOK)
619 g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
620 node->name, instance);
621 else if (*emission->state_p == EMISSION_RUN)
622 *emission->state_p = EMISSION_STOP;
625 g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
626 node->name, instance);
629 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
630 G_UNLOCK (g_signal_mutex);
634 signal_parse_name (const gchar *name,
637 gboolean force_quark)
639 const gchar *colon = strchr (name, ':');
644 signal_id = signal_id_lookup (g_quark_try_string (name), itype);
645 if (signal_id && detail_p)
648 else if (colon[1] == ':')
651 guint l = colon - name;
655 memcpy (buffer, name, l);
657 signal_id = signal_id_lookup (g_quark_try_string (buffer), itype);
661 gchar *signal = g_new (gchar, l + 1);
663 memcpy (signal, name, l);
665 signal_id = signal_id_lookup (g_quark_try_string (signal), itype);
669 if (signal_id && detail_p)
670 *detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0;
678 g_signal_parse_name (const gchar *detailed_signal,
682 gboolean force_detail_quark)
687 g_return_val_if_fail (detailed_signal != NULL, FALSE);
688 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
690 G_LOCK (g_signal_mutex);
691 signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
692 G_UNLOCK (g_signal_mutex);
697 *signal_id_p = signal_id;
708 g_signal_lookup (const gchar *name,
713 g_return_val_if_fail (name != NULL, 0);
714 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
716 G_LOCK (g_signal_mutex);
717 signal_id = signal_id_lookup (g_quark_try_string (name), itype);
718 G_UNLOCK (g_signal_mutex);
724 g_signal_name (guint signal_id)
729 G_LOCK (g_signal_mutex);
730 node = LOOKUP_SIGNAL_NODE (signal_id);
731 name = node ? node->name : NULL;
732 G_UNLOCK (g_signal_mutex);
738 g_signal_query (guint signal_id,
743 g_return_if_fail (query != NULL);
745 G_LOCK (g_signal_mutex);
746 node = LOOKUP_SIGNAL_NODE (signal_id);
747 if (!node || node->destroyed)
748 query->signal_id = 0;
751 query->signal_id = node->signal_id;
752 query->signal_name = node->name;
753 query->itype = node->itype;
754 query->signal_flags = node->flags;
755 query->return_type = node->return_type;
756 query->n_params = node->n_params;
757 query->param_types = node->param_types;
759 G_UNLOCK (g_signal_mutex);
763 g_signal_list_ids (GType itype,
771 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
772 g_return_val_if_fail (n_ids != NULL, NULL);
774 G_LOCK (g_signal_mutex);
776 keys = g_signal_key_bsa.nodes;
777 n_nodes = g_signal_key_bsa.n_nodes;
778 result = g_array_new (FALSE, FALSE, sizeof (guint));
780 for (i = 0; i < n_nodes; i++)
781 if (keys[i].itype == itype)
783 gchar *name = g_quark_to_string (keys[i].quark);
785 /* Signal names with "_" in them are aliases to the same
786 * name with "-" instead of "_".
788 if (!strchr (name, '_'))
789 g_array_append_val (result, keys[i].signal_id);
792 *n_ids = result->len;
794 G_UNLOCK (g_signal_mutex);
796 return (guint *) g_array_free (result, FALSE);
800 g_signal_newv (const gchar *signal_name,
802 GSignalFlags signal_flags,
803 GClosure *class_closure,
804 GSignalAccumulator accumulator,
805 GSignalCMarshaller c_marshaller,
814 g_return_val_if_fail (signal_name != NULL, 0);
815 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
817 g_return_val_if_fail (param_types != NULL, 0);
818 if (return_type != G_TYPE_NONE)
819 g_return_val_if_fail (accumulator == NULL, 0);
821 name = g_strdup (signal_name);
822 g_strdelimit (name, G_STR_DELIMITERS ":^", '_'); // FIXME do character checks like for types
824 G_LOCK (g_signal_mutex);
826 signal_id = signal_id_lookup (g_quark_try_string (name), itype);
827 node = LOOKUP_SIGNAL_NODE (signal_id);
828 if (node && !node->destroyed)
830 g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
832 g_type_name (node->itype),
833 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
835 G_UNLOCK (g_signal_mutex);
838 if (node && node->itype != itype)
840 g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
843 g_type_name (node->itype));
845 G_UNLOCK (g_signal_mutex);
848 for (i = 0; i < n_params; i++)
849 if (!G_TYPE_IS_VALUE (param_types[i]) ||
850 param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */
852 g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
853 i + 1, g_type_name (param_types[i]), g_type_name (itype), name);
855 G_UNLOCK (g_signal_mutex);
858 if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type))
860 g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
861 g_type_name (param_types[i]), g_type_name (itype), name);
863 G_UNLOCK (g_signal_mutex);
867 /* setup permanent portion of signal node */
872 signal_id = g_n_signal_nodes++;
873 node = g_new (SignalNode, 1);
874 node->signal_id = signal_id;
875 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
876 g_signal_nodes[signal_id] = node;
880 key.quark = g_quark_from_string (node->name);
881 key.signal_id = signal_id;
882 g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
883 g_strdelimit (node->name, "_", '-');
884 key.quark = g_quark_from_static_string (node->name);
885 g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
887 node->destroyed = FALSE;
889 /* setup reinitializable portion */
890 node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
891 node->n_params = n_params;
892 node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
893 node->return_type = return_type;
894 node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL;
895 node->accumulator = accumulator;
896 node->c_marshaller = c_marshaller;
897 node->emission_hooks = NULL;
898 if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure))
899 g_closure_set_marshal (class_closure, node->c_marshaller);
901 G_UNLOCK (g_signal_mutex);
906 signal_destroy_R (SignalNode *signal_node)
908 SignalNode node = *signal_node;
910 signal_node->destroyed = TRUE;
912 /* reentrancy caution, zero out real contents first */
913 signal_node->n_params = 0;
914 signal_node->param_types = NULL;
915 signal_node->return_type = 0;
916 signal_node->class_closure = NULL;
917 signal_node->accumulator = NULL;
918 signal_node->c_marshaller = NULL;
919 signal_node->emission_hooks = NULL;
921 #ifndef G_DISABLE_CHECKS
922 /* check current emissions */
926 for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
927 emission; emission = emission->next)
928 if (emission->signal_id == node.signal_id)
929 g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
930 node.name, emission->instance);
934 /* free contents that need to
936 G_UNLOCK (g_signal_mutex);
937 g_free (node.param_types);
938 g_closure_unref (node.class_closure);
939 if (node.emission_hooks)
941 g_hook_list_clear (node.emission_hooks);
942 g_free (node.emission_hooks);
944 G_LOCK (g_signal_mutex);
948 g_signal_connect_closure_by_id (gpointer instance,
955 guint handler_id = 0;
957 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
958 g_return_val_if_fail (signal_id > 0, 0);
959 g_return_val_if_fail (closure != NULL, 0);
961 G_LOCK (g_signal_mutex);
962 node = LOOKUP_SIGNAL_NODE (signal_id);
963 if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
965 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
966 G_UNLOCK (g_signal_mutex);
969 if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
971 Handler *handler = handler_new (after);
973 handler_id = handler->id;
974 handler->detail = detail;
975 handler->closure = g_closure_ref (closure);
976 handler_insert (signal_id, instance, handler);
977 if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
978 g_closure_set_marshal (closure, node->c_marshaller);
981 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
982 G_UNLOCK (g_signal_mutex);
988 g_signal_handler_block (gpointer instance,
993 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
994 g_return_if_fail (handler_id > 0);
996 G_LOCK (g_signal_mutex);
997 handler = handler_lookup (instance, handler_id, NULL);
1000 #ifndef G_DISABLE_CHECKS
1001 if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
1002 g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
1005 handler->block_count += 1;
1008 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1009 G_UNLOCK (g_signal_mutex);
1013 g_signal_handler_unblock (gpointer instance,
1018 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1019 g_return_if_fail (handler_id > 0);
1021 G_LOCK (g_signal_mutex);
1022 handler = handler_lookup (instance, handler_id, NULL);
1025 if (handler->block_count)
1026 handler->block_count -= 1;
1028 g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance);
1031 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1032 G_UNLOCK (g_signal_mutex);
1036 g_signal_handler_disconnect (gpointer instance,
1042 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1043 g_return_if_fail (handler_id > 0);
1045 G_LOCK (g_signal_mutex);
1046 handler = handler_lookup (instance, handler_id, &signal_id);
1050 handler->block_count = 1;
1051 handler_unref_R (signal_id, instance, handler);
1054 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1055 G_UNLOCK (g_signal_mutex);
1059 _g_signal_handlers_destroy (gpointer instance)
1061 GBSearchArray *hlbsa;
1063 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1065 G_LOCK (g_signal_mutex);
1066 hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
1071 /* reentrancy caution, delete instance trace first */
1072 g_hash_table_remove (g_handler_list_bsa_ht, instance);
1074 for (i = 0; i < hlbsa->n_nodes; i++)
1076 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
1077 Handler *handler = hlist->handlers;
1081 Handler *tmp = handler;
1083 handler = tmp->next;
1084 tmp->block_count = 1;
1085 /* cruel unlink, this works because _all_ handlers vanish */
1091 handler_unref_R (0, NULL, tmp);
1095 g_free (hlbsa->nodes);
1096 g_generic_node_free (&g_bsa_ts, hlbsa);
1098 G_UNLOCK (g_signal_mutex);
1102 g_signal_handler_find (gpointer instance,
1103 GSignalMatchType mask,
1111 guint handler_id = 0;
1113 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1114 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1116 if (mask & G_SIGNAL_MATCH_MASK)
1118 G_LOCK (g_signal_mutex);
1119 handler = handler_find (instance, mask, signal_id, detail, closure, func, data);
1120 handler_id = handler ? handler->id : 0;
1121 G_UNLOCK (g_signal_mutex);
1128 signal_handlers_foreach_matched (gpointer instance,
1129 GSignalMatchType mask,
1135 void (*callback) (gpointer instance,
1139 guint n_handlers = 0;
1141 handler = handler_find (instance, mask, signal_id, detail, closure, func, data);
1142 while (handler && handler->id)
1145 G_UNLOCK (g_signal_mutex);
1146 callback (instance, handler->id);
1147 G_LOCK (g_signal_mutex);
1148 /* need constant relookups due to callback */
1149 handler = handler_find (instance, mask, signal_id, detail, closure, func, data);
1156 g_signal_handlers_block_matched (gpointer instance,
1157 GSignalMatchType mask,
1164 guint n_handlers = 0;
1166 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1167 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1169 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1171 G_LOCK (g_signal_mutex);
1172 n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail,
1173 closure, func, data,
1174 g_signal_handler_block);
1175 G_UNLOCK (g_signal_mutex);
1182 g_signal_handlers_unblock_matched (gpointer instance,
1183 GSignalMatchType mask,
1190 guint n_handlers = 0;
1192 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1193 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1195 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1197 G_LOCK (g_signal_mutex);
1198 n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail,
1199 closure, func, data,
1200 g_signal_handler_unblock);
1201 G_UNLOCK (g_signal_mutex);
1208 g_signal_handlers_disconnect_matched (gpointer instance,
1209 GSignalMatchType mask,
1216 guint n_handlers = 0;
1218 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1219 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1221 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1223 G_LOCK (g_signal_mutex);
1224 n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail,
1225 closure, func, data,
1226 g_signal_handler_disconnect);
1227 G_UNLOCK (g_signal_mutex);
1234 g_signal_has_handler_pending (gpointer instance,
1237 gboolean may_be_blocked)
1239 Handler *handler = NULL;
1241 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1242 g_return_val_if_fail (signal_id > 0, FALSE);
1244 G_LOCK (g_signal_mutex);
1247 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1249 if (!(node->flags & G_SIGNAL_DETAILED))
1251 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1252 G_UNLOCK (g_signal_mutex);
1256 handler = handler_find (instance,
1257 (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL |
1258 (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
1259 signal_id, detail, NULL, NULL, NULL);
1260 G_UNLOCK (g_signal_mutex);
1262 return handler != NULL;
1266 g_signal_emitv (const GValue *instance_and_params,
1269 GValue *return_value)
1273 const GValue *param_values;
1276 g_return_if_fail (instance_and_params != NULL);
1277 instance = g_value_get_as_pointer (instance_and_params);
1278 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1279 g_return_if_fail (signal_id > 0);
1281 param_values = instance_and_params + 1;
1283 G_LOCK (g_signal_mutex);
1284 node = LOOKUP_SIGNAL_NODE (signal_id);
1285 #ifndef G_DISABLE_CHECKS
1286 if (!node || !g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
1288 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1289 G_UNLOCK (g_signal_mutex);
1292 if (detail && !(node->flags & G_SIGNAL_DETAILED))
1294 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1295 G_UNLOCK (g_signal_mutex);
1298 for (i = 0; i < node->n_params; i++)
1299 if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
1301 g_critical (G_STRLOC ": value for `%s' parameter %u for signal \"%s\" is of type `%s'",
1302 g_type_name (node->param_types[i]),
1305 G_VALUE_TYPE_NAME (param_values + i));
1306 G_UNLOCK (g_signal_mutex);
1309 if (node->return_type != G_TYPE_NONE)
1313 g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is (NULL)",
1314 g_type_name (node->return_type),
1316 G_UNLOCK (g_signal_mutex);
1319 else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
1321 g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is of type `%s'",
1322 g_type_name (node->return_type),
1324 G_VALUE_TYPE_NAME (return_value));
1325 G_UNLOCK (g_signal_mutex);
1330 return_value = NULL;
1331 #endif /* !G_DISABLE_CHECKS */
1333 signal_emit_R (node, detail, instance, return_value, instance_and_params);
1335 G_UNLOCK (g_signal_mutex);
1339 signal_emit_R (SignalNode *node,
1342 GValue *return_value,
1343 const GValue *instance_and_params)
1345 EmissionState emission_state = 0;
1346 GSignalAccumulator accumulator;
1347 GSignalInvocationHint ihint;
1348 GClosure *class_closure;
1350 Handler *handler_list = NULL;
1352 gboolean accu_used = FALSE;
1353 guint signal_id = node->signal_id;
1355 if (node->flags & G_SIGNAL_NO_RECURSE)
1357 Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance);
1361 *emission->state_p = EMISSION_RESTART;
1365 ihint.signal_id = node->signal_id;
1366 ihint.detail = detail;
1367 accumulator = node->accumulator;
1370 G_UNLOCK (g_signal_mutex);
1371 g_value_init (&accu, node->return_type);
1372 G_LOCK (g_signal_mutex);
1374 emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
1375 signal_id, detail, instance, &emission_state);
1376 class_closure = node->class_closure;
1381 handler_unref_R (signal_id, instance, handler_list);
1382 hlist = handler_list_lookup (signal_id, instance);
1383 handler_list = hlist ? hlist->handlers : NULL;
1385 handler_ref (handler_list);
1387 ihint.run_type = G_SIGNAL_RUN_FIRST;
1389 if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
1391 emission_state = EMISSION_RUN;
1393 G_UNLOCK (g_signal_mutex);
1397 g_value_reset (&accu);
1398 g_closure_invoke (class_closure,
1401 instance_and_params,
1403 if (!accumulator (&ihint, return_value, &accu) &&
1404 emission_state == EMISSION_RUN)
1405 emission_state = EMISSION_STOP;
1409 g_closure_invoke (class_closure,
1412 instance_and_params,
1414 G_LOCK (g_signal_mutex);
1416 if (emission_state == EMISSION_STOP)
1418 else if (emission_state == EMISSION_RESTART)
1422 if (node->emission_hooks)
1424 emission_state = EMISSION_HOOK;
1426 G_UNLOCK (g_signal_mutex);
1427 g_print ("emission_hooks()\n");
1428 G_LOCK (g_signal_mutex);
1430 if (emission_state == EMISSION_RESTART)
1436 Handler *handler = handler_list;
1438 emission_state = EMISSION_RUN;
1439 handler_ref (handler);
1446 handler_unref_R (signal_id, instance, handler_list);
1447 handler_list = handler;
1450 else if (!handler->block_count && (!handler->detail || handler->detail == detail))
1452 G_UNLOCK (g_signal_mutex);
1456 g_value_reset (&accu);
1457 g_closure_invoke (handler->closure,
1460 instance_and_params,
1462 if (!accumulator (&ihint, return_value, &accu) &&
1463 emission_state == EMISSION_RUN)
1464 emission_state = EMISSION_STOP;
1468 g_closure_invoke (handler->closure,
1471 instance_and_params,
1473 G_LOCK (g_signal_mutex);
1475 tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1478 tmp = handler->next;
1482 handler_unref_R (signal_id, instance, handler_list);
1483 handler_list = handler;
1488 if (emission_state == EMISSION_STOP)
1490 else if (emission_state == EMISSION_RESTART)
1494 ihint.run_type = G_SIGNAL_RUN_LAST;
1496 if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
1498 emission_state = EMISSION_RUN;
1500 G_UNLOCK (g_signal_mutex);
1504 g_value_reset (&accu);
1505 g_closure_invoke (class_closure,
1508 instance_and_params,
1510 if (!accumulator (&ihint, return_value, &accu) &&
1511 emission_state == EMISSION_RUN)
1512 emission_state = EMISSION_STOP;
1516 g_closure_invoke (class_closure,
1519 instance_and_params,
1521 G_LOCK (g_signal_mutex);
1523 if (emission_state == EMISSION_STOP)
1525 else if (emission_state == EMISSION_RESTART)
1531 Handler *handler = handler_list;
1533 emission_state = EMISSION_RUN;
1534 handler_ref (handler);
1539 if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail))
1541 G_UNLOCK (g_signal_mutex);
1545 g_value_reset (&accu);
1546 g_closure_invoke (handler->closure,
1549 instance_and_params,
1551 if (!accumulator (&ihint, return_value, &accu) &&
1552 emission_state == EMISSION_RUN)
1553 emission_state = EMISSION_STOP;
1557 g_closure_invoke (handler->closure,
1560 instance_and_params,
1562 G_LOCK (g_signal_mutex);
1564 tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1567 tmp = handler->next;
1571 handler_unref_R (signal_id, instance, handler);
1576 if (emission_state == EMISSION_STOP)
1578 else if (emission_state == EMISSION_RESTART)
1584 ihint.run_type = G_SIGNAL_RUN_CLEANUP;
1586 if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
1588 gboolean need_unset = FALSE;
1590 emission_state = EMISSION_STOP;
1592 G_UNLOCK (g_signal_mutex);
1593 if (node->return_type != G_TYPE_NONE)
1597 g_value_init (&accu, node->return_type);
1601 g_value_reset (&accu);
1603 g_closure_invoke (class_closure,
1604 node->return_type != G_TYPE_NONE ? &accu : NULL,
1606 instance_and_params,
1609 g_value_unset (&accu);
1610 G_LOCK (g_signal_mutex);
1612 if (emission_state == EMISSION_RESTART)
1617 handler_unref_R (signal_id, instance, handler_list);
1619 emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
1622 G_UNLOCK (g_signal_mutex);
1623 g_value_unset (&accu);
1624 G_LOCK (g_signal_mutex);