Fix warnings.
[platform/upstream/glib.git] / gobject / gsignal.c
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  */
44 static inline gpointer
45 g_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 }
67 static inline void
68 g_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 --- */
76 typedef struct _SignalNode   SignalNode;
77 typedef struct _SignalKey    SignalKey;
78 typedef struct _Emission     Emission;
79 typedef struct _Handler      Handler;
80 typedef struct _HandlerList  HandlerList;
81 typedef struct _HandlerMatch HandlerMatch;
82 typedef enum
83 {
84   EMISSION_STOP,
85   EMISSION_RUN,
86   EMISSION_HOOK,
87   EMISSION_RESTART
88 } EmissionState;
89
90
91 /* --- prototypes --- */
92 static inline guint             signal_id_lookup        (GQuark           quark,
93                                                          GType            itype);
94 static        void              signal_destroy_R        (SignalNode      *signal_node);
95 static inline HandlerList*      handler_list_ensure     (guint            signal_id,
96                                                          gpointer         instance);
97 static inline HandlerList*      handler_list_lookup     (guint            signal_id,
98                                                          gpointer         instance);
99 static inline Handler*          handler_new             (gboolean         after);
100 static        void              handler_insert          (guint            signal_id,
101                                                          gpointer         instance,
102                                                          Handler         *handler);
103 static        Handler*          handler_lookup          (gpointer         instance,
104                                                          guint            handler_id,
105                                                          guint           *signal_id_p);
106 static inline HandlerMatch*     handler_match_prepend   (HandlerMatch    *list,
107                                                          Handler         *handler,
108                                                          guint            signal_id);
109 static inline HandlerMatch*     handler_match_free1_R   (HandlerMatch    *node,
110                                                          gpointer         instance);
111 static        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);
119 static inline void              handler_ref             (Handler         *handler);
120 static inline void              handler_unref_R         (guint            signal_id,
121                                                          gpointer         instance,
122                                                          Handler         *handler);
123 static inline void              emission_push           (Emission       **emission_list_p,
124                                                          guint            signal_id,
125                                                          GQuark           detail,
126                                                          gpointer         instance,
127                                                          EmissionState   *state_p);
128 static inline void              emission_pop            (Emission       **emission_list_p,
129                                                          EmissionState   *state_p);
130 static inline Emission*         emission_find           (Emission        *emission_list,
131                                                          guint            signal_id,
132                                                          GQuark           detail,
133                                                          gpointer         instance);
134 static        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 --- */
142 struct _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
161 struct _SignalKey
162 {
163   GType  itype;
164   GQuark quark;
165   guint  signal_id;
166 };
167
168 struct _Emission
169 {
170   Emission      *next;
171   guint          signal_id;
172   GQuark         detail;
173   gpointer       instance;
174   EmissionState *state_p;
175 };
176
177 struct _HandlerList
178 {
179   guint    signal_id;
180   Handler *handlers;
181 };
182 struct _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 };
195 struct _HandlerMatch
196 {
197   Handler      *handler;
198   HandlerMatch *next;
199   union {
200     guint       signal_id;
201     gpointer    dummy;
202   } d;
203 };
204
205
206 /* --- variables --- */
207 static GBSearchArray  g_signal_key_bsa = { NULL, 0, 0, 0, NULL };
208 static GHashTable    *g_handler_list_bsa_ht = NULL;
209 static Emission      *g_recursive_emissions = NULL;
210 static Emission      *g_restart_emissions = NULL;
211 static GTrashStack   *g_bsa_ts = NULL;
212 static GTrashStack   *g_handler_ts = NULL;
213 static GTrashStack   *g_emission_ts = NULL;
214 G_LOCK_DEFINE_STATIC (g_signal_mutex);
215
216
217 /* --- signal nodes --- */
218 static guint          g_n_signal_nodes = 0;
219 static SignalNode   **g_signal_nodes = NULL;
220
221 static inline SignalNode*
222 LOOKUP_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 --- */
232 static inline guint
233 signal_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
255 static gint
256 handler_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
264 static inline HandlerList*
265 handler_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
289 static inline HandlerList*
290 handler_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
301 static Handler*
302 handler_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
331 static inline HandlerMatch*
332 handler_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 }
351 static inline HandlerMatch*
352 handler_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
363 static HandlerMatch*
364 handlers_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 = NULL;
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 = NULL;
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
447 static inline Handler*
448 handler_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
471 static inline void
472 handler_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
484 static inline void
485 handler_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
511 static void
512 handler_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
547 static inline void
548 emission_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
565 static inline void
566 emission_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
580 static inline Emission*
581 emission_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
596 static gint
597 signal_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
608 void
609 g_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
633 void
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
656 void
657 g_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
696 static inline guint
697 signal_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
740 gboolean
741 g_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
770 guint
771 g_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
786 gchar*
787 g_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
800 void
801 g_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
825 guint*
826 g_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
862 guint
863 g_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
968 static void
969 signal_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
1010 guint
1011 g_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
1050 void
1051 g_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
1075 void
1076 g_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
1098 void
1099 g_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
1121 void
1122 g_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
1164 guint
1165 g_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
1195 static guint
1196 signal_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
1222 guint
1223 g_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
1248 guint
1249 g_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
1274 guint
1275 g_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
1300 gboolean
1301 g_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
1339 void
1340 g_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
1412 static void
1413 signal_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 }