fixed deadlock scenarion where g_signal_lookup() would be called with the
[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        "gsignal.h"
23
24 #include        "gbsearcharray.h"
25
26
27 /* pre allocation configurations
28  */
29 #define BSA_PRE_ALLOC           (20)
30 #define HANDLER_PRE_ALLOC       (48)
31 #define EMISSION_PRE_ALLOC      (16)
32
33 #define TIGHT_MEMORY    (1)
34
35 #define REPORT_BUG      "please report occourance circumstances to gtk-devel-list@gnome.org"
36
37
38 /* --- generic allocation --- */
39 /* we can special case allocations generically by replacing
40  * these functions with more speed/memory aware variants
41  */
42 static inline gpointer
43 g_generic_node_alloc (GTrashStack **trash_stack_p,
44                       guint         sizeof_node,
45                       guint         nodes_pre_alloc)
46 {
47   gpointer node = g_trash_stack_pop (trash_stack_p);
48   
49   if (!node)
50     {
51       guint8 *block;
52       
53       nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
54       block = g_malloc (sizeof_node * nodes_pre_alloc);
55       while (--nodes_pre_alloc)
56         {
57           g_trash_stack_push (trash_stack_p, block);
58           block += sizeof_node;
59         }
60       node = block;
61     }
62   
63   return node;
64 }
65 static inline void
66 g_generic_node_free (GTrashStack **trash_stack_p,
67                      gpointer      node)
68 {
69   g_trash_stack_push (trash_stack_p, node);
70 }
71
72
73 /* --- typedefs --- */
74 typedef struct _SignalNode  SignalNode;
75 typedef struct _SignalKey   SignalKey;
76 typedef struct _Emission    Emission;
77 typedef struct _Handler     Handler;
78 typedef struct _HandlerList HandlerList;
79 typedef enum
80 {
81   EMISSION_STOP,
82   EMISSION_RUN,
83   EMISSION_HOOK,
84   EMISSION_RESTART
85 } EmissionState;
86
87
88 /* --- prototypes --- */
89 static inline guint             signal_id_lookup      (GQuark           quark,
90                                                        GType            itype);
91 static        void              signal_destroy_R      (SignalNode      *signal_node);
92 static inline HandlerList*      handler_list_ensure   (guint            signal_id,
93                                                        gpointer         instance);
94 static inline HandlerList*      handler_list_lookup   (guint            signal_id,
95                                                        gpointer         instance);
96 static inline Handler*          handler_new           (gboolean         after);
97 static        void              handler_insert        (guint            signal_id,
98                                                        gpointer         instance,
99                                                        Handler         *handler);
100 static        Handler*          handler_lookup        (gpointer         instance,
101                                                        guint            handler_id,
102                                                        guint           *signal_id_p);
103 static        Handler*          handler_find          (gpointer         instance,
104                                                        GSignalMatchType mask,
105                                                        guint            signal_id,
106                                                        GClosure        *closure,
107                                                        gpointer         func,
108                                                        gpointer         data);
109 static inline void              handler_ref           (Handler         *handler);
110 static inline void              handler_unref_R       (guint            signal_id,
111                                                        gpointer         instance,
112                                                        Handler         *handler);
113 static inline void              emission_push         (Emission       **emission_list_p,
114                                                        guint            signal_id,
115                                                        gpointer         instance,
116                                                        EmissionState   *state_p);
117 static inline void              emission_pop          (Emission       **emission_list_p);
118 static inline Emission*         emission_find         (Emission        *emission_list,
119                                                        guint            signal_id,
120                                                        gpointer         instance);
121 static        void              signal_emit_R         (SignalNode      *node,
122                                                        gpointer         instance,
123                                                        GValue          *return_value,
124                                                        const GValue    *instance_and_params);
125
126
127 /* --- structures --- */
128 struct _SignalNode
129 {
130   /* permanent portion */
131   guint              signal_id;
132   GType              itype;
133   gchar             *name;
134   guint              destroyed : 1;
135   
136   /* reinitializable portion */
137   guint              flags : 8;
138   guint              n_params : 8;
139   GType             *param_types;
140   GType              return_type;
141   GClosure          *class_closure;
142   GSignalAccumulator accumulator;
143   GSignalCMarshaller c_marshaller;
144   GHookList         *emission_hooks;
145 };
146
147 struct _SignalKey
148 {
149   GType  itype;
150   GQuark quark;
151   guint  signal_id;
152 };
153
154 struct _Emission
155 {
156   Emission      *next;
157   guint          signal_id;
158   gpointer       instance;
159   EmissionState *state_p;
160 };
161
162 struct _HandlerList
163 {
164   guint    signal_id;
165   Handler *handlers;
166 };
167
168 struct _Handler
169 {
170   guint         id;
171   Handler      *next;
172   Handler      *prev;
173   guint         ref_count : 16;
174 #define HANDLER_MAX_REF_COUNT   (1 << 16)
175   guint         block_count : 12;
176 #define HANDLER_MAX_BLOCK_COUNT (1 << 12)
177   guint         after : 1;
178   GClosure     *closure;
179 };
180
181
182 /* --- variables --- */
183 static GBSearchArray  g_signal_key_bsa = { NULL, 0, 0, 0, NULL };
184 static GHashTable    *g_handler_list_bsa_ht = NULL;
185 static Emission      *g_recursive_emissions = NULL;
186 static Emission      *g_restart_emissions = NULL;
187 static GTrashStack   *g_bsa_ts = NULL;
188 static GTrashStack   *g_handler_ts = NULL;
189 static GTrashStack   *g_emission_ts = NULL;
190 G_LOCK_DEFINE_STATIC (g_signal_mutex);
191
192
193 /* --- signal nodes --- */
194 static guint          g_n_signal_nodes = 0;
195 static SignalNode   **g_signal_nodes = NULL;
196
197 static inline SignalNode*
198 LOOKUP_SIGNAL_NODE (register guint signal_id)
199 {
200   if (signal_id < g_n_signal_nodes)
201     return g_signal_nodes[signal_id];
202   else
203     return NULL;
204 }
205
206
207 /* --- functions --- */
208 static inline guint
209 signal_id_lookup (GQuark quark,
210                   GType  itype)
211 {
212   do
213     {
214       SignalKey key, *signal_key;
215       
216       key.itype = itype;
217       key.quark = quark;
218       
219       signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
220       
221       if (signal_key)
222         return signal_key->signal_id;
223       
224       itype = g_type_parent (itype);
225     }
226   while (itype);
227   
228   return 0;
229 }
230
231 static gint
232 handler_lists_cmp (gconstpointer node1,
233                    gconstpointer node2)
234 {
235   const HandlerList *hlist1 = node1, *hlist2 = node2;
236   
237   return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
238 }
239
240 static inline HandlerList*
241 handler_list_ensure (guint    signal_id,
242                      gpointer instance)
243 {
244   GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
245   HandlerList key;
246   
247   if (!hlbsa)
248     {
249       hlbsa = g_generic_node_alloc (&g_bsa_ts,
250                                     sizeof (GBSearchArray),
251                                     BSA_PRE_ALLOC);
252       hlbsa->cmp_func = handler_lists_cmp;
253       hlbsa->sizeof_node = sizeof (HandlerList);
254       hlbsa->flags = G_BSEARCH_DEFER_SHRINK;
255       hlbsa->n_nodes = 0;
256       hlbsa->nodes = NULL;
257       g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
258     }
259   key.signal_id = signal_id;
260   key.handlers = NULL;
261   
262   return g_bsearch_array_insert (hlbsa, &key, FALSE);
263 }
264
265 static inline HandlerList*
266 handler_list_lookup (guint    signal_id,
267                      gpointer instance)
268 {
269   GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
270   HandlerList key;
271   
272   key.signal_id = signal_id;
273   
274   return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL;
275 }
276
277 static Handler*
278 handler_lookup (gpointer instance,
279                 guint    handler_id,
280                 guint   *signal_id_p)
281 {
282   GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
283   
284   if (hlbsa)
285     {
286       guint i;
287       
288       for (i = 0; i < hlbsa->n_nodes; i++)
289         {
290           HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
291           Handler *handler;
292           
293           for (handler = hlist->handlers; handler; handler = handler->next)
294             if (handler->id == handler_id)
295               {
296                 if (signal_id_p)
297                   *signal_id_p = hlist->signal_id;
298                 
299                 return handler;
300               }
301         }
302     }
303   
304   return NULL;
305 }
306
307 static Handler*
308 handler_find (gpointer         instance,
309               GSignalMatchType mask,
310               guint            signal_id,
311               GClosure        *closure,
312               gpointer         func,
313               gpointer         data)
314 {
315   if (mask & G_SIGNAL_MATCH_ID)
316     {
317       HandlerList *hlist = handler_list_lookup (signal_id, instance);
318       Handler *handler;
319       SignalNode *node;
320       
321       if (mask & G_SIGNAL_MATCH_FUNC)
322         {
323           node = LOOKUP_SIGNAL_NODE (signal_id);
324           if (!node || !node->c_marshaller)
325             return NULL;
326         }
327           
328       mask = ~mask;
329       for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
330         if (((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
331             ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
332             ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
333             ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
334                                               handler->closure->meta_marshal == 0 &&
335                                               ((GCClosure*) handler->closure)->callback == func)))
336           return handler;
337     }
338   else
339     {
340       GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
341       
342       mask = ~mask;
343       if (hlbsa)
344         {
345           guint i;
346           
347           for (i = 0; i < hlbsa->n_nodes; i++)
348             {
349               HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
350               SignalNode *node;
351               Handler *handler;
352               
353               if (!(mask & G_SIGNAL_MATCH_FUNC))
354                 {
355                   node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
356                   if (!node->c_marshaller)
357                     continue;
358                 }
359
360               for (handler = hlist->handlers; handler; handler = handler->next)
361                 if (((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
362                     ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
363                     ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
364                     ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
365                                                       handler->closure->meta_marshal == 0 &&
366                                                       ((GCClosure*) handler->closure)->callback == func)))
367                   return handler;
368             }
369         }
370     }
371   
372   return NULL;
373 }
374
375 static inline Handler*
376 handler_new (gboolean after)
377 {
378   static guint handler_id = 1;
379   Handler *handler = g_generic_node_alloc (&g_handler_ts,
380                                            sizeof (Handler),
381                                            HANDLER_PRE_ALLOC);
382 #ifndef G_DISABLE_CHECKS
383   if (handler_id == 0)
384     g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
385 #endif
386   
387   handler->id = handler_id++;
388   handler->prev = NULL;
389   handler->next = NULL;
390   handler->ref_count = 1;
391   handler->block_count = 0;
392   handler->after = after != FALSE;
393   handler->closure = NULL;
394   
395   return handler;
396 }
397
398 static inline void
399 handler_ref (Handler *handler)
400 {
401   g_return_if_fail (handler->ref_count > 0);
402   
403 #ifndef G_DISABLE_CHECKS
404   if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
405     g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
406 #endif
407   
408   handler->ref_count += 1;
409 }
410
411 static inline void
412 handler_unref_R (guint    signal_id,
413                  gpointer instance,
414                  Handler *handler)
415 {
416   g_return_if_fail (handler->ref_count > 0);
417   
418   handler->ref_count -= 1;
419   if (!handler->ref_count)
420     {
421       if (handler->next)
422         handler->next->prev = handler->prev;
423       if (handler->prev)        /* watch out for g_signal_handlers_destroy()! */
424         handler->prev->next = handler->next;
425       else
426         {
427           HandlerList *hlist = handler_list_lookup (signal_id, instance);
428           
429           hlist->handlers = handler->next;
430         }
431       G_UNLOCK (g_signal_mutex);
432       g_closure_unref (handler->closure);
433       G_LOCK (g_signal_mutex);
434       g_generic_node_free (&g_handler_ts, handler);
435     }
436 }
437
438 static void
439 handler_insert (guint    signal_id,
440                 gpointer instance,
441                 Handler  *handler)
442 {
443   HandlerList *hlist;
444   
445   g_assert (handler->prev == NULL && handler->next == NULL); // FIXME: paranoid
446   
447   hlist = handler_list_ensure (signal_id, instance);
448   if (!hlist->handlers)
449     hlist->handlers = handler;
450   else if (hlist->handlers->after && !handler->after)
451     {
452       handler->next = hlist->handlers;
453       hlist->handlers->prev = handler;
454       hlist->handlers = handler;
455     }
456   else
457     {
458       Handler *tmp = hlist->handlers;
459       
460       if (handler->after)
461         while (tmp->next)
462           tmp = tmp->next;
463       else
464         while (tmp->next && !tmp->next->after)
465           tmp = tmp->next;
466       if (tmp->next)
467         tmp->next->prev = handler;
468       handler->next = tmp->next;
469       handler->prev = tmp;
470       tmp->next = handler;
471     }
472 }
473
474 static inline void
475 emission_push (Emission     **emission_list_p,
476                guint          signal_id,
477                gpointer       instance,
478                EmissionState *state_p)
479 {
480   Emission *emission = g_generic_node_alloc (&g_emission_ts,
481                                              sizeof (Emission),
482                                              EMISSION_PRE_ALLOC);
483   emission->next = *emission_list_p;
484   emission->signal_id = signal_id;
485   emission->instance = instance;
486   emission->state_p = state_p;
487   *emission_list_p = emission;
488 }
489
490 static inline void
491 emission_pop (Emission **emission_list_p)
492 {
493   Emission *emission = *emission_list_p;
494   
495   *emission_list_p = emission->next;
496   g_generic_node_free (&g_emission_ts, emission);
497 }
498
499 static inline Emission*
500 emission_find (Emission *emission_list,
501                guint     signal_id,
502                gpointer  instance)
503 {
504   Emission *emission;
505   
506   for (emission = emission_list; emission; emission = emission->next)
507     if (emission->instance == instance && emission->signal_id == signal_id)
508       return emission;
509   return NULL;
510 }
511
512 static gint
513 signal_key_cmp (gconstpointer node1,
514                 gconstpointer node2)
515 {
516   const SignalKey *key1 = node1, *key2 = node2;
517   
518   if (key1->itype == key2->itype)
519     return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
520   else
521     return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
522 }
523
524 void
525 g_signal_init (void) /* sync with gtype.c */
526 {
527   G_LOCK (g_signal_mutex);
528   if (!g_n_signal_nodes)
529     {
530       /* setup signal key array */
531       g_signal_key_bsa.cmp_func = signal_key_cmp;
532       g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
533       g_signal_key_bsa.flags = 0; /* alloc-only */
534       
535       /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
536       g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
537       
538       /* invalid (0) signal_id */
539       g_n_signal_nodes = 1;
540       g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
541       g_signal_nodes[0] = NULL;
542     }
543   G_UNLOCK (g_signal_mutex);
544 }
545
546 void
547 g_signals_destroy (GType itype)
548 {
549   guint i;
550   gboolean found_one = FALSE;
551   
552   G_LOCK (g_signal_mutex);
553   for (i = 0; i < g_n_signal_nodes; i++)
554     {
555       SignalNode *node = g_signal_nodes[i];
556       
557       if (node->itype == itype)
558         {
559           if (node->destroyed)
560             g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
561                        node->name,
562                        g_type_name (node->itype));
563           else
564             {
565               found_one = TRUE;
566               signal_destroy_R (node);
567             }
568         }
569     }
570   if (!found_one)
571     g_warning (G_STRLOC ": type `%s' has no signals that could be destroyed",
572                g_type_name (itype));
573   G_UNLOCK (g_signal_mutex);
574 }
575
576 void
577 g_signal_stop_emission (gpointer instance,
578                         guint    signal_id)
579 {
580   SignalNode *node;
581   
582   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
583   g_return_if_fail (signal_id > 0);
584   
585   G_LOCK (g_signal_mutex);
586   node = LOOKUP_SIGNAL_NODE (signal_id);
587   if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
588     {
589       Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
590       Emission *emission = emission_find (emission_list, signal_id, instance);
591       
592       if (emission)
593         {
594           if (*emission->state_p == EMISSION_HOOK)
595             g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
596                        node->name, instance);
597           else if (*emission->state_p == EMISSION_RUN)
598             *emission->state_p = EMISSION_STOP;
599         }
600       else
601         g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
602                    node->name, instance);
603     }
604   else
605     g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
606   G_UNLOCK (g_signal_mutex);
607 }
608
609 guint
610 g_signal_lookup (const gchar *name,
611                  GType        itype)
612 {
613   guint signal_id;
614   
615   g_return_val_if_fail (name != NULL, 0);
616   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
617   
618   G_LOCK (g_signal_mutex);
619   signal_id = signal_id_lookup (g_quark_try_string (name), itype);
620   G_UNLOCK (g_signal_mutex);
621   
622   return signal_id;
623 }
624
625 gchar*
626 g_signal_name (guint signal_id)
627 {
628   SignalNode *node;
629   gchar *name;
630
631   G_LOCK (g_signal_mutex);
632   node = LOOKUP_SIGNAL_NODE (signal_id);
633   name = node ? node->name : NULL;
634   G_UNLOCK (g_signal_mutex);
635   
636   return name;
637 }
638
639 void
640 g_signal_query (guint         signal_id,
641                 GSignalQuery *query)
642 {
643   SignalNode *node;
644
645   g_return_if_fail (query != NULL);
646
647   G_LOCK (g_signal_mutex);
648   node = LOOKUP_SIGNAL_NODE (signal_id);
649   if (!node || node->destroyed)
650     query->signal_id = 0;
651   else
652     {
653       query->signal_id = node->signal_id;
654       query->signal_name = node->name;
655       query->itype = node->itype;
656       query->signal_flags = node->flags;
657       query->return_type = node->return_type;
658       query->n_params = node->n_params;
659       query->param_types = node->param_types;
660     }
661   G_UNLOCK (g_signal_mutex);
662 }
663
664 guint
665 g_signal_newv (const gchar       *signal_name,
666                GType              itype,
667                GSignalType        signal_flags,
668                GClosure          *class_closure,
669                GSignalAccumulator accumulator,
670                GSignalCMarshaller c_marshaller,
671                GType              return_type,
672                guint              n_params,
673                GType             *param_types)
674 {
675   gchar *name;
676   guint signal_id, i;
677   SignalNode *node;
678   
679   g_return_val_if_fail (signal_name != NULL, 0);
680   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
681   if (n_params)
682     g_return_val_if_fail (param_types != NULL, 0);
683   if (return_type != G_TYPE_NONE)
684     g_return_val_if_fail (accumulator == NULL, 0);
685   
686   name = g_strdup (signal_name);
687   g_strdelimit (name, G_STR_DELIMITERS ":^", '_');  // FIXME do character checks like for types
688   
689   G_LOCK (g_signal_mutex);
690   
691   signal_id = signal_id_lookup (g_quark_try_string (name), itype);
692   node = LOOKUP_SIGNAL_NODE (signal_id);
693   if (node && !node->destroyed)
694     {
695       g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
696                  name,
697                  g_type_name (node->itype),
698                  G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
699       g_free (name);
700       G_UNLOCK (g_signal_mutex);
701       return 0;
702     }
703   if (node && node->itype != itype)
704     {
705       g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
706                  name,
707                  g_type_name (itype),
708                  g_type_name (node->itype));
709       g_free (name);
710       G_UNLOCK (g_signal_mutex);
711       return 0;
712     }
713   for (i = 0; i < n_params; i++)
714     if (!G_TYPE_IS_VALUE (param_types[i]) ||
715         param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */
716       {
717         g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
718                    i + 1, g_type_name (param_types[i]), g_type_name (itype), name);
719         g_free (name);
720         G_UNLOCK (g_signal_mutex);
721         return 0;
722       }
723   if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type))
724     {
725       g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
726                  g_type_name (param_types[i]), g_type_name (itype), name);
727       g_free (name);
728       G_UNLOCK (g_signal_mutex);
729       return 0;
730     }
731   
732   /* setup permanent portion of signal node */
733   if (!node)
734     {
735       SignalKey key;
736       
737       signal_id = g_n_signal_nodes++;
738       node = g_new (SignalNode, 1);
739       node->signal_id = signal_id;
740       g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
741       g_signal_nodes[signal_id] = node;
742       node->itype = itype;
743       node->name = name;
744       key.itype = itype;
745       key.quark = g_quark_from_string (node->name);
746       key.signal_id = signal_id;
747       g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
748       g_strdelimit (node->name, "_", '-');
749       key.quark = g_quark_from_static_string (node->name);
750       g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
751     }
752   node->destroyed = FALSE;
753   
754   /* setup reinitializable portion */
755   node->flags = signal_flags & (G_SIGNAL_RUN_FIRST |
756                                 G_SIGNAL_RUN_LAST |
757                                 G_SIGNAL_RUN_CLEANUP |
758                                 G_SIGNAL_NO_RECURSE |
759                                 G_SIGNAL_ACTION |
760                                 G_SIGNAL_NO_HOOKS);
761   node->n_params = n_params;
762   node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
763   node->return_type = return_type;
764   node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL;
765   node->accumulator = accumulator;
766   node->c_marshaller = c_marshaller;
767   node->emission_hooks = NULL;
768   if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure))
769     g_closure_set_marshal (class_closure, node->c_marshaller);
770   
771   G_UNLOCK (g_signal_mutex);
772   return signal_id;
773 }
774
775 static void
776 signal_destroy_R (SignalNode *signal_node)
777 {
778   SignalNode node = *signal_node;
779   
780   signal_node->destroyed = TRUE;
781   
782   /* reentrancy caution, zero out real contents first */
783   signal_node->n_params = 0;
784   signal_node->param_types = NULL;
785   signal_node->return_type = 0;
786   signal_node->class_closure = NULL;
787   signal_node->accumulator = NULL;
788   signal_node->c_marshaller = NULL;
789   signal_node->emission_hooks = NULL;
790   
791 #ifndef G_DISABLE_CHECKS
792   /* check current emissions */
793   {
794     Emission *emission;
795     
796     for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
797          emission; emission = emission->next)
798       if (emission->signal_id == node.signal_id)
799         g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
800                     node.name, emission->instance);
801   }
802 #endif
803   
804   /* free contents that need to
805    */
806   G_UNLOCK (g_signal_mutex);
807   g_free (node.param_types);
808   g_closure_unref (node.class_closure);
809   if (node.emission_hooks)
810     {
811       g_hook_list_clear (node.emission_hooks);
812       g_free (node.emission_hooks);
813     }
814   G_LOCK (g_signal_mutex);
815 }
816
817 guint
818 g_signal_connect_closure (gpointer  instance,
819                           guint     signal_id,
820                           GClosure *closure,
821                           gboolean  after)
822 {
823   SignalNode *node;
824   guint handler_id = 0;
825   
826   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
827   g_return_val_if_fail (signal_id > 0, 0);
828   g_return_val_if_fail (closure != NULL, 0);
829   
830   G_LOCK (g_signal_mutex);
831   node = LOOKUP_SIGNAL_NODE (signal_id);
832   if (node && g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
833     {
834       Handler *handler = handler_new (after);
835       
836       handler_id = handler->id;
837       handler->closure = g_closure_ref (closure);
838       handler_insert (signal_id, instance, handler);
839       if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
840         g_closure_set_marshal (closure, node->c_marshaller);
841     }
842   else
843     g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
844   G_UNLOCK (g_signal_mutex);
845   
846   return handler_id;
847 }
848
849 void
850 g_signal_handler_disconnect (gpointer instance,
851                              guint    handler_id)
852 {
853   Handler *handler;
854   guint signal_id;
855   
856   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
857   g_return_if_fail (handler_id > 0);
858   
859   G_LOCK (g_signal_mutex);
860   handler = handler_lookup (instance, handler_id, &signal_id);
861   if (handler)
862     {
863       handler->id = 0;
864       handler->block_count = 1;
865       handler_unref_R (signal_id, instance, handler);
866     }
867   else
868     g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
869   G_UNLOCK (g_signal_mutex);
870 }
871
872 void
873 g_signal_handlers_destroy (gpointer instance)
874 {
875   GBSearchArray *hlbsa;
876   
877   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
878   
879   G_LOCK (g_signal_mutex);
880   hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
881   if (hlbsa)
882     {
883       guint i;
884       
885       /* reentrancy caution, delete instance trace first */
886       g_hash_table_remove (g_handler_list_bsa_ht, instance);
887
888       for (i = 0; i < hlbsa->n_nodes; i++)
889         {
890           HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
891           Handler *handler = hlist->handlers;
892           
893           while (handler)
894             {
895               Handler *tmp = handler;
896               
897               handler = tmp->next;
898               tmp->block_count = 1;
899               /* cruel unlink, this works because _all_ handlers vanish */
900               tmp->next = NULL;
901               tmp->prev = tmp;
902               if (tmp->id)
903                 {
904                   tmp->id = 0;
905                   handler_unref_R (0, NULL, tmp);
906                 }
907             }
908         }
909       g_free (hlbsa->nodes);
910       g_generic_node_free (&g_bsa_ts, hlbsa);
911     }
912   G_UNLOCK (g_signal_mutex);
913 }
914
915 void
916 g_signal_handler_block (gpointer instance,
917                         guint    handler_id)
918 {
919   Handler *handler;
920   
921   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
922   g_return_if_fail (handler_id > 0);
923   
924   G_LOCK (g_signal_mutex);
925   handler = handler_lookup (instance, handler_id, NULL);
926   if (handler)
927     {
928 #ifndef G_DISABLE_CHECKS
929       if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
930         g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
931 #endif
932       
933       handler->block_count += 1;
934     }
935   else
936     g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
937   G_UNLOCK (g_signal_mutex);
938 }
939
940 void
941 g_signal_handler_unblock (gpointer instance,
942                           guint    handler_id)
943 {
944   Handler *handler;
945   
946   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
947   g_return_if_fail (handler_id > 0);
948   
949   G_LOCK (g_signal_mutex);
950   handler = handler_lookup (instance, handler_id, NULL);
951   if (handler)
952     {
953       if (handler->block_count)
954         handler->block_count -= 1;
955       else
956         g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance);
957     }
958   else
959     g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
960   G_UNLOCK (g_signal_mutex);
961 }
962
963 guint
964 g_signal_handler_find (gpointer         instance,
965                        GSignalMatchType mask,
966                        guint            signal_id,
967                        GClosure        *closure,
968                        gpointer         func,
969                        gpointer         data)
970 {
971   Handler *handler = NULL;
972   guint handler_id;
973   
974   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
975   
976   G_LOCK (g_signal_mutex);
977   handler = handler_find (instance, mask, signal_id, closure, func, data);
978   handler_id = handler ? handler->id : 0;
979   G_UNLOCK (g_signal_mutex);
980   
981   return handler_id;
982 }
983
984 gboolean
985 g_signal_handler_pending (gpointer instance,
986                           guint    signal_id,
987                           gboolean may_be_blocked)
988 {
989   Handler *handler = NULL;
990   
991   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
992   g_return_val_if_fail (signal_id > 0, FALSE);
993   
994   G_LOCK (g_signal_mutex);
995   handler = handler_find (instance, G_SIGNAL_MATCH_ID, signal_id, NULL, NULL, NULL);
996   if (!may_be_blocked)
997     for (; handler; handler = handler->next)
998       if (!handler->block_count)
999         break;
1000   G_UNLOCK (g_signal_mutex);
1001   
1002   return handler != NULL;
1003 }
1004
1005 void
1006 g_signal_emitv (const GValue *instance_and_params,
1007                 guint         signal_id,
1008                 GValue       *return_value)
1009 {
1010   SignalNode *node;
1011   gpointer instance;
1012   const GValue *param_values;
1013   guint i;
1014   
1015   g_return_if_fail (instance_and_params != NULL);
1016   instance = g_value_get_as_pointer (instance_and_params);
1017   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1018   g_return_if_fail (signal_id > 0);
1019
1020   param_values = instance_and_params + 1;
1021   
1022   G_LOCK (g_signal_mutex);
1023   node = LOOKUP_SIGNAL_NODE (signal_id);
1024 #ifndef G_DISABLE_CHECKS
1025   if (!node || !g_type_conforms_to (G_TYPE_FROM_INSTANCE (instance), node->itype))
1026     g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1027   for (i = 0; i < node->n_params; i++)
1028     if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
1029       {
1030         g_critical (G_STRLOC ": value for `%s' parameter %u for signal \"%s\" is of type `%s'",
1031                     g_type_name (node->param_types[i]),
1032                     i,
1033                     node->name,
1034                     G_VALUE_TYPE_NAME (param_values + i));
1035         G_UNLOCK (g_signal_mutex);
1036         return;
1037       }
1038   if (node->return_type != G_TYPE_NONE)
1039     {
1040       if (!return_value)
1041         {
1042           g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is (NULL)",
1043                       g_type_name (node->return_type),
1044                       node->name);
1045           G_UNLOCK (g_signal_mutex);
1046           return;
1047         }
1048       else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
1049         {
1050           g_critical (G_STRLOC ": return value `%s' for signal \"%s\" is of type `%s'",
1051                       g_type_name (node->return_type),
1052                       node->name,
1053                       G_VALUE_TYPE_NAME (return_value));
1054           G_UNLOCK (g_signal_mutex);
1055           return;
1056         }
1057     }
1058   else
1059     return_value = NULL;
1060 #endif  /* !G_DISABLE_CHECKS */
1061   
1062   signal_emit_R (node, instance, return_value, instance_and_params);
1063   
1064   G_UNLOCK (g_signal_mutex);
1065 }
1066
1067 static void
1068 signal_emit_R (SignalNode   *node,
1069                gpointer      instance,
1070                GValue       *return_value,
1071                const GValue *instance_and_params)
1072 {
1073   EmissionState emission_state = 0;
1074   GSignalAccumulator accumulator;
1075   GClosure *class_closure;
1076   HandlerList *hlist;
1077   Handler *handlers;
1078   GValue accu;
1079   gboolean accu_used = FALSE;
1080   guint signal_id = node->signal_id;
1081   
1082   if (node->flags & G_SIGNAL_NO_RECURSE)
1083     {
1084       Emission *emission = emission_find (g_restart_emissions, signal_id, instance);
1085       
1086       if (emission)
1087         {
1088           *emission->state_p = EMISSION_RESTART;
1089           return;
1090         }
1091     }
1092   accumulator = node->accumulator;
1093   if (accumulator)
1094     {
1095       G_UNLOCK (g_signal_mutex);
1096       g_value_init (&accu, node->return_type);
1097       G_LOCK (g_signal_mutex);
1098     }
1099   emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
1100                  signal_id, instance, &emission_state);
1101   class_closure = node->class_closure;
1102   hlist = handler_list_lookup (signal_id, instance);
1103   handlers = hlist ? hlist->handlers : NULL;
1104   if (handlers)
1105     handler_ref (handlers);
1106   
1107  EMIT_RESTART:
1108   
1109   if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
1110     {
1111       emission_state = EMISSION_RUN;
1112       
1113       G_UNLOCK (g_signal_mutex);
1114       if (accumulator)
1115         {
1116           if (accu_used)
1117             g_value_reset (&accu);
1118           g_closure_invoke (class_closure,
1119                             (signal_id << 8) | G_SIGNAL_RUN_FIRST,
1120                             &accu,
1121                             node->n_params + 1,
1122                             instance_and_params);
1123           if (!accumulator (signal_id, return_value, &accu) &&
1124               emission_state == EMISSION_RUN)
1125             emission_state = EMISSION_STOP;
1126           accu_used = TRUE;
1127         }
1128       else
1129         g_closure_invoke (class_closure,
1130                           (signal_id << 8) | G_SIGNAL_RUN_FIRST,
1131                           return_value,
1132                           node->n_params + 1,
1133                           instance_and_params);
1134       G_LOCK (g_signal_mutex);
1135       
1136       if (emission_state == EMISSION_STOP)
1137         goto EMIT_CLEANUP;
1138       else if (emission_state == EMISSION_RESTART)
1139         goto EMIT_RESTART;
1140     }
1141   
1142   if (node->emission_hooks)
1143     {
1144       emission_state = EMISSION_HOOK;
1145       
1146       G_UNLOCK (g_signal_mutex);
1147       g_print ("emission_hooks()\n");
1148       G_LOCK (g_signal_mutex);
1149       
1150       if (emission_state == EMISSION_RESTART)
1151         goto EMIT_RESTART;
1152     }
1153   
1154   if (handlers)
1155     {
1156       Handler *handler = handlers;
1157       
1158       emission_state = EMISSION_RUN;
1159       
1160       handler_ref (handler);
1161       do
1162         {
1163           Handler *tmp;
1164           
1165           if (!handler->after && !handler->block_count)
1166             {
1167               G_UNLOCK (g_signal_mutex);
1168               if (accumulator)
1169                 {
1170                   if (accu_used)
1171                     g_value_reset (&accu);
1172                   g_closure_invoke (handler->closure,
1173                                     (signal_id << 8) | G_SIGNAL_RUN_FIRST,
1174                                     &accu,
1175                                     node->n_params + 1,
1176                                     instance_and_params);
1177                   if (!accumulator (signal_id, return_value, &accu) &&
1178                       emission_state == EMISSION_RUN)
1179                     emission_state = EMISSION_STOP;
1180                   accu_used = TRUE;
1181                 }
1182               else
1183                 g_closure_invoke (handler->closure,
1184                                   (signal_id << 8) | G_SIGNAL_RUN_FIRST,
1185                                   return_value,
1186                                   node->n_params + 1,
1187                                   instance_and_params);
1188               G_LOCK (g_signal_mutex);
1189               
1190               tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1191             }
1192           else
1193             tmp = handler->next;
1194           
1195           if (tmp)
1196             handler_ref (tmp);
1197           handler_unref_R (signal_id, instance, handler);
1198           handler = tmp;
1199         }
1200       while (handler);
1201       
1202       if (emission_state == EMISSION_STOP)
1203         goto EMIT_CLEANUP;
1204       else if (emission_state == EMISSION_RESTART)
1205         goto EMIT_RESTART;
1206     }
1207   
1208   if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
1209     {
1210       emission_state = EMISSION_RUN;
1211       
1212       G_UNLOCK (g_signal_mutex);
1213       if (accumulator)
1214         {
1215           if (accu_used)
1216             g_value_reset (&accu);
1217           g_closure_invoke (class_closure,
1218                             (signal_id << 8) | G_SIGNAL_RUN_LAST,
1219                             &accu,
1220                             node->n_params + 1,
1221                             instance_and_params);
1222           if (!accumulator (signal_id, return_value, &accu) &&
1223               emission_state == EMISSION_RUN)
1224             emission_state = EMISSION_STOP;
1225           accu_used = TRUE;
1226         }
1227       else
1228         g_closure_invoke (class_closure,
1229                           (signal_id << 8) | G_SIGNAL_RUN_LAST,
1230                           return_value,
1231                           node->n_params + 1,
1232                           instance_and_params);
1233       G_LOCK (g_signal_mutex);
1234       
1235       if (emission_state == EMISSION_STOP)
1236         goto EMIT_CLEANUP;
1237       else if (emission_state == EMISSION_RESTART)
1238         goto EMIT_RESTART;
1239     }
1240   
1241   if (handlers)
1242     {
1243       Handler *handler = handlers;
1244       
1245       emission_state = EMISSION_RUN;
1246       
1247       handler_ref (handler);
1248       do
1249         {
1250           Handler *tmp;
1251           
1252           if (handler->after && !handler->block_count)
1253             {
1254               G_UNLOCK (g_signal_mutex);
1255               if (accumulator)
1256                 {
1257                   if (accu_used)
1258                     g_value_reset (&accu);
1259                   g_closure_invoke (handler->closure,
1260                                     (signal_id << 8) | G_SIGNAL_RUN_LAST,
1261                                     &accu,
1262                                     node->n_params + 1,
1263                                     instance_and_params);
1264                   if (!accumulator (signal_id, return_value, &accu) &&
1265                       emission_state == EMISSION_RUN)
1266                     emission_state = EMISSION_STOP;
1267                   accu_used = TRUE;
1268                 }
1269               else
1270                 g_closure_invoke (handler->closure,
1271                                   (signal_id << 8) | G_SIGNAL_RUN_LAST,
1272                                   return_value,
1273                                   node->n_params + 1,
1274                                   instance_and_params);
1275               G_LOCK (g_signal_mutex);
1276               
1277               tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1278             }
1279           else
1280             tmp = handler->next;
1281           
1282           if (tmp)
1283             handler_ref (tmp);
1284           handler_unref_R (signal_id, instance, handler);
1285           handler = tmp;
1286         }
1287       while (handler);
1288       
1289       if (emission_state == EMISSION_STOP)
1290         goto EMIT_CLEANUP;
1291       else if (emission_state == EMISSION_RESTART)
1292         goto EMIT_RESTART;
1293     }
1294   
1295  EMIT_CLEANUP:
1296   
1297   if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
1298     {
1299       emission_state = EMISSION_STOP;
1300       
1301       G_UNLOCK (g_signal_mutex);
1302       if (node->return_type != G_TYPE_NONE)
1303         {
1304           if (!accumulator)
1305             g_value_init (&accu, node->return_type);
1306           else if (accu_used)
1307             g_value_reset (&accu);
1308           accu_used = TRUE;
1309         }
1310       g_closure_invoke (class_closure,
1311                         (signal_id << 8) | G_SIGNAL_RUN_CLEANUP,
1312                         node->return_type != G_TYPE_NONE ? &accu : NULL,
1313                         node->n_params + 1,
1314                         instance_and_params);
1315       if (node->return_type != G_TYPE_NONE && !accumulator)
1316         g_value_unset (&accu);
1317       G_LOCK (g_signal_mutex);
1318
1319       if (emission_state == EMISSION_RESTART)
1320         goto EMIT_RESTART;
1321     }
1322   
1323   if (handlers)
1324     handler_unref_R (signal_id, instance, handlers);
1325   
1326   emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions);
1327   if (accumulator)
1328     {
1329       G_UNLOCK (g_signal_mutex);
1330       g_value_unset (&accu);
1331       G_LOCK (g_signal_mutex);
1332     }
1333 }