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