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>
24 #include "gbsearcharray.h"
27 /* pre allocation configurations
29 #define BSA_PRE_ALLOC (20)
30 #define HANDLER_PRE_ALLOC (48)
31 #define EMISSION_PRE_ALLOC (16)
33 #define TIGHT_MEMORY (1)
35 #define REPORT_BUG "please report occourance circumstances to gtk-devel-list@gnome.org"
38 /* --- generic allocation --- */
39 /* we can special case allocations generically by replacing
40 * these functions with more speed/memory aware variants
42 static inline gpointer
43 g_generic_node_alloc (GTrashStack **trash_stack_p,
45 guint nodes_pre_alloc)
47 gpointer node = g_trash_stack_pop (trash_stack_p);
53 nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
54 block = g_malloc (sizeof_node * nodes_pre_alloc);
55 while (--nodes_pre_alloc)
57 g_trash_stack_push (trash_stack_p, block);
66 g_generic_node_free (GTrashStack **trash_stack_p,
69 g_trash_stack_push (trash_stack_p, node);
73 /* --- typedefs --- */
74 typedef struct _SignalNode SignalNode;
75 typedef struct _SignalKey SignalKey;
76 typedef struct _Emission Emission;
77 typedef struct _Handler Handler;
78 typedef struct _HandlerList HandlerList;
88 /* --- prototypes --- */
89 static inline guint signal_id_lookup (GQuark quark,
91 static void signal_destroy_R (SignalNode *signal_node);
92 static inline HandlerList* handler_list_ensure (guint signal_id,
94 static inline HandlerList* handler_list_lookup (guint signal_id,
96 static inline Handler* handler_new (gboolean after);
97 static void handler_insert (guint signal_id,
100 static Handler* handler_lookup (gpointer instance,
103 static Handler* handler_find (gpointer instance,
104 GSignalMatchType mask,
110 static inline void handler_ref (Handler *handler);
111 static inline void handler_unref_R (guint signal_id,
114 static inline void emission_push (Emission **emission_list_p,
118 EmissionState *state_p);
119 static inline void emission_pop (Emission **emission_list_p,
120 EmissionState *state_p);
121 static inline Emission* emission_find (Emission *emission_list,
125 static void signal_emit_R (SignalNode *node,
128 GValue *return_value,
129 const GValue *instance_and_params);
132 /* --- structures --- */
135 /* permanent portion */
141 /* reinitializable portion */
146 GClosure *class_closure;
147 GSignalAccumulator accumulator;
148 GSignalCMarshaller c_marshaller;
149 GHookList *emission_hooks;
165 EmissionState *state_p;
180 guint ref_count : 16;
181 #define HANDLER_MAX_REF_COUNT (1 << 16)
182 guint block_count : 12;
183 #define HANDLER_MAX_BLOCK_COUNT (1 << 12)
189 /* --- variables --- */
190 static GBSearchArray g_signal_key_bsa = { NULL, 0, 0, 0, NULL };
191 static GHashTable *g_handler_list_bsa_ht = NULL;
192 static Emission *g_recursive_emissions = NULL;
193 static Emission *g_restart_emissions = NULL;
194 static GTrashStack *g_bsa_ts = NULL;
195 static GTrashStack *g_handler_ts = NULL;
196 static GTrashStack *g_emission_ts = NULL;
197 G_LOCK_DEFINE_STATIC (g_signal_mutex);
200 /* --- signal nodes --- */
201 static guint g_n_signal_nodes = 0;
202 static SignalNode **g_signal_nodes = NULL;
204 static inline SignalNode*
205 LOOKUP_SIGNAL_NODE (register guint signal_id)
207 if (signal_id < g_n_signal_nodes)
208 return g_signal_nodes[signal_id];
214 /* --- functions --- */
216 signal_id_lookup (GQuark quark,
221 SignalKey key, *signal_key;
226 signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
229 return signal_key->signal_id;
231 itype = g_type_parent (itype);
239 handler_lists_cmp (gconstpointer node1,
242 const HandlerList *hlist1 = node1, *hlist2 = node2;
244 return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
247 static inline HandlerList*
248 handler_list_ensure (guint signal_id,
251 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
256 hlbsa = g_generic_node_alloc (&g_bsa_ts,
257 sizeof (GBSearchArray),
259 hlbsa->cmp_func = handler_lists_cmp;
260 hlbsa->sizeof_node = sizeof (HandlerList);
261 hlbsa->flags = G_BSEARCH_DEFER_SHRINK;
264 g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
266 key.signal_id = signal_id;
269 return g_bsearch_array_insert (hlbsa, &key, FALSE);
272 static inline HandlerList*
273 handler_list_lookup (guint signal_id,
276 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
279 key.signal_id = signal_id;
281 return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL;
285 handler_lookup (gpointer instance,
289 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
295 for (i = 0; i < hlbsa->n_nodes; i++)
297 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
300 for (handler = hlist->handlers; handler; handler = handler->next)
301 if (handler->id == handler_id)
304 *signal_id_p = hlist->signal_id;
315 handler_find (gpointer instance,
316 GSignalMatchType mask,
323 if (mask & G_SIGNAL_MATCH_ID)
325 HandlerList *hlist = handler_list_lookup (signal_id, instance);
329 if (mask & G_SIGNAL_MATCH_FUNC)
331 node = LOOKUP_SIGNAL_NODE (signal_id);
332 if (!node || !node->c_marshaller)
337 for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
338 if (((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
339 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
340 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
341 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
342 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
343 handler->closure->meta_marshal == 0 &&
344 ((GCClosure*) handler->closure)->callback == func)))
349 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
356 for (i = 0; i < hlbsa->n_nodes; i++)
358 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
362 if (!(mask & G_SIGNAL_MATCH_FUNC))
364 node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
365 if (!node->c_marshaller)
369 for (handler = hlist->handlers; handler; handler = handler->next)
370 if (((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
371 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
372 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
373 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
374 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
375 handler->closure->meta_marshal == 0 &&
376 ((GCClosure*) handler->closure)->callback == func)))
385 static inline Handler*
386 handler_new (gboolean after)
388 static guint handler_id = 1;
389 Handler *handler = g_generic_node_alloc (&g_handler_ts,
392 #ifndef G_DISABLE_CHECKS
394 g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
397 handler->id = handler_id++;
398 handler->prev = NULL;
399 handler->next = NULL;
401 handler->ref_count = 1;
402 handler->block_count = 0;
403 handler->after = after != FALSE;
404 handler->closure = NULL;
410 handler_ref (Handler *handler)
412 g_return_if_fail (handler->ref_count > 0);
414 #ifndef G_DISABLE_CHECKS
415 if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
416 g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
419 handler->ref_count += 1;
423 handler_unref_R (guint signal_id,
427 g_return_if_fail (handler->ref_count > 0);
429 handler->ref_count -= 1;
430 if (!handler->ref_count)
433 handler->next->prev = handler->prev;
434 if (handler->prev) /* watch out for g_signal_handlers_destroy()! */
435 handler->prev->next = handler->next;
438 HandlerList *hlist = handler_list_lookup (signal_id, instance);
440 hlist->handlers = handler->next;
442 G_UNLOCK (g_signal_mutex);
443 g_closure_unref (handler->closure);
444 G_LOCK (g_signal_mutex);
445 g_generic_node_free (&g_handler_ts, handler);
450 handler_insert (guint signal_id,
456 g_assert (handler->prev == NULL && handler->next == NULL); // FIXME: paranoid
458 hlist = handler_list_ensure (signal_id, instance);
459 if (!hlist->handlers)
460 hlist->handlers = handler;
461 else if (hlist->handlers->after && !handler->after)
463 handler->next = hlist->handlers;
464 hlist->handlers->prev = handler;
465 hlist->handlers = handler;
469 Handler *tmp = hlist->handlers;
475 while (tmp->next && !tmp->next->after)
478 tmp->next->prev = handler;
479 handler->next = tmp->next;
486 emission_push (Emission **emission_list_p,
490 EmissionState *state_p)
492 Emission *emission = g_generic_node_alloc (&g_emission_ts,
495 emission->next = *emission_list_p;
496 emission->signal_id = signal_id;
497 emission->detail = detail;
498 emission->instance = instance;
499 emission->state_p = state_p;
500 *emission_list_p = emission;
504 emission_pop (Emission **emission_list_p,
505 EmissionState *state_p)
507 Emission **loc = emission_list_p, *emission = *loc;
509 while (emission->state_p != state_p)
511 loc = &emission->next;
514 *loc = emission->next;
515 g_generic_node_free (&g_emission_ts, emission);
518 static inline Emission*
519 emission_find (Emission *emission_list,
526 for (emission = emission_list; emission; emission = emission->next)
527 if (emission->instance == instance &&
528 emission->signal_id == signal_id &&
529 emission->detail == detail)
535 signal_key_cmp (gconstpointer node1,
538 const SignalKey *key1 = node1, *key2 = node2;
540 if (key1->itype == key2->itype)
541 return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
543 return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
547 g_signal_init (void) /* sync with gtype.c */
549 G_LOCK (g_signal_mutex);
550 if (!g_n_signal_nodes)
552 /* setup signal key array */
553 g_signal_key_bsa.cmp_func = signal_key_cmp;
554 g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
555 g_signal_key_bsa.flags = 0; /* alloc-only */
557 /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
558 g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
560 /* invalid (0) signal_id */
561 g_n_signal_nodes = 1;
562 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
563 g_signal_nodes[0] = NULL;
565 G_UNLOCK (g_signal_mutex);
569 g_signals_destroy (GType itype)
572 gboolean found_one = FALSE;
574 G_LOCK (g_signal_mutex);
575 for (i = 0; i < g_n_signal_nodes; i++)
577 SignalNode *node = g_signal_nodes[i];
579 if (node->itype == itype)
582 g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
584 g_type_name (node->itype));
588 signal_destroy_R (node);
593 g_warning (G_STRLOC ": type `%s' has no signals that could be destroyed",
594 g_type_name (itype));
595 G_UNLOCK (g_signal_mutex);
599 g_signal_stop_emission (gpointer instance,
605 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
606 g_return_if_fail (signal_id > 0);
608 G_LOCK (g_signal_mutex);
609 node = LOOKUP_SIGNAL_NODE (signal_id);
610 if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
612 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
613 G_UNLOCK (g_signal_mutex);
616 if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
618 Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
619 Emission *emission = emission_find (emission_list, signal_id, detail, instance);
623 if (*emission->state_p == EMISSION_HOOK)
624 g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
625 node->name, instance);
626 else if (*emission->state_p == EMISSION_RUN)
627 *emission->state_p = EMISSION_STOP;
630 g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
631 node->name, instance);
634 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
635 G_UNLOCK (g_signal_mutex);
639 g_signal_lookup (const gchar *name,
644 g_return_val_if_fail (name != NULL, 0);
645 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
647 G_LOCK (g_signal_mutex);
648 signal_id = signal_id_lookup (g_quark_try_string (name), itype);
649 G_UNLOCK (g_signal_mutex);
655 g_signal_name (guint signal_id)
660 G_LOCK (g_signal_mutex);
661 node = LOOKUP_SIGNAL_NODE (signal_id);
662 name = node ? node->name : NULL;
663 G_UNLOCK (g_signal_mutex);
669 g_signal_query (guint signal_id,
674 g_return_if_fail (query != NULL);
676 G_LOCK (g_signal_mutex);
677 node = LOOKUP_SIGNAL_NODE (signal_id);
678 if (!node || node->destroyed)
679 query->signal_id = 0;
682 query->signal_id = node->signal_id;
683 query->signal_name = node->name;
684 query->itype = node->itype;
685 query->signal_flags = node->flags;
686 query->return_type = node->return_type;
687 query->n_params = node->n_params;
688 query->param_types = node->param_types;
690 G_UNLOCK (g_signal_mutex);
694 g_signal_newv (const gchar *signal_name,
696 GSignalFlags signal_flags,
697 GClosure *class_closure,
698 GSignalAccumulator accumulator,
699 GSignalCMarshaller c_marshaller,
708 g_return_val_if_fail (signal_name != NULL, 0);
709 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
711 g_return_val_if_fail (param_types != NULL, 0);
712 if (return_type != G_TYPE_NONE)
713 g_return_val_if_fail (accumulator == NULL, 0);
715 name = g_strdup (signal_name);
716 g_strdelimit (name, G_STR_DELIMITERS ":^", '_'); // FIXME do character checks like for types
718 G_LOCK (g_signal_mutex);
720 signal_id = signal_id_lookup (g_quark_try_string (name), itype);
721 node = LOOKUP_SIGNAL_NODE (signal_id);
722 if (node && !node->destroyed)
724 g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
726 g_type_name (node->itype),
727 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
729 G_UNLOCK (g_signal_mutex);
732 if (node && node->itype != itype)
734 g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
737 g_type_name (node->itype));
739 G_UNLOCK (g_signal_mutex);
742 for (i = 0; i < n_params; i++)
743 if (!G_TYPE_IS_VALUE (param_types[i]) ||
744 param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */
746 g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
747 i + 1, g_type_name (param_types[i]), g_type_name (itype), name);
749 G_UNLOCK (g_signal_mutex);
752 if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type))
754 g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
755 g_type_name (param_types[i]), g_type_name (itype), name);
757 G_UNLOCK (g_signal_mutex);
761 /* setup permanent portion of signal node */
766 signal_id = g_n_signal_nodes++;
767 node = g_new (SignalNode, 1);
768 node->signal_id = signal_id;
769 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
770 g_signal_nodes[signal_id] = node;
774 key.quark = g_quark_from_string (node->name);
775 key.signal_id = signal_id;
776 g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
777 g_strdelimit (node->name, "_", '-');
778 key.quark = g_quark_from_static_string (node->name);
779 g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
781 node->destroyed = FALSE;
783 /* setup reinitializable portion */
784 node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
785 node->n_params = n_params;
786 node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
787 node->return_type = return_type;
788 node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL;
789 node->accumulator = accumulator;
790 node->c_marshaller = c_marshaller;
791 node->emission_hooks = NULL;
792 if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure))
793 g_closure_set_marshal (class_closure, node->c_marshaller);
795 G_UNLOCK (g_signal_mutex);
800 signal_destroy_R (SignalNode *signal_node)
802 SignalNode node = *signal_node;
804 signal_node->destroyed = TRUE;
806 /* reentrancy caution, zero out real contents first */
807 signal_node->n_params = 0;
808 signal_node->param_types = NULL;
809 signal_node->return_type = 0;
810 signal_node->class_closure = NULL;
811 signal_node->accumulator = NULL;
812 signal_node->c_marshaller = NULL;
813 signal_node->emission_hooks = NULL;
815 #ifndef G_DISABLE_CHECKS
816 /* check current emissions */
820 for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
821 emission; emission = emission->next)
822 if (emission->signal_id == node.signal_id)
823 g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
824 node.name, emission->instance);
828 /* free contents that need to
830 G_UNLOCK (g_signal_mutex);
831 g_free (node.param_types);
832 g_closure_unref (node.class_closure);
833 if (node.emission_hooks)
835 g_hook_list_clear (node.emission_hooks);
836 g_free (node.emission_hooks);
838 G_LOCK (g_signal_mutex);
842 g_signal_connect_closure (gpointer instance,
849 guint handler_id = 0;
851 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
852 g_return_val_if_fail (signal_id > 0, 0);
853 g_return_val_if_fail (closure != NULL, 0);
855 G_LOCK (g_signal_mutex);
856 node = LOOKUP_SIGNAL_NODE (signal_id);
857 if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
859 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
860 G_UNLOCK (g_signal_mutex);
863 if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
865 Handler *handler = handler_new (after);
867 handler_id = handler->id;
868 handler->detail = detail;
869 handler->closure = g_closure_ref (closure);
870 handler_insert (signal_id, instance, handler);
871 if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
872 g_closure_set_marshal (closure, node->c_marshaller);
875 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
876 G_UNLOCK (g_signal_mutex);
882 g_signal_handler_disconnect (gpointer instance,
888 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
889 g_return_if_fail (handler_id > 0);
891 G_LOCK (g_signal_mutex);
892 handler = handler_lookup (instance, handler_id, &signal_id);
896 handler->block_count = 1;
897 handler_unref_R (signal_id, instance, handler);
900 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
901 G_UNLOCK (g_signal_mutex);
905 g_signal_handlers_destroy (gpointer instance)
907 GBSearchArray *hlbsa;
909 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
911 G_LOCK (g_signal_mutex);
912 hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
917 /* reentrancy caution, delete instance trace first */
918 g_hash_table_remove (g_handler_list_bsa_ht, instance);
920 for (i = 0; i < hlbsa->n_nodes; i++)
922 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
923 Handler *handler = hlist->handlers;
927 Handler *tmp = handler;
930 tmp->block_count = 1;
931 /* cruel unlink, this works because _all_ handlers vanish */
937 handler_unref_R (0, NULL, tmp);
941 g_free (hlbsa->nodes);
942 g_generic_node_free (&g_bsa_ts, hlbsa);
944 G_UNLOCK (g_signal_mutex);
948 g_signal_handler_block (gpointer instance,
953 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
954 g_return_if_fail (handler_id > 0);
956 G_LOCK (g_signal_mutex);
957 handler = handler_lookup (instance, handler_id, NULL);
960 #ifndef G_DISABLE_CHECKS
961 if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
962 g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
965 handler->block_count += 1;
968 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
969 G_UNLOCK (g_signal_mutex);
973 g_signal_handler_unblock (gpointer instance,
978 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
979 g_return_if_fail (handler_id > 0);
981 G_LOCK (g_signal_mutex);
982 handler = handler_lookup (instance, handler_id, NULL);
985 if (handler->block_count)
986 handler->block_count -= 1;
988 g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance);
991 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
992 G_UNLOCK (g_signal_mutex);
996 g_signal_handler_find (gpointer instance,
997 GSignalMatchType mask,
1004 Handler *handler = NULL;
1007 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1008 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1010 G_LOCK (g_signal_mutex);
1011 handler = handler_find (instance, mask, signal_id, detail, closure, func, data);
1012 handler_id = handler ? handler->id : 0;
1013 G_UNLOCK (g_signal_mutex);
1019 g_signal_handler_pending (gpointer instance,
1022 gboolean may_be_blocked)
1024 Handler *handler = NULL;
1026 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1027 g_return_val_if_fail (signal_id > 0, FALSE);
1029 G_LOCK (g_signal_mutex);
1032 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1034 if (!(node->flags & G_SIGNAL_DETAILED))
1036 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1037 G_UNLOCK (g_signal_mutex);
1041 handler = handler_find (instance,
1042 (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL |
1043 (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
1044 signal_id, detail, NULL, NULL, NULL);
1045 G_UNLOCK (g_signal_mutex);
1047 return handler != NULL;
1051 g_signal_emitv (const GValue *instance_and_params,
1054 GValue *return_value)
1058 const GValue *param_values;
1061 g_return_if_fail (instance_and_params != NULL);
1062 instance = g_value_get_as_pointer (instance_and_params);
1063 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1064 g_return_if_fail (signal_id > 0);
1066 param_values = instance_and_params + 1;
1068 G_LOCK (g_signal_mutex);
1069 node = LOOKUP_SIGNAL_NODE (signal_id);
1070 #ifndef G_DISABLE_CHECKS
1071 if (!node || !g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
1072 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1073 if (detail && !(node->flags & G_SIGNAL_DETAILED))
1075 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1076 G_UNLOCK (g_signal_mutex);
1079 for (i = 0; i < node->n_params; i++)
1080 if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
1082 g_critical (G_STRLOC ": value for `%s' parameter %u for signal \"%s\" is of type `%s'",
1083 g_type_name (node->param_types[i]),
1086 G_VALUE_TYPE_NAME (param_values + i));
1087 G_UNLOCK (g_signal_mutex);
1090 if (node->return_type != G_TYPE_NONE)
1094 g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is (NULL)",
1095 g_type_name (node->return_type),
1097 G_UNLOCK (g_signal_mutex);
1100 else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
1102 g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is of type `%s'",
1103 g_type_name (node->return_type),
1105 G_VALUE_TYPE_NAME (return_value));
1106 G_UNLOCK (g_signal_mutex);
1111 return_value = NULL;
1112 #endif /* !G_DISABLE_CHECKS */
1114 signal_emit_R (node, detail, instance, return_value, instance_and_params);
1116 G_UNLOCK (g_signal_mutex);
1120 signal_emit_R (SignalNode *node,
1123 GValue *return_value,
1124 const GValue *instance_and_params)
1126 EmissionState emission_state = 0;
1127 GSignalAccumulator accumulator;
1128 GSignalInvocationHint ihint;
1129 GClosure *class_closure;
1131 Handler *handler_list = NULL;
1133 gboolean accu_used = FALSE;
1134 guint signal_id = node->signal_id;
1136 if (node->flags & G_SIGNAL_NO_RECURSE)
1138 Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance);
1142 *emission->state_p = EMISSION_RESTART;
1146 ihint.signal_id = node->signal_id;
1147 ihint.detail = detail;
1148 accumulator = node->accumulator;
1151 G_UNLOCK (g_signal_mutex);
1152 g_value_init (&accu, node->return_type);
1153 G_LOCK (g_signal_mutex);
1155 emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
1156 signal_id, detail, instance, &emission_state);
1157 class_closure = node->class_closure;
1162 handler_unref_R (signal_id, instance, handler_list);
1163 hlist = handler_list_lookup (signal_id, instance);
1164 handler_list = hlist ? hlist->handlers : NULL;
1166 handler_ref (handler_list);
1168 ihint.run_type = G_SIGNAL_RUN_FIRST;
1170 if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
1172 emission_state = EMISSION_RUN;
1174 G_UNLOCK (g_signal_mutex);
1178 g_value_reset (&accu);
1179 g_closure_invoke (class_closure,
1182 instance_and_params,
1184 if (!accumulator (&ihint, return_value, &accu) &&
1185 emission_state == EMISSION_RUN)
1186 emission_state = EMISSION_STOP;
1190 g_closure_invoke (class_closure,
1193 instance_and_params,
1195 G_LOCK (g_signal_mutex);
1197 if (emission_state == EMISSION_STOP)
1199 else if (emission_state == EMISSION_RESTART)
1203 if (node->emission_hooks)
1205 emission_state = EMISSION_HOOK;
1207 G_UNLOCK (g_signal_mutex);
1208 g_print ("emission_hooks()\n");
1209 G_LOCK (g_signal_mutex);
1211 if (emission_state == EMISSION_RESTART)
1217 Handler *handler = handler_list;
1219 emission_state = EMISSION_RUN;
1220 handler_ref (handler);
1227 handler_unref_R (signal_id, instance, handler_list);
1228 handler_list = handler;
1231 else if (!handler->block_count && (!handler->detail || handler->detail == detail))
1233 G_UNLOCK (g_signal_mutex);
1237 g_value_reset (&accu);
1238 g_closure_invoke (handler->closure,
1241 instance_and_params,
1243 if (!accumulator (&ihint, return_value, &accu) &&
1244 emission_state == EMISSION_RUN)
1245 emission_state = EMISSION_STOP;
1249 g_closure_invoke (handler->closure,
1252 instance_and_params,
1254 G_LOCK (g_signal_mutex);
1256 tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1259 tmp = handler->next;
1263 handler_unref_R (signal_id, instance, handler_list);
1264 handler_list = handler;
1269 if (emission_state == EMISSION_STOP)
1271 else if (emission_state == EMISSION_RESTART)
1275 ihint.run_type = G_SIGNAL_RUN_LAST;
1277 if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
1279 emission_state = EMISSION_RUN;
1281 G_UNLOCK (g_signal_mutex);
1285 g_value_reset (&accu);
1286 g_closure_invoke (class_closure,
1289 instance_and_params,
1291 if (!accumulator (&ihint, return_value, &accu) &&
1292 emission_state == EMISSION_RUN)
1293 emission_state = EMISSION_STOP;
1297 g_closure_invoke (class_closure,
1300 instance_and_params,
1302 G_LOCK (g_signal_mutex);
1304 if (emission_state == EMISSION_STOP)
1306 else if (emission_state == EMISSION_RESTART)
1312 Handler *handler = handler_list;
1314 emission_state = EMISSION_RUN;
1315 handler_ref (handler);
1320 if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail))
1322 G_UNLOCK (g_signal_mutex);
1326 g_value_reset (&accu);
1327 g_closure_invoke (handler->closure,
1330 instance_and_params,
1332 if (!accumulator (&ihint, return_value, &accu) &&
1333 emission_state == EMISSION_RUN)
1334 emission_state = EMISSION_STOP;
1338 g_closure_invoke (handler->closure,
1341 instance_and_params,
1343 G_LOCK (g_signal_mutex);
1345 tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1348 tmp = handler->next;
1352 handler_unref_R (signal_id, instance, handler);
1357 if (emission_state == EMISSION_STOP)
1359 else if (emission_state == EMISSION_RESTART)
1365 ihint.run_type = G_SIGNAL_RUN_CLEANUP;
1367 if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
1369 gboolean need_unset = FALSE;
1371 emission_state = EMISSION_STOP;
1373 G_UNLOCK (g_signal_mutex);
1374 if (node->return_type != G_TYPE_NONE)
1378 g_value_init (&accu, node->return_type);
1382 g_value_reset (&accu);
1384 g_closure_invoke (class_closure,
1385 node->return_type != G_TYPE_NONE ? &accu : NULL,
1387 instance_and_params,
1390 g_value_unset (&accu);
1391 G_LOCK (g_signal_mutex);
1393 if (emission_state == EMISSION_RESTART)
1398 handler_unref_R (signal_id, instance, handler_list);
1400 emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
1403 G_UNLOCK (g_signal_mutex);
1404 g_value_unset (&accu);
1405 G_LOCK (g_signal_mutex);