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