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