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,
109 static inline void handler_ref (Handler *handler);
110 static inline void handler_unref_R (guint signal_id,
113 static inline void emission_push (Emission **emission_list_p,
116 EmissionState *state_p);
117 static inline void emission_pop (Emission **emission_list_p);
118 static inline Emission* emission_find (Emission *emission_list,
121 static void signal_emit_R (SignalNode *node,
123 GValue *return_value,
124 const GValue *instance_and_params);
127 /* --- structures --- */
130 /* permanent portion */
136 /* reinitializable portion */
141 GClosure *class_closure;
142 GSignalAccumulator accumulator;
143 GSignalCMarshaller c_marshaller;
144 GHookList *emission_hooks;
159 EmissionState *state_p;
173 guint ref_count : 16;
174 #define HANDLER_MAX_REF_COUNT (1 << 16)
175 guint block_count : 12;
176 #define HANDLER_MAX_BLOCK_COUNT (1 << 12)
182 /* --- variables --- */
183 static GBSearchArray g_signal_key_bsa = { NULL, 0, 0, 0, NULL };
184 static GHashTable *g_handler_list_bsa_ht = NULL;
185 static Emission *g_recursive_emissions = NULL;
186 static Emission *g_restart_emissions = NULL;
187 static GTrashStack *g_bsa_ts = NULL;
188 static GTrashStack *g_handler_ts = NULL;
189 static GTrashStack *g_emission_ts = NULL;
190 G_LOCK_DEFINE_STATIC (g_signal_mutex);
193 /* --- signal nodes --- */
194 static guint g_n_signal_nodes = 0;
195 static SignalNode **g_signal_nodes = NULL;
197 static inline SignalNode*
198 LOOKUP_SIGNAL_NODE (register guint signal_id)
200 if (signal_id < g_n_signal_nodes)
201 return g_signal_nodes[signal_id];
207 /* --- functions --- */
209 signal_id_lookup (GQuark quark,
214 SignalKey key, *signal_key;
219 signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
222 return signal_key->signal_id;
224 itype = g_type_parent (itype);
232 handler_lists_cmp (gconstpointer node1,
235 const HandlerList *hlist1 = node1, *hlist2 = node2;
237 return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
240 static inline HandlerList*
241 handler_list_ensure (guint signal_id,
244 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
249 hlbsa = g_generic_node_alloc (&g_bsa_ts,
250 sizeof (GBSearchArray),
252 hlbsa->cmp_func = handler_lists_cmp;
253 hlbsa->sizeof_node = sizeof (HandlerList);
254 hlbsa->flags = G_BSEARCH_DEFER_SHRINK;
257 g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
259 key.signal_id = signal_id;
262 return g_bsearch_array_insert (hlbsa, &key, FALSE);
265 static inline HandlerList*
266 handler_list_lookup (guint signal_id,
269 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
272 key.signal_id = signal_id;
274 return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL;
278 handler_lookup (gpointer instance,
282 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
288 for (i = 0; i < hlbsa->n_nodes; i++)
290 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
293 for (handler = hlist->handlers; handler; handler = handler->next)
294 if (handler->id == handler_id)
297 *signal_id_p = hlist->signal_id;
308 handler_find (gpointer instance,
309 GSignalMatchType mask,
315 if (mask & G_SIGNAL_MATCH_ID)
317 HandlerList *hlist = handler_list_lookup (signal_id, instance);
321 if (mask & G_SIGNAL_MATCH_FUNC)
323 node = LOOKUP_SIGNAL_NODE (signal_id);
324 if (!node || !node->c_marshaller)
329 for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
330 if (((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
331 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
332 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
333 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
334 handler->closure->meta_marshal == 0 &&
335 ((GCClosure*) handler->closure)->callback == func)))
340 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
347 for (i = 0; i < hlbsa->n_nodes; i++)
349 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
353 if (!(mask & G_SIGNAL_MATCH_FUNC))
355 node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
356 if (!node->c_marshaller)
360 for (handler = hlist->handlers; handler; handler = handler->next)
361 if (((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
362 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
363 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
364 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
365 handler->closure->meta_marshal == 0 &&
366 ((GCClosure*) handler->closure)->callback == func)))
375 static inline Handler*
376 handler_new (gboolean after)
378 static guint handler_id = 1;
379 Handler *handler = g_generic_node_alloc (&g_handler_ts,
382 #ifndef G_DISABLE_CHECKS
384 g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
387 handler->id = handler_id++;
388 handler->prev = NULL;
389 handler->next = NULL;
390 handler->ref_count = 1;
391 handler->block_count = 0;
392 handler->after = after != FALSE;
393 handler->closure = NULL;
399 handler_ref (Handler *handler)
401 g_return_if_fail (handler->ref_count > 0);
403 #ifndef G_DISABLE_CHECKS
404 if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
405 g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
408 handler->ref_count += 1;
412 handler_unref_R (guint signal_id,
416 g_return_if_fail (handler->ref_count > 0);
418 handler->ref_count -= 1;
419 if (!handler->ref_count)
422 handler->next->prev = handler->prev;
423 if (handler->prev) /* watch out for g_signal_handlers_destroy()! */
424 handler->prev->next = handler->next;
427 HandlerList *hlist = handler_list_lookup (signal_id, instance);
429 hlist->handlers = handler->next;
431 G_UNLOCK (g_signal_mutex);
432 g_closure_unref (handler->closure);
433 G_LOCK (g_signal_mutex);
434 g_generic_node_free (&g_handler_ts, handler);
439 handler_insert (guint signal_id,
445 g_assert (handler->prev == NULL && handler->next == NULL); // FIXME: paranoid
447 hlist = handler_list_ensure (signal_id, instance);
448 if (!hlist->handlers)
449 hlist->handlers = handler;
450 else if (hlist->handlers->after && !handler->after)
452 handler->next = hlist->handlers;
453 hlist->handlers->prev = handler;
454 hlist->handlers = handler;
458 Handler *tmp = hlist->handlers;
464 while (tmp->next && !tmp->next->after)
467 tmp->next->prev = handler;
468 handler->next = tmp->next;
475 emission_push (Emission **emission_list_p,
478 EmissionState *state_p)
480 Emission *emission = g_generic_node_alloc (&g_emission_ts,
483 emission->next = *emission_list_p;
484 emission->signal_id = signal_id;
485 emission->instance = instance;
486 emission->state_p = state_p;
487 *emission_list_p = emission;
491 emission_pop (Emission **emission_list_p)
493 Emission *emission = *emission_list_p;
495 *emission_list_p = emission->next;
496 g_generic_node_free (&g_emission_ts, emission);
499 static inline Emission*
500 emission_find (Emission *emission_list,
506 for (emission = emission_list; emission; emission = emission->next)
507 if (emission->instance == instance && emission->signal_id == signal_id)
513 signal_key_cmp (gconstpointer node1,
516 const SignalKey *key1 = node1, *key2 = node2;
518 if (key1->itype == key2->itype)
519 return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
521 return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
525 g_signal_init (void) /* sync with gtype.c */
527 G_LOCK (g_signal_mutex);
528 if (!g_n_signal_nodes)
530 /* setup signal key array */
531 g_signal_key_bsa.cmp_func = signal_key_cmp;
532 g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
533 g_signal_key_bsa.flags = 0; /* alloc-only */
535 /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
536 g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
538 /* invalid (0) signal_id */
539 g_n_signal_nodes = 1;
540 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
541 g_signal_nodes[0] = NULL;
543 G_UNLOCK (g_signal_mutex);
547 g_signals_destroy (GType itype)
550 gboolean found_one = FALSE;
552 G_LOCK (g_signal_mutex);
553 for (i = 0; i < g_n_signal_nodes; i++)
555 SignalNode *node = g_signal_nodes[i];
557 if (node->itype == itype)
560 g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
562 g_type_name (node->itype));
566 signal_destroy_R (node);
571 g_warning (G_STRLOC ": type `%s' has no signals that could be destroyed",
572 g_type_name (itype));
573 G_UNLOCK (g_signal_mutex);
577 g_signal_stop_emission (gpointer instance,
582 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
583 g_return_if_fail (signal_id > 0);
585 G_LOCK (g_signal_mutex);
586 node = LOOKUP_SIGNAL_NODE (signal_id);
587 if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
589 Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
590 Emission *emission = emission_find (emission_list, signal_id, instance);
594 if (*emission->state_p == EMISSION_HOOK)
595 g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
596 node->name, instance);
597 else if (*emission->state_p == EMISSION_RUN)
598 *emission->state_p = EMISSION_STOP;
601 g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
602 node->name, instance);
605 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
606 G_UNLOCK (g_signal_mutex);
610 g_signal_lookup (const gchar *name,
615 g_return_val_if_fail (name != NULL, 0);
616 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
618 G_LOCK (g_signal_mutex);
619 signal_id = signal_id_lookup (g_quark_try_string (name), itype);
620 G_UNLOCK (g_signal_mutex);
626 g_signal_name (guint signal_id)
631 G_LOCK (g_signal_mutex);
632 node = LOOKUP_SIGNAL_NODE (signal_id);
633 name = node ? node->name : NULL;
634 G_UNLOCK (g_signal_mutex);
640 g_signal_query (guint signal_id,
645 g_return_if_fail (query != NULL);
647 G_LOCK (g_signal_mutex);
648 node = LOOKUP_SIGNAL_NODE (signal_id);
649 if (!node || node->destroyed)
650 query->signal_id = 0;
653 query->signal_id = node->signal_id;
654 query->signal_name = node->name;
655 query->itype = node->itype;
656 query->signal_flags = node->flags;
657 query->return_type = node->return_type;
658 query->n_params = node->n_params;
659 query->param_types = node->param_types;
661 G_UNLOCK (g_signal_mutex);
665 g_signal_newv (const gchar *signal_name,
667 GSignalType signal_flags,
668 GClosure *class_closure,
669 GSignalAccumulator accumulator,
670 GSignalCMarshaller c_marshaller,
679 g_return_val_if_fail (signal_name != NULL, 0);
680 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
682 g_return_val_if_fail (param_types != NULL, 0);
683 if (return_type != G_TYPE_NONE)
684 g_return_val_if_fail (accumulator == NULL, 0);
686 name = g_strdup (signal_name);
687 g_strdelimit (name, G_STR_DELIMITERS ":^", '_'); // FIXME do character checks like for types
689 G_LOCK (g_signal_mutex);
691 signal_id = signal_id_lookup (g_quark_try_string (name), itype);
692 node = LOOKUP_SIGNAL_NODE (signal_id);
693 if (node && !node->destroyed)
695 g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
697 g_type_name (node->itype),
698 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
700 G_UNLOCK (g_signal_mutex);
703 if (node && node->itype != itype)
705 g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
708 g_type_name (node->itype));
710 G_UNLOCK (g_signal_mutex);
713 for (i = 0; i < n_params; i++)
714 if (!G_TYPE_IS_VALUE (param_types[i]) ||
715 param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */
717 g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
718 i + 1, g_type_name (param_types[i]), g_type_name (itype), name);
720 G_UNLOCK (g_signal_mutex);
723 if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type))
725 g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
726 g_type_name (param_types[i]), g_type_name (itype), name);
728 G_UNLOCK (g_signal_mutex);
732 /* setup permanent portion of signal node */
737 signal_id = g_n_signal_nodes++;
738 node = g_new (SignalNode, 1);
739 node->signal_id = signal_id;
740 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
741 g_signal_nodes[signal_id] = node;
745 key.quark = g_quark_from_string (node->name);
746 key.signal_id = signal_id;
747 g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
748 g_strdelimit (node->name, "_", '-');
749 key.quark = g_quark_from_static_string (node->name);
750 g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
752 node->destroyed = FALSE;
754 /* setup reinitializable portion */
755 node->flags = signal_flags & (G_SIGNAL_RUN_FIRST |
757 G_SIGNAL_RUN_CLEANUP |
758 G_SIGNAL_NO_RECURSE |
761 node->n_params = n_params;
762 node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
763 node->return_type = return_type;
764 node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL;
765 node->accumulator = accumulator;
766 node->c_marshaller = c_marshaller;
767 node->emission_hooks = NULL;
768 if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure))
769 g_closure_set_marshal (class_closure, node->c_marshaller);
771 G_UNLOCK (g_signal_mutex);
776 signal_destroy_R (SignalNode *signal_node)
778 SignalNode node = *signal_node;
780 signal_node->destroyed = TRUE;
782 /* reentrancy caution, zero out real contents first */
783 signal_node->n_params = 0;
784 signal_node->param_types = NULL;
785 signal_node->return_type = 0;
786 signal_node->class_closure = NULL;
787 signal_node->accumulator = NULL;
788 signal_node->c_marshaller = NULL;
789 signal_node->emission_hooks = NULL;
791 #ifndef G_DISABLE_CHECKS
792 /* check current emissions */
796 for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
797 emission; emission = emission->next)
798 if (emission->signal_id == node.signal_id)
799 g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
800 node.name, emission->instance);
804 /* free contents that need to
806 G_UNLOCK (g_signal_mutex);
807 g_free (node.param_types);
808 g_closure_unref (node.class_closure);
809 if (node.emission_hooks)
811 g_hook_list_clear (node.emission_hooks);
812 g_free (node.emission_hooks);
814 G_LOCK (g_signal_mutex);
818 g_signal_connect_closure (gpointer instance,
824 guint handler_id = 0;
826 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
827 g_return_val_if_fail (signal_id > 0, 0);
828 g_return_val_if_fail (closure != NULL, 0);
830 G_LOCK (g_signal_mutex);
831 node = LOOKUP_SIGNAL_NODE (signal_id);
832 if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
834 Handler *handler = handler_new (after);
836 handler_id = handler->id;
837 handler->closure = g_closure_ref (closure);
838 handler_insert (signal_id, instance, handler);
839 if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
840 g_closure_set_marshal (closure, node->c_marshaller);
843 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
844 G_UNLOCK (g_signal_mutex);
850 g_signal_handler_disconnect (gpointer instance,
856 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
857 g_return_if_fail (handler_id > 0);
859 G_LOCK (g_signal_mutex);
860 handler = handler_lookup (instance, handler_id, &signal_id);
864 handler->block_count = 1;
865 handler_unref_R (signal_id, instance, handler);
868 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
869 G_UNLOCK (g_signal_mutex);
873 g_signal_handlers_destroy (gpointer instance)
875 GBSearchArray *hlbsa;
877 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
879 G_LOCK (g_signal_mutex);
880 hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
885 /* reentrancy caution, delete instance trace first */
886 g_hash_table_remove (g_handler_list_bsa_ht, instance);
888 for (i = 0; i < hlbsa->n_nodes; i++)
890 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
891 Handler *handler = hlist->handlers;
895 Handler *tmp = handler;
898 tmp->block_count = 1;
899 /* cruel unlink, this works because _all_ handlers vanish */
905 handler_unref_R (0, NULL, tmp);
909 g_free (hlbsa->nodes);
910 g_generic_node_free (&g_bsa_ts, hlbsa);
912 G_UNLOCK (g_signal_mutex);
916 g_signal_handler_block (gpointer instance,
921 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
922 g_return_if_fail (handler_id > 0);
924 G_LOCK (g_signal_mutex);
925 handler = handler_lookup (instance, handler_id, NULL);
928 #ifndef G_DISABLE_CHECKS
929 if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
930 g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
933 handler->block_count += 1;
936 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
937 G_UNLOCK (g_signal_mutex);
941 g_signal_handler_unblock (gpointer instance,
946 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
947 g_return_if_fail (handler_id > 0);
949 G_LOCK (g_signal_mutex);
950 handler = handler_lookup (instance, handler_id, NULL);
953 if (handler->block_count)
954 handler->block_count -= 1;
956 g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance);
959 g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
960 G_UNLOCK (g_signal_mutex);
964 g_signal_handler_find (gpointer instance,
965 GSignalMatchType mask,
971 Handler *handler = NULL;
974 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
976 G_LOCK (g_signal_mutex);
977 handler = handler_find (instance, mask, signal_id, closure, func, data);
978 handler_id = handler ? handler->id : 0;
979 G_UNLOCK (g_signal_mutex);
985 g_signal_handler_pending (gpointer instance,
987 gboolean may_be_blocked)
989 Handler *handler = NULL;
991 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
992 g_return_val_if_fail (signal_id > 0, FALSE);
994 G_LOCK (g_signal_mutex);
995 handler = handler_find (instance, G_SIGNAL_MATCH_ID, signal_id, NULL, NULL, NULL);
997 for (; handler; handler = handler->next)
998 if (!handler->block_count)
1000 G_UNLOCK (g_signal_mutex);
1002 return handler != NULL;
1006 g_signal_emitv (const GValue *instance_and_params,
1008 GValue *return_value)
1012 const GValue *param_values;
1015 g_return_if_fail (instance_and_params != NULL);
1016 instance = g_value_get_as_pointer (instance_and_params);
1017 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1018 g_return_if_fail (signal_id > 0);
1020 param_values = instance_and_params + 1;
1022 G_LOCK (g_signal_mutex);
1023 node = LOOKUP_SIGNAL_NODE (signal_id);
1024 #ifndef G_DISABLE_CHECKS
1025 if (!node || !g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
1026 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1027 for (i = 0; i < node->n_params; i++)
1028 if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
1030 g_critical (G_STRLOC ": value for `%s' parameter %u for signal \"%s\" is of type `%s'",
1031 g_type_name (node->param_types[i]),
1034 G_VALUE_TYPE_NAME (param_values + i));
1035 G_UNLOCK (g_signal_mutex);
1038 if (node->return_type != G_TYPE_NONE)
1042 g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is (NULL)",
1043 g_type_name (node->return_type),
1045 G_UNLOCK (g_signal_mutex);
1048 else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
1050 g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is of type `%s'",
1051 g_type_name (node->return_type),
1053 G_VALUE_TYPE_NAME (return_value));
1054 G_UNLOCK (g_signal_mutex);
1059 return_value = NULL;
1060 #endif /* !G_DISABLE_CHECKS */
1062 signal_emit_R (node, instance, return_value, instance_and_params);
1064 G_UNLOCK (g_signal_mutex);
1068 signal_emit_R (SignalNode *node,
1070 GValue *return_value,
1071 const GValue *instance_and_params)
1073 EmissionState emission_state = 0;
1074 GSignalAccumulator accumulator;
1075 GClosure *class_closure;
1079 gboolean accu_used = FALSE;
1080 guint signal_id = node->signal_id;
1082 if (node->flags & G_SIGNAL_NO_RECURSE)
1084 Emission *emission = emission_find (g_restart_emissions, signal_id, instance);
1088 *emission->state_p = EMISSION_RESTART;
1092 accumulator = node->accumulator;
1095 G_UNLOCK (g_signal_mutex);
1096 g_value_init (&accu, node->return_type);
1097 G_LOCK (g_signal_mutex);
1099 emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
1100 signal_id, instance, &emission_state);
1101 class_closure = node->class_closure;
1102 hlist = handler_list_lookup (signal_id, instance);
1103 handlers = hlist ? hlist->handlers : NULL;
1105 handler_ref (handlers);
1109 if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
1111 emission_state = EMISSION_RUN;
1113 G_UNLOCK (g_signal_mutex);
1117 g_value_reset (&accu);
1118 g_closure_invoke (class_closure,
1119 (signal_id << 8) | G_SIGNAL_RUN_FIRST,
1122 instance_and_params);
1123 if (!accumulator (signal_id, return_value, &accu) &&
1124 emission_state == EMISSION_RUN)
1125 emission_state = EMISSION_STOP;
1129 g_closure_invoke (class_closure,
1130 (signal_id << 8) | G_SIGNAL_RUN_FIRST,
1133 instance_and_params);
1134 G_LOCK (g_signal_mutex);
1136 if (emission_state == EMISSION_STOP)
1138 else if (emission_state == EMISSION_RESTART)
1142 if (node->emission_hooks)
1144 emission_state = EMISSION_HOOK;
1146 G_UNLOCK (g_signal_mutex);
1147 g_print ("emission_hooks()\n");
1148 G_LOCK (g_signal_mutex);
1150 if (emission_state == EMISSION_RESTART)
1156 Handler *handler = handlers;
1158 emission_state = EMISSION_RUN;
1160 handler_ref (handler);
1165 if (!handler->after && !handler->block_count)
1167 G_UNLOCK (g_signal_mutex);
1171 g_value_reset (&accu);
1172 g_closure_invoke (handler->closure,
1173 (signal_id << 8) | G_SIGNAL_RUN_FIRST,
1176 instance_and_params);
1177 if (!accumulator (signal_id, return_value, &accu) &&
1178 emission_state == EMISSION_RUN)
1179 emission_state = EMISSION_STOP;
1183 g_closure_invoke (handler->closure,
1184 (signal_id << 8) | G_SIGNAL_RUN_FIRST,
1187 instance_and_params);
1188 G_LOCK (g_signal_mutex);
1190 tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1193 tmp = handler->next;
1197 handler_unref_R (signal_id, instance, handler);
1202 if (emission_state == EMISSION_STOP)
1204 else if (emission_state == EMISSION_RESTART)
1208 if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
1210 emission_state = EMISSION_RUN;
1212 G_UNLOCK (g_signal_mutex);
1216 g_value_reset (&accu);
1217 g_closure_invoke (class_closure,
1218 (signal_id << 8) | G_SIGNAL_RUN_LAST,
1221 instance_and_params);
1222 if (!accumulator (signal_id, return_value, &accu) &&
1223 emission_state == EMISSION_RUN)
1224 emission_state = EMISSION_STOP;
1228 g_closure_invoke (class_closure,
1229 (signal_id << 8) | G_SIGNAL_RUN_LAST,
1232 instance_and_params);
1233 G_LOCK (g_signal_mutex);
1235 if (emission_state == EMISSION_STOP)
1237 else if (emission_state == EMISSION_RESTART)
1243 Handler *handler = handlers;
1245 emission_state = EMISSION_RUN;
1247 handler_ref (handler);
1252 if (handler->after && !handler->block_count)
1254 G_UNLOCK (g_signal_mutex);
1258 g_value_reset (&accu);
1259 g_closure_invoke (handler->closure,
1260 (signal_id << 8) | G_SIGNAL_RUN_LAST,
1263 instance_and_params);
1264 if (!accumulator (signal_id, return_value, &accu) &&
1265 emission_state == EMISSION_RUN)
1266 emission_state = EMISSION_STOP;
1270 g_closure_invoke (handler->closure,
1271 (signal_id << 8) | G_SIGNAL_RUN_LAST,
1274 instance_and_params);
1275 G_LOCK (g_signal_mutex);
1277 tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1280 tmp = handler->next;
1284 handler_unref_R (signal_id, instance, handler);
1289 if (emission_state == EMISSION_STOP)
1291 else if (emission_state == EMISSION_RESTART)
1297 if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
1299 emission_state = EMISSION_STOP;
1301 G_UNLOCK (g_signal_mutex);
1302 if (node->return_type != G_TYPE_NONE)
1305 g_value_init (&accu, node->return_type);
1307 g_value_reset (&accu);
1310 g_closure_invoke (class_closure,
1311 (signal_id << 8) | G_SIGNAL_RUN_CLEANUP,
1312 node->return_type != G_TYPE_NONE ? &accu : NULL,
1314 instance_and_params);
1315 if (node->return_type != G_TYPE_NONE && !accumulator)
1316 g_value_unset (&accu);
1317 G_LOCK (g_signal_mutex);
1319 if (emission_state == EMISSION_RESTART)
1324 handler_unref_R (signal_id, instance, handlers);
1326 emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions);
1329 G_UNLOCK (g_signal_mutex);
1330 g_value_unset (&accu);
1331 G_LOCK (g_signal_mutex);