gsignal.c revision 0cba1b531d5d28890fa4f48359d4e7adacf2a603
1/* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 2000-2001 Red Hat, Inc.
3 *
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.
8 *
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.
13 *
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.
18 *
19 * this code is based on the original GtkSignal implementation
20 * for the Gtk+ library by Peter Mattis <petm@xcf.berkeley.edu>
21 */
22
23/*
24 * MT safe
25 */
26
27#include <config.h>
28
29#include        "gsignal.h"
30
31#include        "gbsearcharray.h"
32#include        "gvaluecollector.h"
33#include	"gvaluetypes.h"
34#include	"gboxed.h"
35
36#include	"gobjectalias.h"
37
38#include	<string.h>
39#include	<signal.h>
40
41
42/* pre allocation configurations
43 */
44#define	MAX_STACK_VALUES	(16)
45
46#define REPORT_BUG      "please report occurrence circumstances to gtk-devel-list@gnome.org"
47#ifdef	G_ENABLE_DEBUG
48#define IF_DEBUG(debug_type, cond)	if ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || cond)
49static volatile gpointer g_trace_instance_signals = NULL;
50static volatile gpointer g_trap_instance_signals = NULL;
51#endif	/* G_ENABLE_DEBUG */
52
53
54/* --- typedefs --- */
55typedef struct _SignalNode   SignalNode;
56typedef struct _SignalKey    SignalKey;
57typedef struct _Emission     Emission;
58typedef struct _Handler      Handler;
59typedef struct _HandlerList  HandlerList;
60typedef struct _HandlerMatch HandlerMatch;
61typedef enum
62{
63  EMISSION_STOP,
64  EMISSION_RUN,
65  EMISSION_HOOK,
66  EMISSION_RESTART
67} EmissionState;
68
69
70/* --- prototypes --- */
71static inline guint		signal_id_lookup	(GQuark		  quark,
72							 GType		  itype);
73static	      void		signal_destroy_R	(SignalNode	 *signal_node);
74static inline HandlerList*	handler_list_ensure	(guint		  signal_id,
75							 gpointer	  instance);
76static inline HandlerList*	handler_list_lookup	(guint		  signal_id,
77							 gpointer	  instance);
78static inline Handler*		handler_new		(gboolean	  after);
79static	      void		handler_insert		(guint		  signal_id,
80							 gpointer	  instance,
81							 Handler	 *handler);
82static	      Handler*		handler_lookup		(gpointer	  instance,
83							 gulong		  handler_id,
84							 guint		 *signal_id_p);
85static inline HandlerMatch*	handler_match_prepend	(HandlerMatch	 *list,
86							 Handler	 *handler,
87							 guint		  signal_id);
88static inline HandlerMatch*	handler_match_free1_R	(HandlerMatch	 *node,
89							 gpointer	  instance);
90static	      HandlerMatch*	handlers_find		(gpointer	  instance,
91							 GSignalMatchType mask,
92							 guint		  signal_id,
93							 GQuark		  detail,
94							 GClosure	 *closure,
95							 gpointer	  func,
96							 gpointer	  data,
97							 gboolean	  one_and_only);
98static inline void		handler_ref		(Handler	 *handler);
99static inline void		handler_unref_R		(guint		  signal_id,
100							 gpointer	  instance,
101							 Handler	 *handler);
102static gint			handler_lists_cmp	(gconstpointer	  node1,
103							 gconstpointer	  node2);
104static inline void		emission_push		(Emission	**emission_list_p,
105							 Emission	 *emission);
106static inline void		emission_pop		(Emission	**emission_list_p,
107							 Emission	 *emission);
108static inline Emission*		emission_find		(Emission	 *emission_list,
109							 guint		  signal_id,
110							 GQuark		  detail,
111							 gpointer	  instance);
112static gint			class_closures_cmp	(gconstpointer	  node1,
113							 gconstpointer	  node2);
114static gint			signal_key_cmp		(gconstpointer	  node1,
115							 gconstpointer	  node2);
116static	      gboolean		signal_emit_unlocked_R	(SignalNode	 *node,
117							 GQuark		  detail,
118							 gpointer	  instance,
119							 GValue		 *return_value,
120							 const GValue	 *instance_and_params);
121static const gchar *            type_debug_name         (GType            type);
122
123
124/* --- structures --- */
125typedef struct
126{
127  GSignalAccumulator func;
128  gpointer           data;
129} SignalAccumulator;
130typedef struct
131{
132  GHook hook;
133  GQuark detail;
134} SignalHook;
135#define	SIGNAL_HOOK(hook)	((SignalHook*) (hook))
136
137struct _SignalNode
138{
139  /* permanent portion */
140  guint              signal_id;
141  GType              itype;
142  const gchar       *name;
143  guint              destroyed : 1;
144
145  /* reinitializable portion */
146  guint		     test_class_offset : 12;
147  guint              flags : 8;
148  guint              n_params : 8;
149  GType		    *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
150  GType		     return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
151  GBSearchArray     *class_closure_bsa;
152  SignalAccumulator *accumulator;
153  GSignalCMarshaller c_marshaller;
154  GHookList         *emission_hooks;
155};
156#define	MAX_TEST_CLASS_OFFSET	(4096)	/* 2^12, 12 bits for test_class_offset */
157#define	TEST_CLASS_MAGIC	(1)	/* indicates NULL class closure, candidate for NOP optimization */
158
159struct _SignalKey
160{
161  GType  itype;
162  GQuark quark;
163  guint  signal_id;
164};
165
166struct _Emission
167{
168  Emission             *next;
169  gpointer              instance;
170  GSignalInvocationHint ihint;
171  EmissionState         state;
172  GType			chain_type;
173};
174
175struct _HandlerList
176{
177  guint    signal_id;
178  Handler *handlers;
179  Handler *tail_before;  /* normal signal handlers are appended here  */
180  Handler *tail_after;   /* CONNECT_AFTER handlers are appended here  */
181};
182
183struct _Handler
184{
185  gulong        sequential_number;
186  Handler      *next;
187  Handler      *prev;
188  GQuark	detail;
189  guint         ref_count;
190  guint         block_count : 16;
191#define HANDLER_MAX_BLOCK_COUNT (1 << 16)
192  guint         after : 1;
193  GClosure     *closure;
194};
195struct _HandlerMatch
196{
197  Handler      *handler;
198  HandlerMatch *next;
199  guint         signal_id;
200};
201
202typedef struct
203{
204  GType     instance_type; /* 0 for default closure */
205  GClosure *closure;
206} ClassClosure;
207
208
209/* --- variables --- */
210static GBSearchArray *g_signal_key_bsa = NULL;
211static const GBSearchConfig g_signal_key_bconfig = {
212  sizeof (SignalKey),
213  signal_key_cmp,
214  G_BSEARCH_ARRAY_ALIGN_POWER2,
215};
216static GBSearchConfig g_signal_hlbsa_bconfig = {
217  sizeof (HandlerList),
218  handler_lists_cmp,
219  0,
220};
221static GBSearchConfig g_class_closure_bconfig = {
222  sizeof (ClassClosure),
223  class_closures_cmp,
224  0,
225};
226static GHashTable    *g_handler_list_bsa_ht = NULL;
227static Emission      *g_recursive_emissions = NULL;
228static Emission      *g_restart_emissions = NULL;
229#ifndef DISABLE_MEM_POOLS
230static GTrashStack   *g_handler_ts = NULL;
231#endif
232static gulong         g_handler_sequential_number = 1;
233G_LOCK_DEFINE_STATIC (g_signal_mutex);
234#define	SIGNAL_LOCK()		G_LOCK (g_signal_mutex)
235#define	SIGNAL_UNLOCK()		G_UNLOCK (g_signal_mutex)
236
237
238/* --- signal nodes --- */
239static guint          g_n_signal_nodes = 0;
240static SignalNode   **g_signal_nodes = NULL;
241
242static inline SignalNode*
243LOOKUP_SIGNAL_NODE (register guint signal_id)
244{
245  if (signal_id < g_n_signal_nodes)
246    return g_signal_nodes[signal_id];
247  else
248    return NULL;
249}
250
251
252/* --- functions --- */
253static inline guint
254signal_id_lookup (GQuark quark,
255		  GType  itype)
256{
257  GType *ifaces, type = itype;
258  SignalKey key;
259  guint n_ifaces;
260
261  key.quark = quark;
262
263  /* try looking up signals for this type and its ancestors */
264  do
265    {
266      SignalKey *signal_key;
267
268      key.itype = type;
269      signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
270
271      if (signal_key)
272	return signal_key->signal_id;
273
274      type = g_type_parent (type);
275    }
276  while (type);
277
278  /* no luck, try interfaces it exports */
279  ifaces = g_type_interfaces (itype, &n_ifaces);
280  while (n_ifaces--)
281    {
282      SignalKey *signal_key;
283
284      key.itype = ifaces[n_ifaces];
285      signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
286
287      if (signal_key)
288	{
289	  g_free (ifaces);
290	  return signal_key->signal_id;
291	}
292    }
293  g_free (ifaces);
294
295  return 0;
296}
297
298static gint
299class_closures_cmp (gconstpointer node1,
300		    gconstpointer node2)
301{
302  const ClassClosure *c1 = node1, *c2 = node2;
303
304  return G_BSEARCH_ARRAY_CMP (c1->instance_type, c2->instance_type);
305}
306
307static gint
308handler_lists_cmp (gconstpointer node1,
309                   gconstpointer node2)
310{
311  const HandlerList *hlist1 = node1, *hlist2 = node2;
312
313  return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
314}
315
316static inline HandlerList*
317handler_list_ensure (guint    signal_id,
318		     gpointer instance)
319{
320  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
321  HandlerList key;
322
323  key.signal_id = signal_id;
324  key.handlers    = NULL;
325  key.tail_before = NULL;
326  key.tail_after  = NULL;
327  if (!hlbsa)
328    {
329      hlbsa = g_bsearch_array_create (&g_signal_hlbsa_bconfig);
330      hlbsa = g_bsearch_array_insert (hlbsa, &g_signal_hlbsa_bconfig, &key);
331      g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
332    }
333  else
334    {
335      GBSearchArray *o = hlbsa;
336
337      hlbsa = g_bsearch_array_insert (o, &g_signal_hlbsa_bconfig, &key);
338      if (hlbsa != o)
339	g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
340    }
341  return g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key);
342}
343
344static inline HandlerList*
345handler_list_lookup (guint    signal_id,
346		     gpointer instance)
347{
348  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
349  HandlerList key;
350
351  key.signal_id = signal_id;
352
353  return hlbsa ? g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key) : NULL;
354}
355
356static Handler*
357handler_lookup (gpointer instance,
358		gulong   handler_id,
359		guint   *signal_id_p)
360{
361  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
362
363  if (hlbsa)
364    {
365      guint i;
366
367      for (i = 0; i < hlbsa->n_nodes; i++)
368        {
369          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
370          Handler *handler;
371
372          for (handler = hlist->handlers; handler; handler = handler->next)
373            if (handler->sequential_number == handler_id)
374              {
375                if (signal_id_p)
376                  *signal_id_p = hlist->signal_id;
377
378                return handler;
379              }
380        }
381    }
382
383  return NULL;
384}
385
386static inline HandlerMatch*
387handler_match_prepend (HandlerMatch *list,
388		       Handler      *handler,
389		       guint	     signal_id)
390{
391  HandlerMatch *node;
392
393  /* yeah, we could use our own memchunk here, introducing yet more
394   * rarely used cached nodes and extra allocation overhead.
395   * instead, we use GList* nodes, since they are exactly the size
396   * we need and are already cached. g_signal_init() asserts this.
397   */
398  node = g_slice_new (HandlerMatch);
399  node->handler = handler;
400  node->next = list;
401  node->signal_id = signal_id;
402  handler_ref (handler);
403
404  return node;
405}
406static inline HandlerMatch*
407handler_match_free1_R (HandlerMatch *node,
408		       gpointer      instance)
409{
410  HandlerMatch *next = node->next;
411
412  handler_unref_R (node->signal_id, instance, node->handler);
413  g_slice_free (HandlerMatch, node);
414
415  return next;
416}
417
418static HandlerMatch*
419handlers_find (gpointer         instance,
420	       GSignalMatchType mask,
421	       guint            signal_id,
422	       GQuark           detail,
423	       GClosure        *closure,
424	       gpointer         func,
425	       gpointer         data,
426	       gboolean         one_and_only)
427{
428  HandlerMatch *mlist = NULL;
429
430  if (mask & G_SIGNAL_MATCH_ID)
431    {
432      HandlerList *hlist = handler_list_lookup (signal_id, instance);
433      Handler *handler;
434      SignalNode *node = NULL;
435
436      if (mask & G_SIGNAL_MATCH_FUNC)
437	{
438	  node = LOOKUP_SIGNAL_NODE (signal_id);
439	  if (!node || !node->c_marshaller)
440	    return NULL;
441	}
442
443      mask = ~mask;
444      for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
445        if (handler->sequential_number &&
446	    ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
447	    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
448            ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
449	    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
450	    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
451					      handler->closure->meta_marshal == 0 &&
452					      ((GCClosure*) handler->closure)->callback == func)))
453	  {
454	    mlist = handler_match_prepend (mlist, handler, signal_id);
455	    if (one_and_only)
456	      return mlist;
457	  }
458    }
459  else
460    {
461      GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
462
463      mask = ~mask;
464      if (hlbsa)
465        {
466          guint i;
467
468          for (i = 0; i < hlbsa->n_nodes; i++)
469            {
470              HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
471	      SignalNode *node = NULL;
472              Handler *handler;
473
474	      if (!(mask & G_SIGNAL_MATCH_FUNC))
475		{
476		  node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
477		  if (!node->c_marshaller)
478		    continue;
479		}
480
481              for (handler = hlist->handlers; handler; handler = handler->next)
482		if (handler->sequential_number &&
483		    ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
484                    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
485                    ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
486		    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
487		    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
488						      handler->closure->meta_marshal == 0 &&
489						      ((GCClosure*) handler->closure)->callback == func)))
490		  {
491		    mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
492		    if (one_and_only)
493		      return mlist;
494		  }
495            }
496        }
497    }
498
499  return mlist;
500}
501
502static inline Handler*
503handler_new (gboolean after)
504{
505  Handler *handler = g_slice_new (Handler);
506#ifndef G_DISABLE_CHECKS
507  if (g_handler_sequential_number < 1)
508    g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
509#endif
510
511  handler->sequential_number = g_handler_sequential_number++;
512  handler->prev = NULL;
513  handler->next = NULL;
514  handler->detail = 0;
515  handler->ref_count = 1;
516  handler->block_count = 0;
517  handler->after = after != FALSE;
518  handler->closure = NULL;
519
520  return handler;
521}
522
523static inline void
524handler_ref (Handler *handler)
525{
526  g_return_if_fail (handler->ref_count > 0);
527
528  g_atomic_int_inc (&handler->ref_count);
529}
530
531static inline void
532handler_unref_R (guint    signal_id,
533		 gpointer instance,
534		 Handler *handler)
535{
536  gboolean is_zero;
537
538  g_return_if_fail (handler->ref_count > 0);
539
540  is_zero = g_atomic_int_dec_and_test (&handler->ref_count);
541
542  if (G_UNLIKELY (is_zero))
543    {
544      HandlerList *hlist = NULL;
545
546      if (handler->next)
547        handler->next->prev = handler->prev;
548      if (handler->prev)    /* watch out for g_signal_handlers_destroy()! */
549        handler->prev->next = handler->next;
550      else
551        {
552          hlist = handler_list_lookup (signal_id, instance);
553          hlist->handlers = handler->next;
554        }
555
556      if (instance)
557        {
558          /*  check if we are removing the handler pointed to by tail_before  */
559          if (!handler->after && (!handler->next || handler->next->after))
560            {
561              if (!hlist)
562                hlist = handler_list_lookup (signal_id, instance);
563              if (hlist)
564                {
565                  g_assert (hlist->tail_before == handler); /* paranoid */
566                  hlist->tail_before = handler->prev;
567                }
568            }
569
570          /*  check if we are removing the handler pointed to by tail_after  */
571          if (!handler->next)
572            {
573              if (!hlist)
574                hlist = handler_list_lookup (signal_id, instance);
575              if (hlist)
576                {
577                  g_assert (hlist->tail_after == handler); /* paranoid */
578                  hlist->tail_after = handler->prev;
579                }
580            }
581        }
582
583      SIGNAL_UNLOCK ();
584      g_closure_unref (handler->closure);
585      SIGNAL_LOCK ();
586      g_slice_free (Handler, handler);
587    }
588}
589
590static void
591handler_insert (guint    signal_id,
592		gpointer instance,
593		Handler  *handler)
594{
595  HandlerList *hlist;
596
597  g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
598
599  hlist = handler_list_ensure (signal_id, instance);
600  if (!hlist->handlers)
601    {
602      hlist->handlers = handler;
603      if (!handler->after)
604        hlist->tail_before = handler;
605    }
606  else if (handler->after)
607    {
608      handler->prev = hlist->tail_after;
609      hlist->tail_after->next = handler;
610    }
611  else
612    {
613      if (hlist->tail_before)
614        {
615          handler->next = hlist->tail_before->next;
616          if (handler->next)
617            handler->next->prev = handler;
618          handler->prev = hlist->tail_before;
619          hlist->tail_before->next = handler;
620        }
621      else /* insert !after handler into a list of only after handlers */
622        {
623          handler->next = hlist->handlers;
624          if (handler->next)
625            handler->next->prev = handler;
626          hlist->handlers = handler;
627        }
628      hlist->tail_before = handler;
629    }
630
631  if (!handler->next)
632    hlist->tail_after = handler;
633}
634
635static inline void
636emission_push (Emission **emission_list_p,
637	       Emission  *emission)
638{
639  emission->next = *emission_list_p;
640  *emission_list_p = emission;
641}
642
643static inline void
644emission_pop (Emission **emission_list_p,
645	      Emission  *emission)
646{
647  Emission *node, *last = NULL;
648
649  for (node = *emission_list_p; node; last = node, node = last->next)
650    if (node == emission)
651      {
652	if (last)
653	  last->next = node->next;
654	else
655	  *emission_list_p = node->next;
656	return;
657      }
658  g_assert_not_reached ();
659}
660
661static inline Emission*
662emission_find (Emission *emission_list,
663	       guint     signal_id,
664	       GQuark    detail,
665	       gpointer  instance)
666{
667  Emission *emission;
668
669  for (emission = emission_list; emission; emission = emission->next)
670    if (emission->instance == instance &&
671	emission->ihint.signal_id == signal_id &&
672	emission->ihint.detail == detail)
673      return emission;
674  return NULL;
675}
676
677static inline Emission*
678emission_find_innermost (gpointer instance)
679{
680  Emission *emission, *s = NULL, *c = NULL;
681
682  for (emission = g_restart_emissions; emission; emission = emission->next)
683    if (emission->instance == instance)
684      {
685	s = emission;
686	break;
687      }
688  for (emission = g_recursive_emissions; emission; emission = emission->next)
689    if (emission->instance == instance)
690      {
691	c = emission;
692	break;
693      }
694  if (!s)
695    return c;
696  else if (!c)
697    return s;
698  else
699    return G_HAVE_GROWING_STACK ? MAX (c, s) : MIN (c, s);
700}
701
702static gint
703signal_key_cmp (gconstpointer node1,
704                gconstpointer node2)
705{
706  const SignalKey *key1 = node1, *key2 = node2;
707
708  if (key1->itype == key2->itype)
709    return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
710  else
711    return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
712}
713
714void
715g_signal_init (void)
716{
717  SIGNAL_LOCK ();
718  if (!g_n_signal_nodes)
719    {
720      /* handler_id_node_prepend() requires this */
721      g_assert (sizeof (GList) == sizeof (HandlerMatch));
722
723      /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
724      g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
725      g_signal_key_bsa = g_bsearch_array_create (&g_signal_key_bconfig);
726
727      /* invalid (0) signal_id */
728      g_n_signal_nodes = 1;
729      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
730      g_signal_nodes[0] = NULL;
731    }
732  SIGNAL_UNLOCK ();
733}
734
735void
736_g_signals_destroy (GType itype)
737{
738  guint i;
739
740  SIGNAL_LOCK ();
741  for (i = 1; i < g_n_signal_nodes; i++)
742    {
743      SignalNode *node = g_signal_nodes[i];
744
745      if (node->itype == itype)
746        {
747          if (node->destroyed)
748            g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
749                       node->name,
750                       type_debug_name (node->itype));
751          else
752	    signal_destroy_R (node);
753        }
754    }
755  SIGNAL_UNLOCK ();
756}
757
758void
759g_signal_stop_emission (gpointer instance,
760                        guint    signal_id,
761			GQuark   detail)
762{
763  SignalNode *node;
764
765  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
766  g_return_if_fail (signal_id > 0);
767
768  SIGNAL_LOCK ();
769  node = LOOKUP_SIGNAL_NODE (signal_id);
770  if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
771    {
772      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
773      SIGNAL_UNLOCK ();
774      return;
775    }
776  if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
777    {
778      Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
779      Emission *emission = emission_find (emission_list, signal_id, detail, instance);
780
781      if (emission)
782        {
783          if (emission->state == EMISSION_HOOK)
784            g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
785                       node->name, instance);
786          else if (emission->state == EMISSION_RUN)
787            emission->state = EMISSION_STOP;
788        }
789      else
790        g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
791                   node->name, instance);
792    }
793  else
794    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
795  SIGNAL_UNLOCK ();
796}
797
798static void
799signal_finalize_hook (GHookList *hook_list,
800		      GHook     *hook)
801{
802  GDestroyNotify destroy = hook->destroy;
803
804  if (destroy)
805    {
806      hook->destroy = NULL;
807      SIGNAL_UNLOCK ();
808      destroy (hook->data);
809      SIGNAL_LOCK ();
810    }
811}
812
813gulong
814g_signal_add_emission_hook (guint               signal_id,
815			    GQuark              detail,
816			    GSignalEmissionHook hook_func,
817			    gpointer            hook_data,
818			    GDestroyNotify      data_destroy)
819{
820  static gulong seq_hook_id = 1;
821  SignalNode *node;
822  GHook *hook;
823  SignalHook *signal_hook;
824
825  g_return_val_if_fail (signal_id > 0, 0);
826  g_return_val_if_fail (hook_func != NULL, 0);
827
828  SIGNAL_LOCK ();
829  node = LOOKUP_SIGNAL_NODE (signal_id);
830  if (!node || node->destroyed)
831    {
832      g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id);
833      SIGNAL_UNLOCK ();
834      return 0;
835    }
836  if (node->flags & G_SIGNAL_NO_HOOKS)
837    {
838      g_warning ("%s: signal id `%u' does not support emission hooks (G_SIGNAL_NO_HOOKS flag set)", G_STRLOC, signal_id);
839      SIGNAL_UNLOCK ();
840      return 0;
841    }
842  if (detail && !(node->flags & G_SIGNAL_DETAILED))
843    {
844      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
845      SIGNAL_UNLOCK ();
846      return 0;
847    }
848  if (!node->emission_hooks)
849    {
850      node->emission_hooks = g_new (GHookList, 1);
851      g_hook_list_init (node->emission_hooks, sizeof (SignalHook));
852      node->emission_hooks->finalize_hook = signal_finalize_hook;
853    }
854  hook = g_hook_alloc (node->emission_hooks);
855  hook->data = hook_data;
856  hook->func = (gpointer) hook_func;
857  hook->destroy = data_destroy;
858  signal_hook = SIGNAL_HOOK (hook);
859  signal_hook->detail = detail;
860  node->emission_hooks->seq_id = seq_hook_id;
861  g_hook_append (node->emission_hooks, hook);
862  seq_hook_id = node->emission_hooks->seq_id;
863  SIGNAL_UNLOCK ();
864
865  return hook->hook_id;
866}
867
868void
869g_signal_remove_emission_hook (guint  signal_id,
870			       gulong hook_id)
871{
872  SignalNode *node;
873
874  g_return_if_fail (signal_id > 0);
875  g_return_if_fail (hook_id > 0);
876
877  SIGNAL_LOCK ();
878  node = LOOKUP_SIGNAL_NODE (signal_id);
879  if (!node || node->destroyed)
880    g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id);
881  else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id))
882    g_warning ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id);
883  SIGNAL_UNLOCK ();
884}
885
886static inline guint
887signal_parse_name (const gchar *name,
888		   GType        itype,
889		   GQuark      *detail_p,
890		   gboolean     force_quark)
891{
892  const gchar *colon = strchr (name, ':');
893  guint signal_id;
894
895  if (!colon)
896    {
897      signal_id = signal_id_lookup (g_quark_try_string (name), itype);
898      if (signal_id && detail_p)
899	*detail_p = 0;
900    }
901  else if (colon[1] == ':')
902    {
903      gchar buffer[32];
904      guint l = colon - name;
905
906      if (l < 32)
907	{
908	  memcpy (buffer, name, l);
909	  buffer[l] = 0;
910	  signal_id = signal_id_lookup (g_quark_try_string (buffer), itype);
911	}
912      else
913	{
914	  gchar *signal = g_new (gchar, l + 1);
915
916	  memcpy (signal, name, l);
917	  signal[l] = 0;
918	  signal_id = signal_id_lookup (g_quark_try_string (signal), itype);
919	  g_free (signal);
920	}
921
922      if (signal_id && detail_p)
923	*detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0;
924    }
925  else
926    signal_id = 0;
927  return signal_id;
928}
929
930gboolean
931g_signal_parse_name (const gchar *detailed_signal,
932		     GType        itype,
933		     guint       *signal_id_p,
934		     GQuark      *detail_p,
935		     gboolean	  force_detail_quark)
936{
937  SignalNode *node;
938  GQuark detail = 0;
939  guint signal_id;
940
941  g_return_val_if_fail (detailed_signal != NULL, FALSE);
942  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
943
944  SIGNAL_LOCK ();
945  signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
946  SIGNAL_UNLOCK ();
947
948  node = signal_id ? LOOKUP_SIGNAL_NODE (signal_id) : NULL;
949  if (!node || node->destroyed ||
950      (detail && !(node->flags & G_SIGNAL_DETAILED)))
951    return FALSE;
952
953  if (signal_id_p)
954    *signal_id_p = signal_id;
955  if (detail_p)
956    *detail_p = detail;
957
958  return TRUE;
959}
960
961void
962g_signal_stop_emission_by_name (gpointer     instance,
963				const gchar *detailed_signal)
964{
965  guint signal_id;
966  GQuark detail = 0;
967  GType itype;
968
969  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
970  g_return_if_fail (detailed_signal != NULL);
971
972  SIGNAL_LOCK ();
973  itype = G_TYPE_FROM_INSTANCE (instance);
974  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
975  if (signal_id)
976    {
977      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
978
979      if (detail && !(node->flags & G_SIGNAL_DETAILED))
980	g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
981      else if (!g_type_is_a (itype, node->itype))
982	g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
983      else
984	{
985	  Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
986	  Emission *emission = emission_find (emission_list, signal_id, detail, instance);
987
988	  if (emission)
989	    {
990	      if (emission->state == EMISSION_HOOK)
991		g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
992			   node->name, instance);
993	      else if (emission->state == EMISSION_RUN)
994		emission->state = EMISSION_STOP;
995	    }
996	  else
997	    g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
998		       node->name, instance);
999	}
1000    }
1001  else
1002    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1003  SIGNAL_UNLOCK ();
1004}
1005
1006guint
1007g_signal_lookup (const gchar *name,
1008                 GType        itype)
1009{
1010  guint signal_id;
1011  g_return_val_if_fail (name != NULL, 0);
1012  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
1013
1014  SIGNAL_LOCK ();
1015  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
1016  SIGNAL_UNLOCK ();
1017  if (!signal_id)
1018    {
1019      /* give elaborate warnings */
1020      if (!g_type_name (itype))
1021	g_warning (G_STRLOC ": unable to lookup signal \"%s\" for invalid type id `%lu'",
1022		   name, itype);
1023      else if (!G_TYPE_IS_INSTANTIATABLE (itype))
1024	g_warning (G_STRLOC ": unable to lookup signal \"%s\" for non instantiatable type `%s'",
1025		   name, g_type_name (itype));
1026      else if (!g_type_class_peek (itype))
1027	g_warning (G_STRLOC ": unable to lookup signal \"%s\" of unloaded type `%s'",
1028		   name, g_type_name (itype));
1029    }
1030
1031  return signal_id;
1032}
1033
1034guint*
1035g_signal_list_ids (GType  itype,
1036		   guint *n_ids)
1037{
1038  SignalKey *keys;
1039  GArray *result;
1040  guint n_nodes;
1041  guint i;
1042
1043  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
1044  g_return_val_if_fail (n_ids != NULL, NULL);
1045
1046  SIGNAL_LOCK ();
1047  keys = g_bsearch_array_get_nth (g_signal_key_bsa, &g_signal_key_bconfig, 0);
1048  n_nodes = g_bsearch_array_get_n_nodes (g_signal_key_bsa);
1049  result = g_array_new (FALSE, FALSE, sizeof (guint));
1050
1051  for (i = 0; i < n_nodes; i++)
1052    if (keys[i].itype == itype)
1053      {
1054	const gchar *name = g_quark_to_string (keys[i].quark);
1055
1056	/* Signal names with "_" in them are aliases to the same
1057	 * name with "-" instead of "_".
1058	 */
1059	if (!strchr (name, '_'))
1060	  g_array_append_val (result, keys[i].signal_id);
1061      }
1062  *n_ids = result->len;
1063  SIGNAL_UNLOCK ();
1064  if (!n_nodes)
1065    {
1066      /* give elaborate warnings */
1067      if (!g_type_name (itype))
1068	g_warning (G_STRLOC ": unable to list signals for invalid type id `%lu'",
1069		   itype);
1070      else if (!G_TYPE_IS_INSTANTIATABLE (itype))
1071	g_warning (G_STRLOC ": unable to list signals of non instantiatable type `%s'",
1072		   g_type_name (itype));
1073      else if (!g_type_class_peek (itype))
1074	g_warning (G_STRLOC ": unable to list signals of unloaded type `%s'",
1075		   g_type_name (itype));
1076    }
1077
1078  return (guint*) g_array_free (result, FALSE);
1079}
1080
1081G_CONST_RETURN gchar*
1082g_signal_name (guint signal_id)
1083{
1084  SignalNode *node;
1085  const gchar *name;
1086
1087  SIGNAL_LOCK ();
1088  node = LOOKUP_SIGNAL_NODE (signal_id);
1089  name = node ? node->name : NULL;
1090  SIGNAL_UNLOCK ();
1091
1092  return (char*) name;
1093}
1094
1095void
1096g_signal_query (guint         signal_id,
1097		GSignalQuery *query)
1098{
1099  SignalNode *node;
1100
1101  g_return_if_fail (query != NULL);
1102
1103  SIGNAL_LOCK ();
1104  node = LOOKUP_SIGNAL_NODE (signal_id);
1105  if (!node || node->destroyed)
1106    query->signal_id = 0;
1107  else
1108    {
1109      query->signal_id = node->signal_id;
1110      query->signal_name = node->name;
1111      query->itype = node->itype;
1112      query->signal_flags = node->flags;
1113      query->return_type = node->return_type;
1114      query->n_params = node->n_params;
1115      query->param_types = node->param_types;
1116    }
1117  SIGNAL_UNLOCK ();
1118}
1119
1120guint
1121g_signal_new (const gchar	 *signal_name,
1122	      GType		  itype,
1123	      GSignalFlags	  signal_flags,
1124	      guint               class_offset,
1125	      GSignalAccumulator  accumulator,
1126	      gpointer		  accu_data,
1127	      GSignalCMarshaller  c_marshaller,
1128	      GType		  return_type,
1129	      guint		  n_params,
1130	      ...)
1131{
1132  va_list args;
1133  guint signal_id;
1134
1135  g_return_val_if_fail (signal_name != NULL, 0);
1136
1137  va_start (args, n_params);
1138
1139  signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
1140                                   class_offset ? g_signal_type_cclosure_new (itype, class_offset) : NULL,
1141				   accumulator, accu_data, c_marshaller,
1142                                   return_type, n_params, args);
1143
1144  va_end (args);
1145
1146  /* optimize NOP emissions with NULL class handlers */
1147  if (signal_id && G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE &&
1148      class_offset && class_offset < MAX_TEST_CLASS_OFFSET)
1149    {
1150      SignalNode *node;
1151
1152      SIGNAL_LOCK ();
1153      node = LOOKUP_SIGNAL_NODE (signal_id);
1154      node->test_class_offset = class_offset;
1155      SIGNAL_UNLOCK ();
1156    }
1157
1158  return signal_id;
1159}
1160
1161static inline ClassClosure*
1162signal_find_class_closure (SignalNode *node,
1163			   GType       itype)
1164{
1165  GBSearchArray *bsa = node->class_closure_bsa;
1166  ClassClosure *cc;
1167
1168  if (bsa)
1169    {
1170      ClassClosure key;
1171
1172      /* cc->instance_type is 0 for default closure */
1173
1174      key.instance_type = itype;
1175      cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key);
1176      while (!cc && key.instance_type)
1177	{
1178	  key.instance_type = g_type_parent (key.instance_type);
1179	  cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key);
1180	}
1181    }
1182  else
1183    cc = NULL;
1184  return cc;
1185}
1186
1187static inline GClosure*
1188signal_lookup_closure (SignalNode    *node,
1189		       GTypeInstance *instance)
1190{
1191  ClassClosure *cc;
1192
1193  if (node->class_closure_bsa && g_bsearch_array_get_n_nodes (node->class_closure_bsa) == 1)
1194    cc = g_bsearch_array_get_nth (node->class_closure_bsa, &g_class_closure_bconfig, 0);
1195  else
1196    cc = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance));
1197  return cc ? cc->closure : NULL;
1198}
1199
1200static void
1201signal_add_class_closure (SignalNode *node,
1202			  GType       itype,
1203			  GClosure   *closure)
1204{
1205  ClassClosure key;
1206
1207  /* can't optimize NOP emissions with overridden class closures */
1208  node->test_class_offset = 0;
1209
1210  if (!node->class_closure_bsa)
1211    node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig);
1212  key.instance_type = itype;
1213  key.closure = g_closure_ref (closure);
1214  node->class_closure_bsa = g_bsearch_array_insert (node->class_closure_bsa,
1215						    &g_class_closure_bconfig,
1216						    &key);
1217  g_closure_sink (closure);
1218  if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (closure))
1219    g_closure_set_marshal (closure, node->c_marshaller);
1220}
1221
1222guint
1223g_signal_newv (const gchar       *signal_name,
1224               GType              itype,
1225               GSignalFlags       signal_flags,
1226               GClosure          *class_closure,
1227               GSignalAccumulator accumulator,
1228	       gpointer		  accu_data,
1229               GSignalCMarshaller c_marshaller,
1230               GType		  return_type,
1231               guint              n_params,
1232               GType		 *param_types)
1233{
1234  gchar *name;
1235  guint signal_id, i;
1236  SignalNode *node;
1237
1238  g_return_val_if_fail (signal_name != NULL, 0);
1239  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
1240  if (n_params)
1241    g_return_val_if_fail (param_types != NULL, 0);
1242  g_return_val_if_fail ((return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == 0, 0);
1243  if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1244    g_return_val_if_fail (accumulator == NULL, 0);
1245  if (!accumulator)
1246    g_return_val_if_fail (accu_data == NULL, 0);
1247
1248  name = g_strdup (signal_name);
1249  g_strdelimit (name, G_STR_DELIMITERS ":^", '_');  /* FIXME do character checks like for types */
1250
1251  SIGNAL_LOCK ();
1252
1253  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
1254  node = LOOKUP_SIGNAL_NODE (signal_id);
1255  if (node && !node->destroyed)
1256    {
1257      g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
1258                 name,
1259                 type_debug_name (node->itype),
1260                 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
1261      g_free (name);
1262      SIGNAL_UNLOCK ();
1263      return 0;
1264    }
1265  if (node && node->itype != itype)
1266    {
1267      g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
1268                 name,
1269                 type_debug_name (itype),
1270                 type_debug_name (node->itype));
1271      g_free (name);
1272      SIGNAL_UNLOCK ();
1273      return 0;
1274    }
1275  for (i = 0; i < n_params; i++)
1276    if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1277      {
1278	g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
1279		   i + 1, type_debug_name (param_types[i]), type_debug_name (itype), name);
1280	g_free (name);
1281	SIGNAL_UNLOCK ();
1282	return 0;
1283      }
1284  if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1285    {
1286      g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
1287		 type_debug_name (return_type), type_debug_name (itype), name);
1288      g_free (name);
1289      SIGNAL_UNLOCK ();
1290      return 0;
1291    }
1292  if (return_type != G_TYPE_NONE &&
1293      (signal_flags & (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP)) == G_SIGNAL_RUN_FIRST)
1294    {
1295      g_warning (G_STRLOC ": signal \"%s::%s\" has return type `%s' and is only G_SIGNAL_RUN_FIRST",
1296		 type_debug_name (itype), name, type_debug_name (return_type));
1297      g_free (name);
1298      SIGNAL_UNLOCK ();
1299      return 0;
1300    }
1301
1302  /* setup permanent portion of signal node */
1303  if (!node)
1304    {
1305      SignalKey key;
1306
1307      signal_id = g_n_signal_nodes++;
1308      node = g_new (SignalNode, 1);
1309      node->signal_id = signal_id;
1310      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
1311      g_signal_nodes[signal_id] = node;
1312      node->itype = itype;
1313      node->name = name;
1314      key.itype = itype;
1315      key.quark = g_quark_from_string (node->name);
1316      key.signal_id = signal_id;
1317      g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key);
1318      g_strdelimit (name, "_", '-');
1319      node->name = g_intern_string (name);
1320      key.quark = g_quark_from_string (name);
1321      g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key);
1322    }
1323  node->destroyed = FALSE;
1324  node->test_class_offset = 0;
1325
1326  /* setup reinitializable portion */
1327  node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
1328  node->n_params = n_params;
1329  node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
1330  node->return_type = return_type;
1331  node->class_closure_bsa = NULL;
1332  if (accumulator)
1333    {
1334      node->accumulator = g_new (SignalAccumulator, 1);
1335      node->accumulator->func = accumulator;
1336      node->accumulator->data = accu_data;
1337    }
1338  else
1339    node->accumulator = NULL;
1340  node->c_marshaller = c_marshaller;
1341  node->emission_hooks = NULL;
1342  if (class_closure)
1343    signal_add_class_closure (node, 0, class_closure);
1344  else if (G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE)
1345    {
1346      /* optimize NOP emissions */
1347      node->test_class_offset = TEST_CLASS_MAGIC;
1348    }
1349  SIGNAL_UNLOCK ();
1350
1351  g_free (name);
1352
1353  return signal_id;
1354}
1355
1356guint
1357g_signal_new_valist (const gchar       *signal_name,
1358                     GType              itype,
1359                     GSignalFlags       signal_flags,
1360                     GClosure          *class_closure,
1361                     GSignalAccumulator accumulator,
1362		     gpointer		accu_data,
1363                     GSignalCMarshaller c_marshaller,
1364                     GType              return_type,
1365                     guint              n_params,
1366                     va_list            args)
1367{
1368  GType *param_types;
1369  guint i;
1370  guint signal_id;
1371
1372  if (n_params > 0)
1373    {
1374      param_types = g_new (GType, n_params);
1375
1376      for (i = 0; i < n_params; i++)
1377	param_types[i] = va_arg (args, GType);
1378    }
1379  else
1380    param_types = NULL;
1381
1382  signal_id = g_signal_newv (signal_name, itype, signal_flags,
1383			     class_closure, accumulator, accu_data, c_marshaller,
1384			     return_type, n_params, param_types);
1385  g_free (param_types);
1386
1387  return signal_id;
1388}
1389
1390static void
1391signal_destroy_R (SignalNode *signal_node)
1392{
1393  SignalNode node = *signal_node;
1394
1395  signal_node->destroyed = TRUE;
1396
1397  /* reentrancy caution, zero out real contents first */
1398  signal_node->test_class_offset = 0;
1399  signal_node->n_params = 0;
1400  signal_node->param_types = NULL;
1401  signal_node->return_type = 0;
1402  signal_node->class_closure_bsa = NULL;
1403  signal_node->accumulator = NULL;
1404  signal_node->c_marshaller = NULL;
1405  signal_node->emission_hooks = NULL;
1406
1407#ifdef	G_ENABLE_DEBUG
1408  /* check current emissions */
1409  {
1410    Emission *emission;
1411
1412    for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
1413         emission; emission = emission->next)
1414      if (emission->ihint.signal_id == node.signal_id)
1415        g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
1416                    node.name, emission->instance);
1417  }
1418#endif
1419
1420  /* free contents that need to
1421   */
1422  SIGNAL_UNLOCK ();
1423  g_free (node.param_types);
1424  if (node.class_closure_bsa)
1425    {
1426      guint i;
1427
1428      for (i = 0; i < node.class_closure_bsa->n_nodes; i++)
1429	{
1430	  ClassClosure *cc = g_bsearch_array_get_nth (node.class_closure_bsa, &g_class_closure_bconfig, i);
1431
1432	  g_closure_unref (cc->closure);
1433	}
1434      g_bsearch_array_free (node.class_closure_bsa, &g_class_closure_bconfig);
1435    }
1436  g_free (node.accumulator);
1437  if (node.emission_hooks)
1438    {
1439      g_hook_list_clear (node.emission_hooks);
1440      g_free (node.emission_hooks);
1441    }
1442  SIGNAL_LOCK ();
1443}
1444
1445void
1446g_signal_override_class_closure (guint     signal_id,
1447				 GType     instance_type,
1448				 GClosure *class_closure)
1449{
1450  SignalNode *node;
1451
1452  g_return_if_fail (signal_id > 0);
1453  g_return_if_fail (class_closure != NULL);
1454
1455  SIGNAL_LOCK ();
1456  node = LOOKUP_SIGNAL_NODE (signal_id);
1457  if (!g_type_is_a (instance_type, node->itype))
1458    g_warning ("%s: type `%s' cannot be overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id);
1459  else
1460    {
1461      ClassClosure *cc = signal_find_class_closure (node, instance_type);
1462
1463      if (cc && cc->instance_type == instance_type)
1464	g_warning ("%s: type `%s' is already overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id);
1465      else
1466	signal_add_class_closure (node, instance_type, class_closure);
1467    }
1468  SIGNAL_UNLOCK ();
1469}
1470
1471void
1472g_signal_chain_from_overridden (const GValue *instance_and_params,
1473				GValue       *return_value)
1474{
1475  GType chain_type = 0, restore_type = 0;
1476  Emission *emission = NULL;
1477  GClosure *closure = NULL;
1478  guint n_params = 0;
1479  gpointer instance;
1480
1481  g_return_if_fail (instance_and_params != NULL);
1482  instance = g_value_peek_pointer (instance_and_params);
1483  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1484
1485  SIGNAL_LOCK ();
1486  emission = emission_find_innermost (instance);
1487  if (emission)
1488    {
1489      SignalNode *node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id);
1490
1491      g_assert (node != NULL);	/* paranoid */
1492
1493      /* we should probably do the same parameter checks as g_signal_emit() here.
1494       */
1495      if (emission->chain_type != G_TYPE_NONE)
1496	{
1497	  ClassClosure *cc = signal_find_class_closure (node, emission->chain_type);
1498
1499	  g_assert (cc != NULL);	/* closure currently in call stack */
1500
1501	  n_params = node->n_params;
1502	  restore_type = cc->instance_type;
1503	  cc = signal_find_class_closure (node, g_type_parent (cc->instance_type));
1504	  if (cc && cc->instance_type != restore_type)
1505	    {
1506	      closure = cc->closure;
1507	      chain_type = cc->instance_type;
1508	    }
1509	}
1510      else
1511	g_warning ("%s: signal id `%u' cannot be chained from current emission stage for instance `%p'", G_STRLOC, node->signal_id, instance);
1512    }
1513  else
1514    g_warning ("%s: no signal is currently being emitted for instance `%p'", G_STRLOC, instance);
1515  if (closure)
1516    {
1517      emission->chain_type = chain_type;
1518      SIGNAL_UNLOCK ();
1519      g_closure_invoke (closure,
1520			return_value,
1521			n_params + 1,
1522			instance_and_params,
1523			&emission->ihint);
1524      SIGNAL_LOCK ();
1525      emission->chain_type = restore_type;
1526    }
1527  SIGNAL_UNLOCK ();
1528}
1529
1530GSignalInvocationHint*
1531g_signal_get_invocation_hint (gpointer instance)
1532{
1533  Emission *emission = NULL;
1534
1535  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), NULL);
1536
1537  SIGNAL_LOCK ();
1538  emission = emission_find_innermost (instance);
1539  SIGNAL_UNLOCK ();
1540
1541  return emission ? &emission->ihint : NULL;
1542}
1543
1544gulong
1545g_signal_connect_closure_by_id (gpointer  instance,
1546				guint     signal_id,
1547				GQuark    detail,
1548				GClosure *closure,
1549				gboolean  after)
1550{
1551  SignalNode *node;
1552  gulong handler_seq_no = 0;
1553
1554  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1555  g_return_val_if_fail (signal_id > 0, 0);
1556  g_return_val_if_fail (closure != NULL, 0);
1557
1558  SIGNAL_LOCK ();
1559  node = LOOKUP_SIGNAL_NODE (signal_id);
1560  if (node)
1561    {
1562      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1563	g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1564      else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1565	g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1566      else
1567	{
1568	  Handler *handler = handler_new (after);
1569
1570	  handler_seq_no = handler->sequential_number;
1571	  handler->detail = detail;
1572	  handler->closure = g_closure_ref (closure);
1573	  g_closure_sink (closure);
1574	  handler_insert (signal_id, instance, handler);
1575	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
1576	    g_closure_set_marshal (closure, node->c_marshaller);
1577	}
1578    }
1579  else
1580    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1581  SIGNAL_UNLOCK ();
1582
1583  return handler_seq_no;
1584}
1585
1586gulong
1587g_signal_connect_closure (gpointer     instance,
1588			  const gchar *detailed_signal,
1589			  GClosure    *closure,
1590			  gboolean     after)
1591{
1592  guint signal_id;
1593  gulong handler_seq_no = 0;
1594  GQuark detail = 0;
1595  GType itype;
1596
1597  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1598  g_return_val_if_fail (detailed_signal != NULL, 0);
1599  g_return_val_if_fail (closure != NULL, 0);
1600
1601  SIGNAL_LOCK ();
1602  itype = G_TYPE_FROM_INSTANCE (instance);
1603  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1604  if (signal_id)
1605    {
1606      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1607
1608      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1609	g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1610      else if (!g_type_is_a (itype, node->itype))
1611	g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1612      else
1613	{
1614	  Handler *handler = handler_new (after);
1615
1616	  handler_seq_no = handler->sequential_number;
1617	  handler->detail = detail;
1618	  handler->closure = g_closure_ref (closure);
1619	  g_closure_sink (closure);
1620	  handler_insert (signal_id, instance, handler);
1621	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1622	    g_closure_set_marshal (handler->closure, node->c_marshaller);
1623	}
1624    }
1625  else
1626    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1627  SIGNAL_UNLOCK ();
1628
1629  return handler_seq_no;
1630}
1631
1632gulong
1633g_signal_connect_data (gpointer       instance,
1634		       const gchar   *detailed_signal,
1635		       GCallback      c_handler,
1636		       gpointer       data,
1637		       GClosureNotify destroy_data,
1638		       GConnectFlags  connect_flags)
1639{
1640  guint signal_id;
1641  gulong handler_seq_no = 0;
1642  GQuark detail = 0;
1643  GType itype;
1644  gboolean swapped, after;
1645
1646  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1647  g_return_val_if_fail (detailed_signal != NULL, 0);
1648  g_return_val_if_fail (c_handler != NULL, 0);
1649
1650  swapped = (connect_flags & G_CONNECT_SWAPPED) != FALSE;
1651  after = (connect_flags & G_CONNECT_AFTER) != FALSE;
1652
1653  SIGNAL_LOCK ();
1654  itype = G_TYPE_FROM_INSTANCE (instance);
1655  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1656  if (signal_id)
1657    {
1658      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1659
1660      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1661	g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1662      else if (!g_type_is_a (itype, node->itype))
1663	g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1664      else
1665	{
1666	  Handler *handler = handler_new (after);
1667
1668	  handler_seq_no = handler->sequential_number;
1669	  handler->detail = detail;
1670	  handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
1671	  g_closure_sink (handler->closure);
1672	  handler_insert (signal_id, instance, handler);
1673	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1674	    g_closure_set_marshal (handler->closure, node->c_marshaller);
1675	}
1676    }
1677  else
1678    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1679  SIGNAL_UNLOCK ();
1680
1681  return handler_seq_no;
1682}
1683
1684void
1685g_signal_handler_block (gpointer instance,
1686                        gulong   handler_id)
1687{
1688  Handler *handler;
1689
1690  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1691  g_return_if_fail (handler_id > 0);
1692
1693  SIGNAL_LOCK ();
1694  handler = handler_lookup (instance, handler_id, NULL);
1695  if (handler)
1696    {
1697#ifndef G_DISABLE_CHECKS
1698      if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
1699        g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
1700#endif
1701      handler->block_count += 1;
1702    }
1703  else
1704    g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id);
1705  SIGNAL_UNLOCK ();
1706}
1707
1708void
1709g_signal_handler_unblock (gpointer instance,
1710                          gulong   handler_id)
1711{
1712  Handler *handler;
1713
1714  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1715  g_return_if_fail (handler_id > 0);
1716
1717  SIGNAL_LOCK ();
1718  handler = handler_lookup (instance, handler_id, NULL);
1719  if (handler)
1720    {
1721      if (handler->block_count)
1722        handler->block_count -= 1;
1723      else
1724        g_warning (G_STRLOC ": handler `%lu' of instance `%p' is not blocked", handler_id, instance);
1725    }
1726  else
1727    g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id);
1728  SIGNAL_UNLOCK ();
1729}
1730
1731void
1732g_signal_handler_disconnect (gpointer instance,
1733                             gulong   handler_id)
1734{
1735  Handler *handler;
1736  guint signal_id;
1737
1738  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1739  g_return_if_fail (handler_id > 0);
1740
1741  SIGNAL_LOCK ();
1742  handler = handler_lookup (instance, handler_id, &signal_id);
1743  if (handler)
1744    {
1745      handler->sequential_number = 0;
1746      handler->block_count = 1;
1747      handler_unref_R (signal_id, instance, handler);
1748    }
1749  else
1750    g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id);
1751  SIGNAL_UNLOCK ();
1752}
1753
1754gboolean
1755g_signal_handler_is_connected (gpointer instance,
1756			       gulong   handler_id)
1757{
1758  Handler *handler;
1759  gboolean connected;
1760
1761  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1762
1763  SIGNAL_LOCK ();
1764  handler = handler_lookup (instance, handler_id, NULL);
1765  connected = handler != NULL;
1766  SIGNAL_UNLOCK ();
1767
1768  return connected;
1769}
1770
1771void
1772g_signal_handlers_destroy (gpointer instance)
1773{
1774  GBSearchArray *hlbsa;
1775
1776  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1777
1778  SIGNAL_LOCK ();
1779  hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
1780  if (hlbsa)
1781    {
1782      guint i;
1783
1784      /* reentrancy caution, delete instance trace first */
1785      g_hash_table_remove (g_handler_list_bsa_ht, instance);
1786
1787      for (i = 0; i < hlbsa->n_nodes; i++)
1788        {
1789          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
1790          Handler *handler = hlist->handlers;
1791
1792          while (handler)
1793            {
1794              Handler *tmp = handler;
1795
1796              handler = tmp->next;
1797              tmp->block_count = 1;
1798              /* cruel unlink, this works because _all_ handlers vanish */
1799              tmp->next = NULL;
1800              tmp->prev = tmp;
1801              if (tmp->sequential_number)
1802		{
1803		  tmp->sequential_number = 0;
1804		  handler_unref_R (0, NULL, tmp);
1805		}
1806            }
1807        }
1808      g_bsearch_array_free (hlbsa, &g_signal_hlbsa_bconfig);
1809    }
1810  SIGNAL_UNLOCK ();
1811}
1812
1813gulong
1814g_signal_handler_find (gpointer         instance,
1815                       GSignalMatchType mask,
1816                       guint            signal_id,
1817		       GQuark		detail,
1818                       GClosure        *closure,
1819                       gpointer         func,
1820                       gpointer         data)
1821{
1822  gulong handler_seq_no = 0;
1823
1824  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1825  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1826
1827  if (mask & G_SIGNAL_MATCH_MASK)
1828    {
1829      HandlerMatch *mlist;
1830
1831      SIGNAL_LOCK ();
1832      mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
1833      if (mlist)
1834	{
1835	  handler_seq_no = mlist->handler->sequential_number;
1836	  handler_match_free1_R (mlist, instance);
1837	}
1838      SIGNAL_UNLOCK ();
1839    }
1840
1841  return handler_seq_no;
1842}
1843
1844static guint
1845signal_handlers_foreach_matched_R (gpointer         instance,
1846				   GSignalMatchType mask,
1847				   guint            signal_id,
1848				   GQuark           detail,
1849				   GClosure        *closure,
1850				   gpointer         func,
1851				   gpointer         data,
1852				   void		  (*callback) (gpointer instance,
1853							       gulong   handler_seq_no))
1854{
1855  HandlerMatch *mlist;
1856  guint n_handlers = 0;
1857
1858  mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
1859  while (mlist)
1860    {
1861      n_handlers++;
1862      if (mlist->handler->sequential_number)
1863	{
1864	  SIGNAL_UNLOCK ();
1865	  callback (instance, mlist->handler->sequential_number);
1866	  SIGNAL_LOCK ();
1867	}
1868      mlist = handler_match_free1_R (mlist, instance);
1869    }
1870
1871  return n_handlers;
1872}
1873
1874guint
1875g_signal_handlers_block_matched (gpointer         instance,
1876				 GSignalMatchType mask,
1877				 guint            signal_id,
1878				 GQuark           detail,
1879				 GClosure        *closure,
1880				 gpointer         func,
1881				 gpointer         data)
1882{
1883  guint n_handlers = 0;
1884
1885  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1886  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1887
1888  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1889    {
1890      SIGNAL_LOCK ();
1891      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1892						      closure, func, data,
1893						      g_signal_handler_block);
1894      SIGNAL_UNLOCK ();
1895    }
1896
1897  return n_handlers;
1898}
1899
1900guint
1901g_signal_handlers_unblock_matched (gpointer         instance,
1902				   GSignalMatchType mask,
1903				   guint            signal_id,
1904				   GQuark           detail,
1905				   GClosure        *closure,
1906				   gpointer         func,
1907				   gpointer         data)
1908{
1909  guint n_handlers = 0;
1910
1911  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1912  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1913
1914  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1915    {
1916      SIGNAL_LOCK ();
1917      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1918						      closure, func, data,
1919						      g_signal_handler_unblock);
1920      SIGNAL_UNLOCK ();
1921    }
1922
1923  return n_handlers;
1924}
1925
1926guint
1927g_signal_handlers_disconnect_matched (gpointer         instance,
1928				      GSignalMatchType mask,
1929				      guint            signal_id,
1930				      GQuark           detail,
1931				      GClosure        *closure,
1932				      gpointer         func,
1933				      gpointer         data)
1934{
1935  guint n_handlers = 0;
1936
1937  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1938  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1939
1940  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1941    {
1942      SIGNAL_LOCK ();
1943      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1944						      closure, func, data,
1945						      g_signal_handler_disconnect);
1946      SIGNAL_UNLOCK ();
1947    }
1948
1949  return n_handlers;
1950}
1951
1952gboolean
1953g_signal_has_handler_pending (gpointer instance,
1954			      guint    signal_id,
1955			      GQuark   detail,
1956			      gboolean may_be_blocked)
1957{
1958  HandlerMatch *mlist;
1959  gboolean has_pending;
1960
1961  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1962  g_return_val_if_fail (signal_id > 0, FALSE);
1963
1964  SIGNAL_LOCK ();
1965  if (detail)
1966    {
1967      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1968
1969      if (!(node->flags & G_SIGNAL_DETAILED))
1970	{
1971	  g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1972	  SIGNAL_UNLOCK ();
1973	  return FALSE;
1974	}
1975    }
1976  mlist = handlers_find (instance,
1977			 (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
1978			 signal_id, detail, NULL, NULL, NULL, TRUE);
1979  if (mlist)
1980    {
1981      has_pending = TRUE;
1982      handler_match_free1_R (mlist, instance);
1983    }
1984  else
1985    has_pending = FALSE;
1986  SIGNAL_UNLOCK ();
1987
1988  return has_pending;
1989}
1990
1991static inline gboolean
1992signal_check_skip_emission (SignalNode *node,
1993			    gpointer    instance,
1994			    GQuark      detail)
1995{
1996  HandlerList *hlist;
1997
1998  /* are we able to check for NULL class handlers? */
1999  if (!node->test_class_offset)
2000    return FALSE;
2001
2002  /* are there emission hooks pending? */
2003  if (node->emission_hooks && node->emission_hooks->hooks)
2004    return FALSE;
2005
2006  /* is there a non-NULL class handler? */
2007  if (node->test_class_offset != TEST_CLASS_MAGIC)
2008    {
2009      GTypeClass *class = G_TYPE_INSTANCE_GET_CLASS (instance, G_TYPE_FROM_INSTANCE (instance), GTypeClass);
2010
2011      if (G_STRUCT_MEMBER (gpointer, class, node->test_class_offset))
2012	return FALSE;
2013    }
2014
2015  /* are signals being debugged? */
2016#ifdef  G_ENABLE_DEBUG
2017  IF_DEBUG (SIGNALS, g_trace_instance_signals || g_trap_instance_signals)
2018    return FALSE;
2019#endif /* G_ENABLE_DEBUG */
2020
2021  /* is this a no-recurse signal already in emission? */
2022  if (node->flags & G_SIGNAL_NO_RECURSE &&
2023      emission_find (g_restart_emissions, node->signal_id, detail, instance))
2024    return FALSE;
2025
2026  /* do we have pending handlers? */
2027  hlist = handler_list_lookup (node->signal_id, instance);
2028  if (hlist && hlist->handlers)
2029    return FALSE;
2030
2031  /* none of the above, no emission required */
2032  return TRUE;
2033}
2034
2035void
2036g_signal_emitv (const GValue *instance_and_params,
2037		guint         signal_id,
2038		GQuark	      detail,
2039		GValue       *return_value)
2040{
2041  gpointer instance;
2042  SignalNode *node;
2043#ifdef G_ENABLE_DEBUG
2044  const GValue *param_values;
2045  guint i;
2046#endif
2047
2048  g_return_if_fail (instance_and_params != NULL);
2049  instance = g_value_peek_pointer (instance_and_params);
2050  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2051  g_return_if_fail (signal_id > 0);
2052
2053#ifdef G_ENABLE_DEBUG
2054  param_values = instance_and_params + 1;
2055#endif
2056
2057  SIGNAL_LOCK ();
2058  node = LOOKUP_SIGNAL_NODE (signal_id);
2059  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
2060    {
2061      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
2062      SIGNAL_UNLOCK ();
2063      return;
2064    }
2065#ifdef G_ENABLE_DEBUG
2066  if (detail && !(node->flags & G_SIGNAL_DETAILED))
2067    {
2068      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
2069      SIGNAL_UNLOCK ();
2070      return;
2071    }
2072  for (i = 0; i < node->n_params; i++)
2073    if (!G_TYPE_CHECK_VALUE_TYPE (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
2074      {
2075	g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'",
2076		    G_STRLOC,
2077		    type_debug_name (node->param_types[i]),
2078		    i,
2079		    node->name,
2080		    G_VALUE_TYPE_NAME (param_values + i));
2081	SIGNAL_UNLOCK ();
2082	return;
2083      }
2084  if (node->return_type != G_TYPE_NONE)
2085    {
2086      if (!return_value)
2087	{
2088	  g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)",
2089		      G_STRLOC,
2090		      type_debug_name (node->return_type),
2091		      node->name);
2092	  SIGNAL_UNLOCK ();
2093	  return;
2094	}
2095      else if (!node->accumulator && !G_TYPE_CHECK_VALUE_TYPE (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
2096	{
2097	  g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'",
2098		      G_STRLOC,
2099		      type_debug_name (node->return_type),
2100		      node->name,
2101		      G_VALUE_TYPE_NAME (return_value));
2102	  SIGNAL_UNLOCK ();
2103	  return;
2104	}
2105    }
2106  else
2107    return_value = NULL;
2108#endif	/* G_ENABLE_DEBUG */
2109
2110  /* optimize NOP emissions */
2111  if (signal_check_skip_emission (node, instance, detail))
2112    {
2113      /* nothing to do to emit this signal */
2114      SIGNAL_UNLOCK ();
2115      /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
2116      return;
2117    }
2118
2119  SIGNAL_UNLOCK ();
2120  signal_emit_unlocked_R (node, detail, instance, return_value, instance_and_params);
2121}
2122
2123void
2124g_signal_emit_valist (gpointer instance,
2125		      guint    signal_id,
2126		      GQuark   detail,
2127		      va_list  var_args)
2128{
2129  GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL;
2130  GType signal_return_type;
2131  GValue *param_values;
2132  SignalNode *node;
2133  guint i, n_params;
2134
2135  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2136  g_return_if_fail (signal_id > 0);
2137
2138  SIGNAL_LOCK ();
2139  node = LOOKUP_SIGNAL_NODE (signal_id);
2140  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
2141    {
2142      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
2143      SIGNAL_UNLOCK ();
2144      return;
2145    }
2146#ifndef G_DISABLE_CHECKS
2147  if (detail && !(node->flags & G_SIGNAL_DETAILED))
2148    {
2149      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
2150      SIGNAL_UNLOCK ();
2151      return;
2152    }
2153#endif  /* !G_DISABLE_CHECKS */
2154
2155  /* optimize NOP emissions */
2156  if (signal_check_skip_emission (node, instance, detail))
2157    {
2158      /* nothing to do to emit this signal */
2159      SIGNAL_UNLOCK ();
2160      /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
2161      return;
2162    }
2163
2164  n_params = node->n_params;
2165  signal_return_type = node->return_type;
2166  if (node->n_params < MAX_STACK_VALUES)
2167    instance_and_params = stack_values;
2168  else
2169    {
2170      free_me = g_new (GValue, node->n_params + 1);
2171      instance_and_params = free_me;
2172    }
2173  param_values = instance_and_params + 1;
2174  for (i = 0; i < node->n_params; i++)
2175    {
2176      gchar *error;
2177      GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
2178      gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
2179
2180      param_values[i].g_type = 0;
2181      SIGNAL_UNLOCK ();
2182      g_value_init (param_values + i, ptype);
2183      G_VALUE_COLLECT (param_values + i,
2184		       var_args,
2185		       static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
2186		       &error);
2187      if (error)
2188	{
2189	  g_warning ("%s: %s", G_STRLOC, error);
2190	  g_free (error);
2191
2192	  /* we purposely leak the value here, it might not be
2193	   * in a sane state if an error condition occoured
2194	   */
2195	  while (i--)
2196	    g_value_unset (param_values + i);
2197
2198	  g_free (free_me);
2199	  return;
2200	}
2201      SIGNAL_LOCK ();
2202    }
2203  SIGNAL_UNLOCK ();
2204  instance_and_params->g_type = 0;
2205  g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (instance));
2206  g_value_set_instance (instance_and_params, instance);
2207  if (signal_return_type == G_TYPE_NONE)
2208    signal_emit_unlocked_R (node, detail, instance, NULL, instance_and_params);
2209  else
2210    {
2211      GValue return_value = { 0, };
2212      gchar *error = NULL;
2213      GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
2214      gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
2215
2216      g_value_init (&return_value, rtype);
2217
2218      signal_emit_unlocked_R (node, detail, instance, &return_value, instance_and_params);
2219
2220      G_VALUE_LCOPY (&return_value,
2221		     var_args,
2222		     static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
2223		     &error);
2224      if (!error)
2225	g_value_unset (&return_value);
2226      else
2227	{
2228	  g_warning ("%s: %s", G_STRLOC, error);
2229	  g_free (error);
2230
2231	  /* we purposely leak the value here, it might not be
2232	   * in a sane state if an error condition occured
2233	   */
2234	}
2235    }
2236  for (i = 0; i < n_params; i++)
2237    g_value_unset (param_values + i);
2238  g_value_unset (instance_and_params);
2239  if (free_me)
2240    g_free (free_me);
2241}
2242
2243void
2244g_signal_emit (gpointer instance,
2245	       guint    signal_id,
2246	       GQuark   detail,
2247	       ...)
2248{
2249  va_list var_args;
2250
2251  va_start (var_args, detail);
2252  g_signal_emit_valist (instance, signal_id, detail, var_args);
2253  va_end (var_args);
2254}
2255
2256void
2257g_signal_emit_by_name (gpointer     instance,
2258		       const gchar *detailed_signal,
2259		       ...)
2260{
2261  GQuark detail = 0;
2262  guint signal_id;
2263
2264  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2265  g_return_if_fail (detailed_signal != NULL);
2266
2267  SIGNAL_LOCK ();
2268  signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE);
2269  SIGNAL_UNLOCK ();
2270
2271  if (signal_id)
2272    {
2273      va_list var_args;
2274
2275      va_start (var_args, detailed_signal);
2276      g_signal_emit_valist (instance, signal_id, detail, var_args);
2277      va_end (var_args);
2278    }
2279  else
2280    g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
2281}
2282
2283static inline gboolean
2284accumulate (GSignalInvocationHint *ihint,
2285	    GValue                *return_accu,
2286	    GValue	          *handler_return,
2287	    SignalAccumulator     *accumulator)
2288{
2289  gboolean continue_emission;
2290
2291  if (!accumulator)
2292    return TRUE;
2293
2294  continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data);
2295  g_value_reset (handler_return);
2296
2297  return continue_emission;
2298}
2299
2300static gboolean
2301signal_emit_unlocked_R (SignalNode   *node,
2302			GQuark	      detail,
2303			gpointer      instance,
2304			GValue	     *emission_return,
2305			const GValue *instance_and_params)
2306{
2307  SignalAccumulator *accumulator;
2308  Emission emission;
2309  GClosure *class_closure;
2310  HandlerList *hlist;
2311  Handler *handler_list = NULL;
2312  GValue *return_accu, accu = { 0, };
2313  guint signal_id;
2314  gulong max_sequential_handler_number;
2315  gboolean return_value_altered = FALSE;
2316
2317#ifdef	G_ENABLE_DEBUG
2318  IF_DEBUG (SIGNALS, g_trace_instance_signals == instance || g_trap_instance_signals == instance)
2319    {
2320      g_message ("%s::%s(%u) emitted (instance=%p, signal-node=%p)",
2321		 g_type_name (G_TYPE_FROM_INSTANCE (instance)),
2322		 node->name, detail,
2323		 instance, node);
2324      if (g_trap_instance_signals == instance)
2325	G_BREAKPOINT ();
2326    }
2327#endif	/* G_ENABLE_DEBUG */
2328
2329  SIGNAL_LOCK ();
2330  signal_id = node->signal_id;
2331  if (node->flags & G_SIGNAL_NO_RECURSE)
2332    {
2333      Emission *node = emission_find (g_restart_emissions, signal_id, detail, instance);
2334
2335      if (node)
2336	{
2337	  node->state = EMISSION_RESTART;
2338	  SIGNAL_UNLOCK ();
2339	  return return_value_altered;
2340	}
2341    }
2342  accumulator = node->accumulator;
2343  if (accumulator)
2344    {
2345      SIGNAL_UNLOCK ();
2346      g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
2347      return_accu = &accu;
2348      SIGNAL_LOCK ();
2349    }
2350  else
2351    return_accu = emission_return;
2352  emission.instance = instance;
2353  emission.ihint.signal_id = node->signal_id;
2354  emission.ihint.detail = detail;
2355  emission.ihint.run_type = 0;
2356  emission.state = 0;
2357  emission.chain_type = G_TYPE_NONE;
2358  emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission);
2359  class_closure = signal_lookup_closure (node, instance);
2360
2361 EMIT_RESTART:
2362
2363  if (handler_list)
2364    handler_unref_R (signal_id, instance, handler_list);
2365  max_sequential_handler_number = g_handler_sequential_number;
2366  hlist = handler_list_lookup (signal_id, instance);
2367  handler_list = hlist ? hlist->handlers : NULL;
2368  if (handler_list)
2369    handler_ref (handler_list);
2370
2371  emission.ihint.run_type = G_SIGNAL_RUN_FIRST;
2372
2373  if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
2374    {
2375      emission.state = EMISSION_RUN;
2376
2377      emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
2378      SIGNAL_UNLOCK ();
2379      g_closure_invoke (class_closure,
2380			return_accu,
2381			node->n_params + 1,
2382			instance_and_params,
2383			&emission.ihint);
2384      if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2385	  emission.state == EMISSION_RUN)
2386	emission.state = EMISSION_STOP;
2387      SIGNAL_LOCK ();
2388      emission.chain_type = G_TYPE_NONE;
2389      return_value_altered = TRUE;
2390
2391      if (emission.state == EMISSION_STOP)
2392	goto EMIT_CLEANUP;
2393      else if (emission.state == EMISSION_RESTART)
2394	goto EMIT_RESTART;
2395    }
2396
2397  if (node->emission_hooks)
2398    {
2399      gboolean need_destroy, was_in_call, may_recurse = TRUE;
2400      GHook *hook;
2401
2402      emission.state = EMISSION_HOOK;
2403      hook = g_hook_first_valid (node->emission_hooks, may_recurse);
2404      while (hook)
2405	{
2406	  SignalHook *signal_hook = SIGNAL_HOOK (hook);
2407
2408	  if (!signal_hook->detail || signal_hook->detail == detail)
2409	    {
2410	      GSignalEmissionHook hook_func = (GSignalEmissionHook) hook->func;
2411
2412	      was_in_call = G_HOOK_IN_CALL (hook);
2413	      hook->flags |= G_HOOK_FLAG_IN_CALL;
2414              SIGNAL_UNLOCK ();
2415	      need_destroy = !hook_func (&emission.ihint, node->n_params + 1, instance_and_params, hook->data);
2416	      SIGNAL_LOCK ();
2417	      if (!was_in_call)
2418		hook->flags &= ~G_HOOK_FLAG_IN_CALL;
2419	      if (need_destroy)
2420		g_hook_destroy_link (node->emission_hooks, hook);
2421	    }
2422	  hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse);
2423	}
2424
2425      if (emission.state == EMISSION_RESTART)
2426	goto EMIT_RESTART;
2427    }
2428
2429  if (handler_list)
2430    {
2431      Handler *handler = handler_list;
2432
2433      emission.state = EMISSION_RUN;
2434      handler_ref (handler);
2435      do
2436	{
2437	  Handler *tmp;
2438
2439	  if (handler->after)
2440	    {
2441	      handler_unref_R (signal_id, instance, handler_list);
2442	      handler_list = handler;
2443	      break;
2444	    }
2445	  else if (!handler->block_count && (!handler->detail || handler->detail == detail) &&
2446		   handler->sequential_number < max_sequential_handler_number)
2447	    {
2448	      SIGNAL_UNLOCK ();
2449	      g_closure_invoke (handler->closure,
2450				return_accu,
2451				node->n_params + 1,
2452				instance_and_params,
2453				&emission.ihint);
2454	      if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2455		  emission.state == EMISSION_RUN)
2456		emission.state = EMISSION_STOP;
2457	      SIGNAL_LOCK ();
2458	      return_value_altered = TRUE;
2459
2460	      tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
2461	    }
2462	  else
2463	    tmp = handler->next;
2464
2465	  if (tmp)
2466	    handler_ref (tmp);
2467	  handler_unref_R (signal_id, instance, handler_list);
2468	  handler_list = handler;
2469	  handler = tmp;
2470	}
2471      while (handler);
2472
2473      if (emission.state == EMISSION_STOP)
2474	goto EMIT_CLEANUP;
2475      else if (emission.state == EMISSION_RESTART)
2476	goto EMIT_RESTART;
2477    }
2478
2479  emission.ihint.run_type = G_SIGNAL_RUN_LAST;
2480
2481  if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
2482    {
2483      emission.state = EMISSION_RUN;
2484
2485      emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
2486      SIGNAL_UNLOCK ();
2487      g_closure_invoke (class_closure,
2488			return_accu,
2489			node->n_params + 1,
2490			instance_and_params,
2491			&emission.ihint);
2492      if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2493	  emission.state == EMISSION_RUN)
2494	emission.state = EMISSION_STOP;
2495      SIGNAL_LOCK ();
2496      emission.chain_type = G_TYPE_NONE;
2497      return_value_altered = TRUE;
2498
2499      if (emission.state == EMISSION_STOP)
2500	goto EMIT_CLEANUP;
2501      else if (emission.state == EMISSION_RESTART)
2502	goto EMIT_RESTART;
2503    }
2504
2505  if (handler_list)
2506    {
2507      Handler *handler = handler_list;
2508
2509      emission.state = EMISSION_RUN;
2510      handler_ref (handler);
2511      do
2512	{
2513	  Handler *tmp;
2514
2515	  if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail) &&
2516	      handler->sequential_number < max_sequential_handler_number)
2517	    {
2518	      SIGNAL_UNLOCK ();
2519	      g_closure_invoke (handler->closure,
2520				return_accu,
2521				node->n_params + 1,
2522				instance_and_params,
2523				&emission.ihint);
2524	      if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2525		  emission.state == EMISSION_RUN)
2526		emission.state = EMISSION_STOP;
2527	      SIGNAL_LOCK ();
2528	      return_value_altered = TRUE;
2529
2530	      tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
2531	    }
2532	  else
2533	    tmp = handler->next;
2534
2535	  if (tmp)
2536	    handler_ref (tmp);
2537	  handler_unref_R (signal_id, instance, handler);
2538	  handler = tmp;
2539	}
2540      while (handler);
2541
2542      if (emission.state == EMISSION_STOP)
2543	goto EMIT_CLEANUP;
2544      else if (emission.state == EMISSION_RESTART)
2545	goto EMIT_RESTART;
2546    }
2547
2548 EMIT_CLEANUP:
2549
2550  emission.ihint.run_type = G_SIGNAL_RUN_CLEANUP;
2551
2552  if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
2553    {
2554      gboolean need_unset = FALSE;
2555
2556      emission.state = EMISSION_STOP;
2557
2558      emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
2559      SIGNAL_UNLOCK ();
2560      if (node->return_type != G_TYPE_NONE && !accumulator)
2561	{
2562	  g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
2563	  need_unset = TRUE;
2564	}
2565      g_closure_invoke (class_closure,
2566			node->return_type != G_TYPE_NONE ? &accu : NULL,
2567			node->n_params + 1,
2568			instance_and_params,
2569			&emission.ihint);
2570      if (need_unset)
2571	g_value_unset (&accu);
2572      SIGNAL_LOCK ();
2573      emission.chain_type = G_TYPE_NONE;
2574
2575      if (emission.state == EMISSION_RESTART)
2576	goto EMIT_RESTART;
2577    }
2578
2579  if (handler_list)
2580    handler_unref_R (signal_id, instance, handler_list);
2581
2582  emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission);
2583  SIGNAL_UNLOCK ();
2584  if (accumulator)
2585    g_value_unset (&accu);
2586
2587  return return_value_altered;
2588}
2589
2590static const gchar*
2591type_debug_name (GType type)
2592{
2593  if (type)
2594    {
2595      const char *name = g_type_name (type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
2596      return name ? name : "<unknown>";
2597    }
2598  else
2599    return "<invalid>";
2600}
2601
2602gboolean
2603g_signal_accumulator_true_handled (GSignalInvocationHint *ihint,
2604				   GValue                *return_accu,
2605				   const GValue          *handler_return,
2606				   gpointer               dummy)
2607{
2608  gboolean continue_emission;
2609  gboolean signal_handled;
2610
2611  signal_handled = g_value_get_boolean (handler_return);
2612  g_value_set_boolean (return_accu, signal_handled);
2613  continue_emission = !signal_handled;
2614
2615  return continue_emission;
2616}
2617
2618/* --- compile standard marshallers --- */
2619#include	"gobject.h"
2620#include	"genums.h"
2621#include        "gmarshal.c"
2622
2623#define __G_SIGNAL_C__
2624#include "gobjectaliasdef.c"
2625