gsignal.c revision a453526f350a3956a26f71db481bd8b436c65f97
1/* GObject - GLib Type, Object, Parameter and Signal Library
2 * Copyright (C) 2000 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#include <string.h>
23
24#include        "gsignal.h"
25
26#include        "gbsearcharray.h"
27
28
29/* pre allocation configurations
30 */
31#define BSA_PRE_ALLOC           (20)
32#define HANDLER_PRE_ALLOC       (48)
33#define EMISSION_PRE_ALLOC      (16)
34
35#define TIGHT_MEMORY    (1)
36
37#define REPORT_BUG      "please report occourance circumstances to gtk-devel-list@gnome.org"
38
39
40/* --- generic allocation --- */
41/* we can special case allocations generically by replacing
42 * these functions with more speed/memory aware variants
43 */
44static inline gpointer
45g_generic_node_alloc (GTrashStack **trash_stack_p,
46                      guint         sizeof_node,
47                      guint         nodes_pre_alloc)
48{
49  gpointer node = g_trash_stack_pop (trash_stack_p);
50
51  if (!node)
52    {
53      guint8 *block;
54
55      nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
56      block = g_malloc (sizeof_node * nodes_pre_alloc);
57      while (--nodes_pre_alloc)
58        {
59          g_trash_stack_push (trash_stack_p, block);
60          block += sizeof_node;
61        }
62      node = block;
63    }
64
65  return node;
66}
67static inline void
68g_generic_node_free (GTrashStack **trash_stack_p,
69                     gpointer      node)
70{
71  g_trash_stack_push (trash_stack_p, node);
72}
73
74
75/* --- typedefs --- */
76typedef struct _SignalNode   SignalNode;
77typedef struct _SignalKey    SignalKey;
78typedef struct _Emission     Emission;
79typedef struct _Handler      Handler;
80typedef struct _HandlerList  HandlerList;
81typedef struct _HandlerMatch HandlerMatch;
82typedef enum
83{
84  EMISSION_STOP,
85  EMISSION_RUN,
86  EMISSION_HOOK,
87  EMISSION_RESTART
88} EmissionState;
89
90
91/* --- prototypes --- */
92static inline guint		signal_id_lookup	(GQuark		  quark,
93							 GType		  itype);
94static	      void		signal_destroy_R	(SignalNode	 *signal_node);
95static inline HandlerList*	handler_list_ensure	(guint		  signal_id,
96							 gpointer	  instance);
97static inline HandlerList*	handler_list_lookup	(guint		  signal_id,
98							 gpointer	  instance);
99static inline Handler*		handler_new		(gboolean	  after);
100static	      void		handler_insert		(guint		  signal_id,
101							 gpointer	  instance,
102							 Handler	 *handler);
103static	      Handler*		handler_lookup		(gpointer	  instance,
104							 guint		  handler_id,
105							 guint		 *signal_id_p);
106static inline HandlerMatch*	handler_match_prepend	(HandlerMatch	 *list,
107							 Handler	 *handler,
108							 guint		  signal_id);
109static inline HandlerMatch*	handler_match_free1_R	(HandlerMatch	 *node,
110							 gpointer	  instance);
111static	      HandlerMatch*	handlers_find		(gpointer	  instance,
112							 GSignalMatchType mask,
113							 guint		  signal_id,
114							 GQuark		  detail,
115							 GClosure	 *closure,
116							 gpointer	  func,
117							 gpointer	  data,
118							 gboolean	  one_and_only);
119static inline void		handler_ref		(Handler	 *handler);
120static inline void		handler_unref_R		(guint		  signal_id,
121							 gpointer	  instance,
122							 Handler	 *handler);
123static inline void		emission_push		(Emission	**emission_list_p,
124							 guint		  signal_id,
125							 GQuark		  detail,
126							 gpointer	  instance,
127							 EmissionState	 *state_p);
128static inline void		emission_pop		(Emission	**emission_list_p,
129							 EmissionState	 *state_p);
130static inline Emission*		emission_find		(Emission	 *emission_list,
131							 guint		  signal_id,
132							 GQuark		  detail,
133							 gpointer	  instance);
134static	      void		signal_emit_R		(SignalNode	 *node,
135							 GQuark		  detail,
136							 gpointer	  instance,
137							 GValue		 *return_value,
138							 const GValue	 *instance_and_params);
139
140
141/* --- structures --- */
142struct _SignalNode
143{
144  /* permanent portion */
145  guint              signal_id;
146  GType              itype;
147  gchar             *name;
148  guint              destroyed : 1;
149
150  /* reinitializable portion */
151  guint              flags : 8;
152  guint              n_params : 8;
153  GType		    *param_types;
154  GType		     return_type;
155  GClosure          *class_closure;
156  GSignalAccumulator accumulator;
157  GSignalCMarshaller c_marshaller;
158  GHookList         *emission_hooks;
159};
160
161struct _SignalKey
162{
163  GType  itype;
164  GQuark quark;
165  guint  signal_id;
166};
167
168struct _Emission
169{
170  Emission      *next;
171  guint          signal_id;
172  GQuark	 detail;
173  gpointer       instance;
174  EmissionState *state_p;
175};
176
177struct _HandlerList
178{
179  guint    signal_id;
180  Handler *handlers;
181};
182struct _Handler
183{
184  guint         id;
185  Handler      *next;
186  Handler      *prev;
187  GQuark	detail;
188  guint         ref_count : 16;
189#define HANDLER_MAX_REF_COUNT   (1 << 16)
190  guint         block_count : 12;
191#define HANDLER_MAX_BLOCK_COUNT (1 << 12)
192  guint         after : 1;
193  GClosure     *closure;
194};
195struct _HandlerMatch
196{
197  Handler      *handler;
198  HandlerMatch *next;
199  union {
200    guint       signal_id;
201    gpointer	dummy;
202  } d;
203};
204
205
206/* --- variables --- */
207static GBSearchArray  g_signal_key_bsa = { NULL, 0, 0, 0, NULL };
208static GHashTable    *g_handler_list_bsa_ht = NULL;
209static Emission      *g_recursive_emissions = NULL;
210static Emission      *g_restart_emissions = NULL;
211static GTrashStack   *g_bsa_ts = NULL;
212static GTrashStack   *g_handler_ts = NULL;
213static GTrashStack   *g_emission_ts = NULL;
214G_LOCK_DEFINE_STATIC (g_signal_mutex);
215
216
217/* --- signal nodes --- */
218static guint          g_n_signal_nodes = 0;
219static SignalNode   **g_signal_nodes = NULL;
220
221static inline SignalNode*
222LOOKUP_SIGNAL_NODE (register guint signal_id)
223{
224  if (signal_id < g_n_signal_nodes)
225    return g_signal_nodes[signal_id];
226  else
227    return NULL;
228}
229
230
231/* --- functions --- */
232static inline guint
233signal_id_lookup (GQuark quark,
234		  GType  itype)
235{
236  do
237    {
238      SignalKey key, *signal_key;
239
240      key.itype = itype;
241      key.quark = quark;
242
243      signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
244
245      if (signal_key)
246	return signal_key->signal_id;
247
248      itype = g_type_parent (itype);
249    }
250  while (itype);
251
252  return 0;
253}
254
255static gint
256handler_lists_cmp (gconstpointer node1,
257                   gconstpointer node2)
258{
259  const HandlerList *hlist1 = node1, *hlist2 = node2;
260
261  return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
262}
263
264static inline HandlerList*
265handler_list_ensure (guint    signal_id,
266		     gpointer instance)
267{
268  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
269  HandlerList key;
270
271  if (!hlbsa)
272    {
273      hlbsa = g_generic_node_alloc (&g_bsa_ts,
274                                    sizeof (GBSearchArray),
275                                    BSA_PRE_ALLOC);
276      hlbsa->cmp_func = handler_lists_cmp;
277      hlbsa->sizeof_node = sizeof (HandlerList);
278      hlbsa->flags = G_BSEARCH_DEFER_SHRINK;
279      hlbsa->n_nodes = 0;
280      hlbsa->nodes = NULL;
281      g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
282    }
283  key.signal_id = signal_id;
284  key.handlers = NULL;
285
286  return g_bsearch_array_insert (hlbsa, &key, FALSE);
287}
288
289static inline HandlerList*
290handler_list_lookup (guint    signal_id,
291		     gpointer instance)
292{
293  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
294  HandlerList key;
295
296  key.signal_id = signal_id;
297
298  return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL;
299}
300
301static Handler*
302handler_lookup (gpointer instance,
303		guint    handler_id,
304		guint   *signal_id_p)
305{
306  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
307
308  if (hlbsa)
309    {
310      guint i;
311
312      for (i = 0; i < hlbsa->n_nodes; i++)
313        {
314          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
315          Handler *handler;
316
317          for (handler = hlist->handlers; handler; handler = handler->next)
318            if (handler->id == handler_id)
319              {
320                if (signal_id_p)
321                  *signal_id_p = hlist->signal_id;
322
323                return handler;
324              }
325        }
326    }
327
328  return NULL;
329}
330
331static inline HandlerMatch*
332handler_match_prepend (HandlerMatch *list,
333		       Handler      *handler,
334		       guint	     signal_id)
335{
336  HandlerMatch *node;
337
338  /* yeah, we could use our own memchunk here, introducing yet more
339   * rarely used cached nodes and extra allocation overhead.
340   * instead, we use GList* nodes, since they are exactly the size
341   * we need and are already cached. g_signal_init() asserts this.
342   */
343  node = (HandlerMatch*) g_list_alloc ();
344  node->handler = handler;
345  node->next = list;
346  node->d.signal_id = signal_id;
347  handler_ref (handler);
348
349  return node;
350}
351static inline HandlerMatch*
352handler_match_free1_R (HandlerMatch *node,
353		       gpointer      instance)
354{
355  HandlerMatch *next = node->next;
356
357  handler_unref_R (node->d.signal_id, instance, node->handler);
358  g_list_free_1 ((GList*) node);
359
360  return next;
361}
362
363static HandlerMatch*
364handlers_find (gpointer         instance,
365	       GSignalMatchType mask,
366	       guint            signal_id,
367	       GQuark           detail,
368	       GClosure        *closure,
369	       gpointer         func,
370	       gpointer         data,
371	       gboolean         one_and_only)
372{
373  HandlerMatch *mlist = NULL;
374
375  if (mask & G_SIGNAL_MATCH_ID)
376    {
377      HandlerList *hlist = handler_list_lookup (signal_id, instance);
378      Handler *handler;
379      SignalNode *node;
380
381      if (mask & G_SIGNAL_MATCH_FUNC)
382	{
383	  node = LOOKUP_SIGNAL_NODE (signal_id);
384	  if (!node || !node->c_marshaller)
385	    return NULL;
386	}
387
388      mask = ~mask;
389      for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
390        if (handler->id &&
391	    ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
392	    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
393            ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
394	    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
395	    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
396					      handler->closure->meta_marshal == 0 &&
397					      ((GCClosure*) handler->closure)->callback == func)))
398	  {
399	    mlist = handler_match_prepend (mlist, handler, signal_id);
400	    if (one_and_only)
401	      return mlist;
402	  }
403    }
404  else
405    {
406      GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
407
408      mask = ~mask;
409      if (hlbsa)
410        {
411          guint i;
412
413          for (i = 0; i < hlbsa->n_nodes; i++)
414            {
415              HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
416	      SignalNode *node;
417              Handler *handler;
418
419	      if (!(mask & G_SIGNAL_MATCH_FUNC))
420		{
421		  node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
422		  if (!node->c_marshaller)
423		    continue;
424		}
425
426              for (handler = hlist->handlers; handler; handler = handler->next)
427		if (handler->id &&
428		    ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
429                    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
430                    ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
431		    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
432		    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
433						      handler->closure->meta_marshal == 0 &&
434						      ((GCClosure*) handler->closure)->callback == func)))
435		  {
436		    mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
437		    if (one_and_only)
438		      return mlist;
439		  }
440            }
441        }
442    }
443
444  return mlist;
445}
446
447static inline Handler*
448handler_new (gboolean after)
449{
450  static guint handler_id = 1;
451  Handler *handler = g_generic_node_alloc (&g_handler_ts,
452                                           sizeof (Handler),
453                                           HANDLER_PRE_ALLOC);
454#ifndef G_DISABLE_CHECKS
455  if (handler_id == 0)
456    g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
457#endif
458
459  handler->id = handler_id++;
460  handler->prev = NULL;
461  handler->next = NULL;
462  handler->detail = 0;
463  handler->ref_count = 1;
464  handler->block_count = 0;
465  handler->after = after != FALSE;
466  handler->closure = NULL;
467
468  return handler;
469}
470
471static inline void
472handler_ref (Handler *handler)
473{
474  g_return_if_fail (handler->ref_count > 0);
475
476#ifndef G_DISABLE_CHECKS
477  if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
478    g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
479#endif
480
481  handler->ref_count += 1;
482}
483
484static inline void
485handler_unref_R (guint    signal_id,
486		 gpointer instance,
487		 Handler *handler)
488{
489  g_return_if_fail (handler->ref_count > 0);
490
491  handler->ref_count -= 1;
492  if (!handler->ref_count)
493    {
494      if (handler->next)
495        handler->next->prev = handler->prev;
496      if (handler->prev)	/* watch out for g_signal_handlers_destroy()! */
497        handler->prev->next = handler->next;
498      else
499        {
500          HandlerList *hlist = handler_list_lookup (signal_id, instance);
501
502          hlist->handlers = handler->next;
503        }
504      G_UNLOCK (g_signal_mutex);
505      g_closure_unref (handler->closure);
506      G_LOCK (g_signal_mutex);
507      g_generic_node_free (&g_handler_ts, handler);
508    }
509}
510
511static void
512handler_insert (guint    signal_id,
513		gpointer instance,
514		Handler  *handler)
515{
516  HandlerList *hlist;
517
518  g_assert (handler->prev == NULL && handler->next == NULL); // FIXME: paranoid
519
520  hlist = handler_list_ensure (signal_id, instance);
521  if (!hlist->handlers)
522    hlist->handlers = handler;
523  else if (hlist->handlers->after && !handler->after)
524    {
525      handler->next = hlist->handlers;
526      hlist->handlers->prev = handler;
527      hlist->handlers = handler;
528    }
529  else
530    {
531      Handler *tmp = hlist->handlers;
532
533      if (handler->after)
534        while (tmp->next)
535          tmp = tmp->next;
536      else
537        while (tmp->next && !tmp->next->after)
538          tmp = tmp->next;
539      if (tmp->next)
540        tmp->next->prev = handler;
541      handler->next = tmp->next;
542      handler->prev = tmp;
543      tmp->next = handler;
544    }
545}
546
547static inline void
548emission_push (Emission     **emission_list_p,
549	       guint          signal_id,
550	       GQuark	      detail,
551	       gpointer       instance,
552	       EmissionState *state_p)
553{
554  Emission *emission = g_generic_node_alloc (&g_emission_ts,
555                                             sizeof (Emission),
556                                             EMISSION_PRE_ALLOC);
557  emission->next = *emission_list_p;
558  emission->signal_id = signal_id;
559  emission->detail = detail;
560  emission->instance = instance;
561  emission->state_p = state_p;
562  *emission_list_p = emission;
563}
564
565static inline void
566emission_pop (Emission     **emission_list_p,
567	      EmissionState *state_p)
568{
569  Emission **loc = emission_list_p, *emission = *loc;
570
571  while (emission->state_p != state_p)
572    {
573      loc = &emission->next;
574      emission = *loc;
575    }
576  *loc = emission->next;
577  g_generic_node_free (&g_emission_ts, emission);
578}
579
580static inline Emission*
581emission_find (Emission *emission_list,
582	       guint     signal_id,
583	       GQuark    detail,
584	       gpointer  instance)
585{
586  Emission *emission;
587
588  for (emission = emission_list; emission; emission = emission->next)
589    if (emission->instance == instance &&
590	emission->signal_id == signal_id &&
591	emission->detail == detail)
592      return emission;
593  return NULL;
594}
595
596static gint
597signal_key_cmp (gconstpointer node1,
598                gconstpointer node2)
599{
600  const SignalKey *key1 = node1, *key2 = node2;
601
602  if (key1->itype == key2->itype)
603    return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
604  else
605    return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
606}
607
608void
609g_signal_init (void) /* sync with gtype.c */
610{
611  G_LOCK (g_signal_mutex);
612  if (!g_n_signal_nodes)
613    {
614      /* handler_id_node_prepend() requires this */
615      g_assert (sizeof (GList) == sizeof (HandlerMatch));
616
617      /* setup signal key array */
618      g_signal_key_bsa.cmp_func = signal_key_cmp;
619      g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
620      g_signal_key_bsa.flags = 0; /* alloc-only */
621
622      /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
623      g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
624
625      /* invalid (0) signal_id */
626      g_n_signal_nodes = 1;
627      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
628      g_signal_nodes[0] = NULL;
629    }
630  G_UNLOCK (g_signal_mutex);
631}
632
633void
634_g_signals_destroy (GType itype)
635{
636  guint i;
637
638  G_LOCK (g_signal_mutex);
639  for (i = 1; i < g_n_signal_nodes; i++)
640    {
641      SignalNode *node = g_signal_nodes[i];
642
643      if (node->itype == itype)
644        {
645          if (node->destroyed)
646            g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
647                       node->name,
648                       g_type_name (node->itype));
649          else
650	    signal_destroy_R (node);
651        }
652    }
653  G_UNLOCK (g_signal_mutex);
654}
655
656void
657g_signal_stop_emission (gpointer instance,
658                        guint    signal_id,
659			GQuark   detail)
660{
661  SignalNode *node;
662
663  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
664  g_return_if_fail (signal_id > 0);
665
666  G_LOCK (g_signal_mutex);
667  node = LOOKUP_SIGNAL_NODE (signal_id);
668  if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
669    {
670      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
671      G_UNLOCK (g_signal_mutex);
672      return;
673    }
674  if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
675    {
676      Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
677      Emission *emission = emission_find (emission_list, signal_id, detail, instance);
678
679      if (emission)
680        {
681          if (*emission->state_p == EMISSION_HOOK)
682            g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
683                       node->name, instance);
684          else if (*emission->state_p == EMISSION_RUN)
685            *emission->state_p = EMISSION_STOP;
686        }
687      else
688        g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
689                   node->name, instance);
690    }
691  else
692    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
693  G_UNLOCK (g_signal_mutex);
694}
695
696static inline guint
697signal_parse_name (const gchar *name,
698		   GType        itype,
699		   GQuark      *detail_p,
700		   gboolean     force_quark)
701{
702  const gchar *colon = strchr (name, ':');
703  guint signal_id;
704
705  if (!colon)
706    {
707      signal_id = signal_id_lookup (g_quark_try_string (name), itype);
708      if (signal_id && detail_p)
709	*detail_p = 0;
710    }
711  else if (colon[1] == ':')
712    {
713      gchar buffer[32];
714      guint l = colon - name;
715
716      if (l < 32)
717	{
718	  memcpy (buffer, name, l);
719	  buffer[l] = 0;
720	  signal_id = signal_id_lookup (g_quark_try_string (buffer), itype);
721	}
722      else
723	{
724	  gchar *signal = g_new (gchar, l + 1);
725
726	  memcpy (signal, name, l);
727	  signal[l] = 0;
728	  signal_id = signal_id_lookup (g_quark_try_string (signal), itype);
729	  g_free (signal);
730	}
731
732      if (signal_id && detail_p)
733	*detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0;
734    }
735  else
736    signal_id = 0;
737  return signal_id;
738}
739
740gboolean
741g_signal_parse_name (const gchar *detailed_signal,
742		     GType        itype,
743		     guint       *signal_id_p,
744		     GQuark      *detail_p,
745		     gboolean	  force_detail_quark)
746{
747  GQuark detail = 0;
748  guint signal_id;
749
750  g_return_val_if_fail (detailed_signal != NULL, FALSE);
751  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
752
753  G_LOCK (g_signal_mutex);
754  signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
755  G_UNLOCK (g_signal_mutex);
756
757  if (signal_id)
758    {
759      if (signal_id_p)
760	*signal_id_p = signal_id;
761      if (detail_p)
762	*detail_p = detail;
763
764      return TRUE;
765    }
766  else
767    return FALSE;
768}
769
770guint
771g_signal_lookup (const gchar *name,
772                 GType        itype)
773{
774  guint signal_id;
775
776  g_return_val_if_fail (name != NULL, 0);
777  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
778
779  G_LOCK (g_signal_mutex);
780  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
781  G_UNLOCK (g_signal_mutex);
782
783  return signal_id;
784}
785
786gchar*
787g_signal_name (guint signal_id)
788{
789  SignalNode *node;
790  gchar *name;
791
792  G_LOCK (g_signal_mutex);
793  node = LOOKUP_SIGNAL_NODE (signal_id);
794  name = node ? node->name : NULL;
795  G_UNLOCK (g_signal_mutex);
796
797  return name;
798}
799
800void
801g_signal_query (guint         signal_id,
802		GSignalQuery *query)
803{
804  SignalNode *node;
805
806  g_return_if_fail (query != NULL);
807
808  G_LOCK (g_signal_mutex);
809  node = LOOKUP_SIGNAL_NODE (signal_id);
810  if (!node || node->destroyed)
811    query->signal_id = 0;
812  else
813    {
814      query->signal_id = node->signal_id;
815      query->signal_name = node->name;
816      query->itype = node->itype;
817      query->signal_flags = node->flags;
818      query->return_type = node->return_type;
819      query->n_params = node->n_params;
820      query->param_types = node->param_types;
821    }
822  G_UNLOCK (g_signal_mutex);
823}
824
825guint*
826g_signal_list_ids (GType  itype,
827		   guint *n_ids)
828{
829  SignalKey *keys;
830  GArray *result;
831  guint n_nodes;
832  guint i;
833
834  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
835  g_return_val_if_fail (n_ids != NULL, NULL);
836
837  G_LOCK (g_signal_mutex);
838
839  keys = g_signal_key_bsa.nodes;
840  n_nodes  = g_signal_key_bsa.n_nodes;
841  result = g_array_new (FALSE, FALSE, sizeof (guint));
842
843  for (i = 0; i < n_nodes; i++)
844    if (keys[i].itype == itype)
845      {
846	gchar *name = g_quark_to_string (keys[i].quark);
847
848	/* Signal names with "_" in them are aliases to the same
849	 * name with "-" instead of "_".
850	 */
851	if (!strchr (name, '_'))
852	  g_array_append_val (result, keys[i].signal_id);
853      }
854
855  *n_ids = result->len;
856
857  G_UNLOCK (g_signal_mutex);
858
859  return (guint *) g_array_free (result, FALSE);
860}
861
862guint
863g_signal_newv (const gchar       *signal_name,
864               GType              itype,
865               GSignalFlags       signal_flags,
866               GClosure          *class_closure,
867               GSignalAccumulator accumulator,
868               GSignalCMarshaller c_marshaller,
869               GType		  return_type,
870               guint              n_params,
871               GType		 *param_types)
872{
873  gchar *name;
874  guint signal_id, i;
875  SignalNode *node;
876
877  g_return_val_if_fail (signal_name != NULL, 0);
878  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
879  if (n_params)
880    g_return_val_if_fail (param_types != NULL, 0);
881  if (return_type != G_TYPE_NONE)
882    g_return_val_if_fail (accumulator == NULL, 0);
883
884  name = g_strdup (signal_name);
885  g_strdelimit (name, G_STR_DELIMITERS ":^", '_');  // FIXME do character checks like for types
886
887  G_LOCK (g_signal_mutex);
888
889  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
890  node = LOOKUP_SIGNAL_NODE (signal_id);
891  if (node && !node->destroyed)
892    {
893      g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
894                 name,
895                 g_type_name (node->itype),
896                 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
897      g_free (name);
898      G_UNLOCK (g_signal_mutex);
899      return 0;
900    }
901  if (node && node->itype != itype)
902    {
903      g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
904                 name,
905                 g_type_name (itype),
906                 g_type_name (node->itype));
907      g_free (name);
908      G_UNLOCK (g_signal_mutex);
909      return 0;
910    }
911  for (i = 0; i < n_params; i++)
912    if (!G_TYPE_IS_VALUE (param_types[i]) ||
913	param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */
914      {
915	g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
916		   i + 1, g_type_name (param_types[i]), g_type_name (itype), name);
917	g_free (name);
918	G_UNLOCK (g_signal_mutex);
919	return 0;
920      }
921  if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type))
922    {
923      g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
924		 g_type_name (param_types[i]), g_type_name (itype), name);
925      g_free (name);
926      G_UNLOCK (g_signal_mutex);
927      return 0;
928    }
929
930  /* setup permanent portion of signal node */
931  if (!node)
932    {
933      SignalKey key;
934
935      signal_id = g_n_signal_nodes++;
936      node = g_new (SignalNode, 1);
937      node->signal_id = signal_id;
938      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
939      g_signal_nodes[signal_id] = node;
940      node->itype = itype;
941      node->name = name;
942      key.itype = itype;
943      key.quark = g_quark_from_string (node->name);
944      key.signal_id = signal_id;
945      g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
946      g_strdelimit (node->name, "_", '-');
947      key.quark = g_quark_from_static_string (node->name);
948      g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
949    }
950  node->destroyed = FALSE;
951
952  /* setup reinitializable portion */
953  node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
954  node->n_params = n_params;
955  node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
956  node->return_type = return_type;
957  node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL;
958  node->accumulator = accumulator;
959  node->c_marshaller = c_marshaller;
960  node->emission_hooks = NULL;
961  if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure))
962    g_closure_set_marshal (class_closure, node->c_marshaller);
963
964  G_UNLOCK (g_signal_mutex);
965  return signal_id;
966}
967
968static void
969signal_destroy_R (SignalNode *signal_node)
970{
971  SignalNode node = *signal_node;
972
973  signal_node->destroyed = TRUE;
974
975  /* reentrancy caution, zero out real contents first */
976  signal_node->n_params = 0;
977  signal_node->param_types = NULL;
978  signal_node->return_type = 0;
979  signal_node->class_closure = NULL;
980  signal_node->accumulator = NULL;
981  signal_node->c_marshaller = NULL;
982  signal_node->emission_hooks = NULL;
983
984#ifndef G_DISABLE_CHECKS
985  /* check current emissions */
986  {
987    Emission *emission;
988
989    for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
990         emission; emission = emission->next)
991      if (emission->signal_id == node.signal_id)
992        g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
993                    node.name, emission->instance);
994  }
995#endif
996
997  /* free contents that need to
998   */
999  G_UNLOCK (g_signal_mutex);
1000  g_free (node.param_types);
1001  g_closure_unref (node.class_closure);
1002  if (node.emission_hooks)
1003    {
1004      g_hook_list_clear (node.emission_hooks);
1005      g_free (node.emission_hooks);
1006    }
1007  G_LOCK (g_signal_mutex);
1008}
1009
1010guint
1011g_signal_connect_closure_by_id (gpointer  instance,
1012				guint     signal_id,
1013				GQuark    detail,
1014				GClosure *closure,
1015				gboolean  after)
1016{
1017  SignalNode *node;
1018  guint handler_id = 0;
1019
1020  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1021  g_return_val_if_fail (signal_id > 0, 0);
1022  g_return_val_if_fail (closure != NULL, 0);
1023
1024  G_LOCK (g_signal_mutex);
1025  node = LOOKUP_SIGNAL_NODE (signal_id);
1026  if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
1027    {
1028      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1029      G_UNLOCK (g_signal_mutex);
1030      return 0;
1031    }
1032  if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
1033    {
1034      Handler *handler = handler_new (after);
1035
1036      handler_id = handler->id;
1037      handler->detail = detail;
1038      handler->closure = g_closure_ref (closure);
1039      handler_insert (signal_id, instance, handler);
1040      if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
1041	g_closure_set_marshal (closure, node->c_marshaller);
1042    }
1043  else
1044    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1045  G_UNLOCK (g_signal_mutex);
1046
1047  return handler_id;
1048}
1049
1050void
1051g_signal_handler_block (gpointer instance,
1052                        guint    handler_id)
1053{
1054  Handler *handler;
1055
1056  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1057  g_return_if_fail (handler_id > 0);
1058
1059  G_LOCK (g_signal_mutex);
1060  handler = handler_lookup (instance, handler_id, NULL);
1061  if (handler)
1062    {
1063#ifndef G_DISABLE_CHECKS
1064      if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
1065        g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
1066#endif
1067
1068      handler->block_count += 1;
1069    }
1070  else
1071    g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1072  G_UNLOCK (g_signal_mutex);
1073}
1074
1075void
1076g_signal_handler_unblock (gpointer instance,
1077                          guint    handler_id)
1078{
1079  Handler *handler;
1080
1081  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1082  g_return_if_fail (handler_id > 0);
1083
1084  G_LOCK (g_signal_mutex);
1085  handler = handler_lookup (instance, handler_id, NULL);
1086  if (handler)
1087    {
1088      if (handler->block_count)
1089        handler->block_count -= 1;
1090      else
1091        g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance);
1092    }
1093  else
1094    g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1095  G_UNLOCK (g_signal_mutex);
1096}
1097
1098void
1099g_signal_handler_disconnect (gpointer instance,
1100                             guint    handler_id)
1101{
1102  Handler *handler;
1103  guint signal_id;
1104
1105  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1106  g_return_if_fail (handler_id > 0);
1107
1108  G_LOCK (g_signal_mutex);
1109  handler = handler_lookup (instance, handler_id, &signal_id);
1110  if (handler)
1111    {
1112      handler->id = 0;
1113      handler->block_count = 1;
1114      handler_unref_R (signal_id, instance, handler);
1115    }
1116  else
1117    g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1118  G_UNLOCK (g_signal_mutex);
1119}
1120
1121void
1122g_signal_handlers_destroy (gpointer instance)
1123{
1124  GBSearchArray *hlbsa;
1125
1126  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1127
1128  G_LOCK (g_signal_mutex);
1129  hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
1130  if (hlbsa)
1131    {
1132      guint i;
1133
1134      /* reentrancy caution, delete instance trace first */
1135      g_hash_table_remove (g_handler_list_bsa_ht, instance);
1136
1137      for (i = 0; i < hlbsa->n_nodes; i++)
1138        {
1139          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
1140          Handler *handler = hlist->handlers;
1141
1142          while (handler)
1143            {
1144              Handler *tmp = handler;
1145
1146              handler = tmp->next;
1147              tmp->block_count = 1;
1148              /* cruel unlink, this works because _all_ handlers vanish */
1149              tmp->next = NULL;
1150              tmp->prev = tmp;
1151              if (tmp->id)
1152		{
1153		  tmp->id = 0;
1154		  handler_unref_R (0, NULL, tmp);
1155		}
1156            }
1157        }
1158      g_free (hlbsa->nodes);
1159      g_generic_node_free (&g_bsa_ts, hlbsa);
1160    }
1161  G_UNLOCK (g_signal_mutex);
1162}
1163
1164guint
1165g_signal_handler_find (gpointer         instance,
1166                       GSignalMatchType mask,
1167                       guint            signal_id,
1168		       GQuark		detail,
1169                       GClosure        *closure,
1170                       gpointer         func,
1171                       gpointer         data)
1172{
1173  guint handler_id = 0;
1174
1175  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1176  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1177
1178  if (mask & G_SIGNAL_MATCH_MASK)
1179    {
1180      HandlerMatch *mlist;
1181
1182      G_LOCK (g_signal_mutex);
1183      mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
1184      if (mlist)
1185	{
1186	  handler_id = mlist->handler->id;
1187	  handler_match_free1_R (mlist, instance);
1188	}
1189      G_UNLOCK (g_signal_mutex);
1190    }
1191
1192  return handler_id;
1193}
1194
1195static guint
1196signal_handlers_foreach_matched_R (gpointer         instance,
1197				   GSignalMatchType mask,
1198				   guint            signal_id,
1199				   GQuark           detail,
1200				   GClosure        *closure,
1201				   gpointer         func,
1202				   gpointer         data,
1203				   void		  (*callback) (gpointer instance,
1204							       guint    handler_id))
1205{
1206  HandlerMatch *mlist;
1207  guint n_handlers = 0;
1208
1209  mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
1210  while (mlist)
1211    {
1212      n_handlers++;
1213      G_UNLOCK (g_signal_mutex);
1214      callback (instance, mlist->handler->id);
1215      G_LOCK (g_signal_mutex);
1216      mlist = handler_match_free1_R (mlist, instance);
1217    }
1218
1219  return n_handlers;
1220}
1221
1222guint
1223g_signal_handlers_block_matched (gpointer         instance,
1224				 GSignalMatchType mask,
1225				 guint            signal_id,
1226				 GQuark           detail,
1227				 GClosure        *closure,
1228				 gpointer         func,
1229				 gpointer         data)
1230{
1231  guint n_handlers = 0;
1232
1233  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1234  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1235
1236  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1237    {
1238      G_LOCK (g_signal_mutex);
1239      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1240						      closure, func, data,
1241						      g_signal_handler_block);
1242      G_UNLOCK (g_signal_mutex);
1243    }
1244
1245  return n_handlers;
1246}
1247
1248guint
1249g_signal_handlers_unblock_matched (gpointer         instance,
1250				   GSignalMatchType mask,
1251				   guint            signal_id,
1252				   GQuark           detail,
1253				   GClosure        *closure,
1254				   gpointer         func,
1255				   gpointer         data)
1256{
1257  guint n_handlers = 0;
1258
1259  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1260  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1261
1262  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1263    {
1264      G_LOCK (g_signal_mutex);
1265      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1266						      closure, func, data,
1267						      g_signal_handler_unblock);
1268      G_UNLOCK (g_signal_mutex);
1269    }
1270
1271  return n_handlers;
1272}
1273
1274guint
1275g_signal_handlers_disconnect_matched (gpointer         instance,
1276				      GSignalMatchType mask,
1277				      guint            signal_id,
1278				      GQuark           detail,
1279				      GClosure        *closure,
1280				      gpointer         func,
1281				      gpointer         data)
1282{
1283  guint n_handlers = 0;
1284
1285  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1286  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1287
1288  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1289    {
1290      G_LOCK (g_signal_mutex);
1291      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1292						      closure, func, data,
1293						      g_signal_handler_disconnect);
1294      G_UNLOCK (g_signal_mutex);
1295    }
1296
1297  return n_handlers;
1298}
1299
1300gboolean
1301g_signal_has_handler_pending (gpointer instance,
1302			      guint    signal_id,
1303			      GQuark   detail,
1304			      gboolean may_be_blocked)
1305{
1306  HandlerMatch *mlist;
1307  gboolean has_pending;
1308
1309  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1310  g_return_val_if_fail (signal_id > 0, FALSE);
1311
1312  G_LOCK (g_signal_mutex);
1313  if (detail)
1314    {
1315      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1316
1317      if (!(node->flags & G_SIGNAL_DETAILED))
1318	{
1319	  g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1320	  G_UNLOCK (g_signal_mutex);
1321	  return FALSE;
1322	}
1323    }
1324  mlist = handlers_find (instance,
1325			 (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
1326			 signal_id, detail, NULL, NULL, NULL, TRUE);
1327  if (mlist)
1328    {
1329      has_pending = TRUE;
1330      handler_match_free1_R (mlist, instance);
1331    }
1332  else
1333    has_pending = FALSE;
1334  G_UNLOCK (g_signal_mutex);
1335
1336  return has_pending;
1337}
1338
1339void
1340g_signal_emitv (const GValue *instance_and_params,
1341		guint         signal_id,
1342		GQuark	      detail,
1343		GValue       *return_value)
1344{
1345  SignalNode *node;
1346  gpointer instance;
1347  const GValue *param_values;
1348  guint i;
1349
1350  g_return_if_fail (instance_and_params != NULL);
1351  instance = g_value_get_as_pointer (instance_and_params);
1352  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1353  g_return_if_fail (signal_id > 0);
1354
1355  param_values = instance_and_params + 1;
1356
1357  G_LOCK (g_signal_mutex);
1358  node = LOOKUP_SIGNAL_NODE (signal_id);
1359#ifndef G_DISABLE_CHECKS
1360  if (!node || !g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
1361    {
1362      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1363      G_UNLOCK (g_signal_mutex);
1364      return;
1365    }
1366  if (detail && !(node->flags & G_SIGNAL_DETAILED))
1367    {
1368      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1369      G_UNLOCK (g_signal_mutex);
1370      return;
1371    }
1372  for (i = 0; i < node->n_params; i++)
1373    if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
1374      {
1375	g_critical (G_STRLOC ": value for `%s' parameter %u for signal \"%s\" is of type `%s'",
1376		    g_type_name (node->param_types[i]),
1377		    i,
1378		    node->name,
1379		    G_VALUE_TYPE_NAME (param_values + i));
1380	G_UNLOCK (g_signal_mutex);
1381	return;
1382      }
1383  if (node->return_type != G_TYPE_NONE)
1384    {
1385      if (!return_value)
1386	{
1387	  g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is (NULL)",
1388		      g_type_name (node->return_type),
1389		      node->name);
1390	  G_UNLOCK (g_signal_mutex);
1391	  return;
1392	}
1393      else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
1394	{
1395	  g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is of type `%s'",
1396		      g_type_name (node->return_type),
1397		      node->name,
1398		      G_VALUE_TYPE_NAME (return_value));
1399	  G_UNLOCK (g_signal_mutex);
1400	  return;
1401	}
1402    }
1403  else
1404    return_value = NULL;
1405#endif	/* !G_DISABLE_CHECKS */
1406
1407  signal_emit_R (node, detail, instance, return_value, instance_and_params);
1408
1409  G_UNLOCK (g_signal_mutex);
1410}
1411
1412static void
1413signal_emit_R (SignalNode   *node,
1414	       GQuark	     detail,
1415	       gpointer      instance,
1416	       GValue	    *return_value,
1417	       const GValue *instance_and_params)
1418{
1419  EmissionState emission_state = 0;
1420  GSignalAccumulator accumulator;
1421  GSignalInvocationHint ihint;
1422  GClosure *class_closure;
1423  HandlerList *hlist;
1424  Handler *handler_list = NULL;
1425  GValue accu;
1426  gboolean accu_used = FALSE;
1427  guint signal_id = node->signal_id;
1428
1429  if (node->flags & G_SIGNAL_NO_RECURSE)
1430    {
1431      Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance);
1432
1433      if (emission)
1434	{
1435	  *emission->state_p = EMISSION_RESTART;
1436	  return;
1437	}
1438    }
1439  ihint.signal_id = node->signal_id;
1440  ihint.detail = detail;
1441  accumulator = node->accumulator;
1442  if (accumulator)
1443    {
1444      G_UNLOCK (g_signal_mutex);
1445      g_value_init (&accu, node->return_type);
1446      G_LOCK (g_signal_mutex);
1447    }
1448  emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
1449		 signal_id, detail, instance, &emission_state);
1450  class_closure = node->class_closure;
1451
1452 EMIT_RESTART:
1453
1454  if (handler_list)
1455    handler_unref_R (signal_id, instance, handler_list);
1456  hlist = handler_list_lookup (signal_id, instance);
1457  handler_list = hlist ? hlist->handlers : NULL;
1458  if (handler_list)
1459    handler_ref (handler_list);
1460
1461  ihint.run_type = G_SIGNAL_RUN_FIRST;
1462
1463  if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
1464    {
1465      emission_state = EMISSION_RUN;
1466
1467      G_UNLOCK (g_signal_mutex);
1468      if (accumulator)
1469	{
1470	  if (accu_used)
1471	    g_value_reset (&accu);
1472	  g_closure_invoke (class_closure,
1473			    &accu,
1474			    node->n_params + 1,
1475			    instance_and_params,
1476			    &ihint);
1477	  if (!accumulator (&ihint, return_value, &accu) &&
1478	      emission_state == EMISSION_RUN)
1479	    emission_state = EMISSION_STOP;
1480	  accu_used = TRUE;
1481	}
1482      else
1483	g_closure_invoke (class_closure,
1484			  return_value,
1485			  node->n_params + 1,
1486			  instance_and_params,
1487			  &ihint);
1488      G_LOCK (g_signal_mutex);
1489
1490      if (emission_state == EMISSION_STOP)
1491	goto EMIT_CLEANUP;
1492      else if (emission_state == EMISSION_RESTART)
1493	goto EMIT_RESTART;
1494    }
1495
1496  if (node->emission_hooks)
1497    {
1498      emission_state = EMISSION_HOOK;
1499
1500      G_UNLOCK (g_signal_mutex);
1501      g_print ("emission_hooks()\n");
1502      G_LOCK (g_signal_mutex);
1503
1504      if (emission_state == EMISSION_RESTART)
1505	goto EMIT_RESTART;
1506    }
1507
1508  if (handler_list)
1509    {
1510      Handler *handler = handler_list;
1511
1512      emission_state = EMISSION_RUN;
1513      handler_ref (handler);
1514      do
1515	{
1516	  Handler *tmp;
1517
1518	  if (handler->after)
1519	    {
1520	      handler_unref_R (signal_id, instance, handler_list);
1521	      handler_list = handler;
1522	      break;
1523	    }
1524	  else if (!handler->block_count && (!handler->detail || handler->detail == detail))
1525	    {
1526	      G_UNLOCK (g_signal_mutex);
1527	      if (accumulator)
1528		{
1529		  if (accu_used)
1530		    g_value_reset (&accu);
1531		  g_closure_invoke (handler->closure,
1532				    &accu,
1533				    node->n_params + 1,
1534				    instance_and_params,
1535				    &ihint);
1536		  if (!accumulator (&ihint, return_value, &accu) &&
1537		      emission_state == EMISSION_RUN)
1538		    emission_state = EMISSION_STOP;
1539		  accu_used = TRUE;
1540		}
1541	      else
1542		g_closure_invoke (handler->closure,
1543				  return_value,
1544				  node->n_params + 1,
1545				  instance_and_params,
1546				  &ihint);
1547	      G_LOCK (g_signal_mutex);
1548
1549	      tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1550	    }
1551	  else
1552	    tmp = handler->next;
1553
1554	  if (tmp)
1555	    handler_ref (tmp);
1556	  handler_unref_R (signal_id, instance, handler_list);
1557	  handler_list = handler;
1558	  handler = tmp;
1559	}
1560      while (handler);
1561
1562      if (emission_state == EMISSION_STOP)
1563	goto EMIT_CLEANUP;
1564      else if (emission_state == EMISSION_RESTART)
1565	goto EMIT_RESTART;
1566    }
1567
1568  ihint.run_type = G_SIGNAL_RUN_LAST;
1569
1570  if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
1571    {
1572      emission_state = EMISSION_RUN;
1573
1574      G_UNLOCK (g_signal_mutex);
1575      if (accumulator)
1576	{
1577	  if (accu_used)
1578	    g_value_reset (&accu);
1579	  g_closure_invoke (class_closure,
1580			    &accu,
1581			    node->n_params + 1,
1582			    instance_and_params,
1583			    &ihint);
1584          if (!accumulator (&ihint, return_value, &accu) &&
1585	      emission_state == EMISSION_RUN)
1586	    emission_state = EMISSION_STOP;
1587	  accu_used = TRUE;
1588	}
1589      else
1590	g_closure_invoke (class_closure,
1591			  return_value,
1592			  node->n_params + 1,
1593			  instance_and_params,
1594			  &ihint);
1595      G_LOCK (g_signal_mutex);
1596
1597      if (emission_state == EMISSION_STOP)
1598	goto EMIT_CLEANUP;
1599      else if (emission_state == EMISSION_RESTART)
1600	goto EMIT_RESTART;
1601    }
1602
1603  if (handler_list)
1604    {
1605      Handler *handler = handler_list;
1606
1607      emission_state = EMISSION_RUN;
1608      handler_ref (handler);
1609      do
1610	{
1611	  Handler *tmp;
1612
1613	  if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail))
1614	    {
1615	      G_UNLOCK (g_signal_mutex);
1616              if (accumulator)
1617		{
1618		  if (accu_used)
1619		    g_value_reset (&accu);
1620		  g_closure_invoke (handler->closure,
1621				    &accu,
1622				    node->n_params + 1,
1623				    instance_and_params,
1624				    &ihint);
1625		  if (!accumulator (&ihint, return_value, &accu) &&
1626		      emission_state == EMISSION_RUN)
1627		    emission_state = EMISSION_STOP;
1628		  accu_used = TRUE;
1629		}
1630	      else
1631		g_closure_invoke (handler->closure,
1632				  return_value,
1633				  node->n_params + 1,
1634				  instance_and_params,
1635				  &ihint);
1636	      G_LOCK (g_signal_mutex);
1637
1638	      tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1639	    }
1640	  else
1641	    tmp = handler->next;
1642
1643	  if (tmp)
1644	    handler_ref (tmp);
1645	  handler_unref_R (signal_id, instance, handler);
1646	  handler = tmp;
1647	}
1648      while (handler);
1649
1650      if (emission_state == EMISSION_STOP)
1651	goto EMIT_CLEANUP;
1652      else if (emission_state == EMISSION_RESTART)
1653	goto EMIT_RESTART;
1654    }
1655
1656 EMIT_CLEANUP:
1657
1658  ihint.run_type = G_SIGNAL_RUN_CLEANUP;
1659
1660  if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
1661    {
1662      gboolean need_unset = FALSE;
1663
1664      emission_state = EMISSION_STOP;
1665
1666      G_UNLOCK (g_signal_mutex);
1667      if (node->return_type != G_TYPE_NONE)
1668	{
1669	  if (!accumulator)
1670	    {
1671	      g_value_init (&accu, node->return_type);
1672	      need_unset = TRUE;
1673	    }
1674	  else if (accu_used)
1675	    g_value_reset (&accu);
1676	}
1677      g_closure_invoke (class_closure,
1678			node->return_type != G_TYPE_NONE ? &accu : NULL,
1679			node->n_params + 1,
1680			instance_and_params,
1681			&ihint);
1682      if (need_unset)
1683	g_value_unset (&accu);
1684      G_LOCK (g_signal_mutex);
1685
1686      if (emission_state == EMISSION_RESTART)
1687	goto EMIT_RESTART;
1688    }
1689
1690  if (handler_list)
1691    handler_unref_R (signal_id, instance, handler_list);
1692
1693  emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
1694  if (accumulator)
1695    {
1696      G_UNLOCK (g_signal_mutex);
1697      g_value_unset (&accu);
1698      G_LOCK (g_signal_mutex);
1699    }
1700}
1701