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