adapt to work with new CVS gtk-doc, leaving the old rules in place caused
[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
23 /*
24  * MT safe
25  */
26
27 #include        "gsignal.h"
28 #include        "gbsearcharray.h"
29 #include        "gvaluecollector.h"
30 #include        <string.h> 
31
32
33 /* pre allocation configurations
34  */
35 #define MAX_STACK_VALUES        (16)
36 #define BSA_PRE_ALLOC           (20)
37 #define HANDLER_PRE_ALLOC       (48)
38 #define EMISSION_PRE_ALLOC      (16)
39
40 #define REPORT_BUG      "please report occourance circumstances to gtk-devel-list@gnome.org"
41
42
43 /* --- generic allocation --- */
44 /* we special case allocations generically by replacing
45  * these functions with more speed/memory aware variants
46  */
47 #ifndef DISABLE_MEM_POOLS
48 static inline gpointer
49 g_generic_node_alloc (GTrashStack **trash_stack_p,
50                       guint         sizeof_node,
51                       guint         nodes_pre_alloc)
52 {
53   gpointer node = g_trash_stack_pop (trash_stack_p);
54   
55   if (!node)
56     {
57       guint8 *block;
58       
59       nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
60       block = g_malloc (sizeof_node * nodes_pre_alloc);
61       while (--nodes_pre_alloc)
62         {
63           g_trash_stack_push (trash_stack_p, block);
64           block += sizeof_node;
65         }
66       node = block;
67     }
68   
69   return node;
70 }
71 #define g_generic_node_free(trash_stack_p, node) g_trash_stack_push (trash_stack_p, node)
72 #else   /* !DISABLE_MEM_POOLS */
73 #define g_generic_node_alloc(t,sizeof_node,p)    g_malloc (sizeof_node)
74 #define g_generic_node_free(t,node)              g_free (node)
75 #endif  /* !DISABLE_MEM_POOLS */
76
77
78 /* --- typedefs --- */
79 typedef struct _SignalNode   SignalNode;
80 typedef struct _SignalKey    SignalKey;
81 typedef struct _Emission     Emission;
82 typedef struct _Handler      Handler;
83 typedef struct _HandlerList  HandlerList;
84 typedef struct _HandlerMatch HandlerMatch;
85 typedef enum
86 {
87   EMISSION_STOP,
88   EMISSION_RUN,
89   EMISSION_HOOK,
90   EMISSION_RESTART
91 } EmissionState;
92
93
94 /* --- prototypes --- */
95 static inline guint             signal_id_lookup        (GQuark           quark,
96                                                          GType            itype);
97 static        void              signal_destroy_R        (SignalNode      *signal_node);
98 static inline HandlerList*      handler_list_ensure     (guint            signal_id,
99                                                          gpointer         instance);
100 static inline HandlerList*      handler_list_lookup     (guint            signal_id,
101                                                          gpointer         instance);
102 static inline Handler*          handler_new             (gboolean         after);
103 static        void              handler_insert          (guint            signal_id,
104                                                          gpointer         instance,
105                                                          Handler         *handler);
106 static        Handler*          handler_lookup          (gpointer         instance,
107                                                          guint            handler_id,
108                                                          guint           *signal_id_p);
109 static inline HandlerMatch*     handler_match_prepend   (HandlerMatch    *list,
110                                                          Handler         *handler,
111                                                          guint            signal_id);
112 static inline HandlerMatch*     handler_match_free1_R   (HandlerMatch    *node,
113                                                          gpointer         instance);
114 static        HandlerMatch*     handlers_find           (gpointer         instance,
115                                                          GSignalMatchType mask,
116                                                          guint            signal_id,
117                                                          GQuark           detail,
118                                                          GClosure        *closure,
119                                                          gpointer         func,
120                                                          gpointer         data,
121                                                          gboolean         one_and_only);
122 static inline void              handler_ref             (Handler         *handler);
123 static inline void              handler_unref_R         (guint            signal_id,
124                                                          gpointer         instance,
125                                                          Handler         *handler);
126 static inline void              emission_push           (Emission       **emission_list_p,
127                                                          guint            signal_id,
128                                                          GQuark           detail,
129                                                          gpointer         instance,
130                                                          EmissionState   *state_p);
131 static inline void              emission_pop            (Emission       **emission_list_p,
132                                                          EmissionState   *state_p);
133 static inline Emission*         emission_find           (Emission        *emission_list,
134                                                          guint            signal_id,
135                                                          GQuark           detail,
136                                                          gpointer         instance);
137 static        gboolean          signal_emit_R           (SignalNode      *node,
138                                                          GQuark           detail,
139                                                          gpointer         instance,
140                                                          GValue          *return_value,
141                                                          const GValue    *instance_and_params);
142
143
144 /* --- structures --- */
145 struct _SignalNode
146 {
147   /* permanent portion */
148   guint              signal_id;
149   GType              itype;
150   gchar             *name;
151   guint              destroyed : 1;
152   
153   /* reinitializable portion */
154   guint              flags : 8;
155   guint              n_params : 8;
156   GType             *param_types;
157   GType              return_type;
158   GClosure          *class_closure;
159   GSignalAccumulator accumulator;
160   GSignalCMarshaller c_marshaller;
161   GHookList         *emission_hooks;
162 };
163
164 struct _SignalKey
165 {
166   GType  itype;
167   GQuark quark;
168   guint  signal_id;
169 };
170
171 struct _Emission
172 {
173   Emission      *next;
174   guint          signal_id;
175   GQuark         detail;
176   gpointer       instance;
177   EmissionState *state_p;
178 };
179
180 struct _HandlerList
181 {
182   guint    signal_id;
183   Handler *handlers;
184 };
185 struct _Handler
186 {
187   guint         id;
188   Handler      *next;
189   Handler      *prev;
190   GQuark        detail;
191   guint         ref_count : 16;
192 #define HANDLER_MAX_REF_COUNT   (1 << 16)
193   guint         block_count : 12;
194 #define HANDLER_MAX_BLOCK_COUNT (1 << 12)
195   guint         after : 1;
196   GClosure     *closure;
197 };
198 struct _HandlerMatch
199 {
200   Handler      *handler;
201   HandlerMatch *next;
202   union {
203     guint       signal_id;
204     gpointer    dummy;
205   } d;
206 };
207
208
209 /* --- variables --- */
210 static GBSearchArray  g_signal_key_bsa = { NULL, 0, 0, 0, NULL };
211 static GHashTable    *g_handler_list_bsa_ht = NULL;
212 static Emission      *g_recursive_emissions = NULL;
213 static Emission      *g_restart_emissions = NULL;
214 static GTrashStack   *g_bsa_ts = NULL;
215 static GTrashStack   *g_handler_ts = NULL;
216 static GTrashStack   *g_emission_ts = NULL;
217 G_LOCK_DEFINE_STATIC (g_signal_mutex);
218
219
220 /* --- signal nodes --- */
221 static guint          g_n_signal_nodes = 0;
222 static SignalNode   **g_signal_nodes = NULL;
223
224 static inline SignalNode*
225 LOOKUP_SIGNAL_NODE (register guint signal_id)
226 {
227   if (signal_id < g_n_signal_nodes)
228     return g_signal_nodes[signal_id];
229   else
230     return NULL;
231 }
232
233
234 /* --- functions --- */
235 static inline guint
236 signal_id_lookup (GQuark quark,
237                   GType  itype)
238 {
239   GType *ifaces, type = itype;
240   SignalKey key;
241   guint n_ifaces;
242
243   key.quark = quark;
244
245   /* try looking up signals for this type and its anchestors */
246   do
247     {
248       SignalKey *signal_key;
249       
250       key.itype = type;
251       signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
252       
253       if (signal_key)
254         return signal_key->signal_id;
255       
256       type = g_type_parent (type);
257     }
258   while (type);
259
260   /* no luck, try interfaces it exports */
261   ifaces = g_type_interfaces (itype, &n_ifaces);
262   while (n_ifaces--)
263     {
264       SignalKey *signal_key;
265
266       key.itype = ifaces[n_ifaces];
267       signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
268
269       if (signal_key)
270         {
271           g_free (ifaces);
272           return signal_key->signal_id;
273         }
274     }
275   g_free (ifaces);
276   
277   return 0;
278 }
279
280 static gint
281 handler_lists_cmp (gconstpointer node1,
282                    gconstpointer node2)
283 {
284   const HandlerList *hlist1 = node1, *hlist2 = node2;
285   
286   return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
287 }
288
289 static inline HandlerList*
290 handler_list_ensure (guint    signal_id,
291                      gpointer instance)
292 {
293   GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
294   HandlerList key;
295   
296   if (!hlbsa)
297     {
298       hlbsa = g_generic_node_alloc (&g_bsa_ts,
299                                     sizeof (GBSearchArray),
300                                     BSA_PRE_ALLOC);
301       hlbsa->cmp_func = handler_lists_cmp;
302       hlbsa->sizeof_node = sizeof (HandlerList);
303       hlbsa->flags = G_BSEARCH_DEFER_SHRINK;
304       hlbsa->n_nodes = 0;
305       hlbsa->nodes = NULL;
306       g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
307     }
308   key.signal_id = signal_id;
309   key.handlers = NULL;
310   
311   return g_bsearch_array_insert (hlbsa, &key, FALSE);
312 }
313
314 static inline HandlerList*
315 handler_list_lookup (guint    signal_id,
316                      gpointer instance)
317 {
318   GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
319   HandlerList key;
320   
321   key.signal_id = signal_id;
322   
323   return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL;
324 }
325
326 static Handler*
327 handler_lookup (gpointer instance,
328                 guint    handler_id,
329                 guint   *signal_id_p)
330 {
331   GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
332   
333   if (hlbsa)
334     {
335       guint i;
336       
337       for (i = 0; i < hlbsa->n_nodes; i++)
338         {
339           HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
340           Handler *handler;
341           
342           for (handler = hlist->handlers; handler; handler = handler->next)
343             if (handler->id == handler_id)
344               {
345                 if (signal_id_p)
346                   *signal_id_p = hlist->signal_id;
347                 
348                 return handler;
349               }
350         }
351     }
352   
353   return NULL;
354 }
355
356 static inline HandlerMatch*
357 handler_match_prepend (HandlerMatch *list,
358                        Handler      *handler,
359                        guint         signal_id)
360 {
361   HandlerMatch *node;
362   
363   /* yeah, we could use our own memchunk here, introducing yet more
364    * rarely used cached nodes and extra allocation overhead.
365    * instead, we use GList* nodes, since they are exactly the size
366    * we need and are already cached. g_signal_init() asserts this.
367    */
368   node = (HandlerMatch*) g_list_alloc ();
369   node->handler = handler;
370   node->next = list;
371   node->d.signal_id = signal_id;
372   handler_ref (handler);
373   
374   return node;
375 }
376 static inline HandlerMatch*
377 handler_match_free1_R (HandlerMatch *node,
378                        gpointer      instance)
379 {
380   HandlerMatch *next = node->next;
381   
382   handler_unref_R (node->d.signal_id, instance, node->handler);
383   g_list_free_1 ((GList*) node);
384   
385   return next;
386 }
387
388 static HandlerMatch*
389 handlers_find (gpointer         instance,
390                GSignalMatchType mask,
391                guint            signal_id,
392                GQuark           detail,
393                GClosure        *closure,
394                gpointer         func,
395                gpointer         data,
396                gboolean         one_and_only)
397 {
398   HandlerMatch *mlist = NULL;
399   
400   if (mask & G_SIGNAL_MATCH_ID)
401     {
402       HandlerList *hlist = handler_list_lookup (signal_id, instance);
403       Handler *handler;
404       SignalNode *node = NULL;
405       
406       if (mask & G_SIGNAL_MATCH_FUNC)
407         {
408           node = LOOKUP_SIGNAL_NODE (signal_id);
409           if (!node || !node->c_marshaller)
410             return NULL;
411         }
412       
413       mask = ~mask;
414       for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
415         if (handler->id &&
416             ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
417             ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
418             ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
419             ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
420             ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
421                                               handler->closure->meta_marshal == 0 &&
422                                               ((GCClosure*) handler->closure)->callback == func)))
423           {
424             mlist = handler_match_prepend (mlist, handler, signal_id);
425             if (one_and_only)
426               return mlist;
427           }
428     }
429   else
430     {
431       GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
432       
433       mask = ~mask;
434       if (hlbsa)
435         {
436           guint i;
437           
438           for (i = 0; i < hlbsa->n_nodes; i++)
439             {
440               HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
441               SignalNode *node = NULL;
442               Handler *handler;
443               
444               if (!(mask & G_SIGNAL_MATCH_FUNC))
445                 {
446                   node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
447                   if (!node->c_marshaller)
448                     continue;
449                 }
450               
451               for (handler = hlist->handlers; handler; handler = handler->next)
452                 if (handler->id &&
453                     ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
454                     ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
455                     ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
456                     ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
457                     ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
458                                                       handler->closure->meta_marshal == 0 &&
459                                                       ((GCClosure*) handler->closure)->callback == func)))
460                   {
461                     mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
462                     if (one_and_only)
463                       return mlist;
464                   }
465             }
466         }
467     }
468   
469   return mlist;
470 }
471
472 static inline Handler*
473 handler_new (gboolean after)
474 {
475   static guint handler_id = 1;
476   Handler *handler = g_generic_node_alloc (&g_handler_ts,
477                                            sizeof (Handler),
478                                            HANDLER_PRE_ALLOC);
479 #ifndef G_DISABLE_CHECKS
480   if (handler_id == 0)
481     g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
482 #endif
483   
484   handler->id = handler_id++;
485   handler->prev = NULL;
486   handler->next = NULL;
487   handler->detail = 0;
488   handler->ref_count = 1;
489   handler->block_count = 0;
490   handler->after = after != FALSE;
491   handler->closure = NULL;
492   
493   return handler;
494 }
495
496 static inline void
497 handler_ref (Handler *handler)
498 {
499   g_return_if_fail (handler->ref_count > 0);
500   
501 #ifndef G_DISABLE_CHECKS
502   if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
503     g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
504 #endif
505   
506   handler->ref_count += 1;
507 }
508
509 static inline void
510 handler_unref_R (guint    signal_id,
511                  gpointer instance,
512                  Handler *handler)
513 {
514   g_return_if_fail (handler->ref_count > 0);
515   
516   handler->ref_count -= 1;
517   if (!handler->ref_count)
518     {
519       if (handler->next)
520         handler->next->prev = handler->prev;
521       if (handler->prev)        /* watch out for g_signal_handlers_destroy()! */
522         handler->prev->next = handler->next;
523       else
524         {
525           HandlerList *hlist = handler_list_lookup (signal_id, instance);
526           
527           hlist->handlers = handler->next;
528         }
529       G_UNLOCK (g_signal_mutex);
530       g_closure_unref (handler->closure);
531       G_LOCK (g_signal_mutex);
532       g_generic_node_free (&g_handler_ts, handler);
533     }
534 }
535
536 static void
537 handler_insert (guint    signal_id,
538                 gpointer instance,
539                 Handler  *handler)
540 {
541   HandlerList *hlist;
542   
543   g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
544   
545   hlist = handler_list_ensure (signal_id, instance);
546   if (!hlist->handlers)
547     hlist->handlers = handler;
548   else if (hlist->handlers->after && !handler->after)
549     {
550       handler->next = hlist->handlers;
551       hlist->handlers->prev = handler;
552       hlist->handlers = handler;
553     }
554   else
555     {
556       Handler *tmp = hlist->handlers;
557       
558       if (handler->after)
559         while (tmp->next)
560           tmp = tmp->next;
561       else
562         while (tmp->next && !tmp->next->after)
563           tmp = tmp->next;
564       if (tmp->next)
565         tmp->next->prev = handler;
566       handler->next = tmp->next;
567       handler->prev = tmp;
568       tmp->next = handler;
569     }
570 }
571
572 static inline void
573 emission_push (Emission     **emission_list_p,
574                guint          signal_id,
575                GQuark         detail,
576                gpointer       instance,
577                EmissionState *state_p)
578 {
579   Emission *emission = g_generic_node_alloc (&g_emission_ts,
580                                              sizeof (Emission),
581                                              EMISSION_PRE_ALLOC);
582   emission->next = *emission_list_p;
583   emission->signal_id = signal_id;
584   emission->detail = detail;
585   emission->instance = instance;
586   emission->state_p = state_p;
587   *emission_list_p = emission;
588 }
589
590 static inline void
591 emission_pop (Emission     **emission_list_p,
592               EmissionState *state_p)
593 {
594   Emission **loc = emission_list_p, *emission = *loc;
595   
596   while (emission->state_p != state_p)
597     {
598       loc = &emission->next;
599       emission = *loc;
600     }
601   *loc = emission->next;
602   g_generic_node_free (&g_emission_ts, emission);
603 }
604
605 static inline Emission*
606 emission_find (Emission *emission_list,
607                guint     signal_id,
608                GQuark    detail,
609                gpointer  instance)
610 {
611   Emission *emission;
612   
613   for (emission = emission_list; emission; emission = emission->next)
614     if (emission->instance == instance &&
615         emission->signal_id == signal_id &&
616         emission->detail == detail)
617       return emission;
618   return NULL;
619 }
620
621 static gint
622 signal_key_cmp (gconstpointer node1,
623                 gconstpointer node2)
624 {
625   const SignalKey *key1 = node1, *key2 = node2;
626   
627   if (key1->itype == key2->itype)
628     return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
629   else
630     return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
631 }
632
633 void
634 g_signal_init (void) /* sync with gtype.c */
635 {
636   G_LOCK (g_signal_mutex);
637   if (!g_n_signal_nodes)
638     {
639       /* handler_id_node_prepend() requires this */
640       g_assert (sizeof (GList) == sizeof (HandlerMatch));
641       
642       /* setup signal key array */
643       g_signal_key_bsa.cmp_func = signal_key_cmp;
644       g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
645       g_signal_key_bsa.flags = G_BSEARCH_ALIGN_POWER2; /* alloc-only */
646       
647       /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
648       g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
649       
650       /* invalid (0) signal_id */
651       g_n_signal_nodes = 1;
652       g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
653       g_signal_nodes[0] = NULL;
654     }
655   G_UNLOCK (g_signal_mutex);
656 }
657
658 void
659 _g_signals_destroy (GType itype)
660 {
661   guint i;
662   
663   G_LOCK (g_signal_mutex);
664   for (i = 1; i < g_n_signal_nodes; i++)
665     {
666       SignalNode *node = g_signal_nodes[i];
667       
668       if (node->itype == itype)
669         {
670           if (node->destroyed)
671             g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
672                        node->name,
673                        g_type_name (node->itype));
674           else
675             signal_destroy_R (node);
676         }
677     }
678   G_UNLOCK (g_signal_mutex);
679 }
680
681 void
682 g_signal_stop_emission (gpointer instance,
683                         guint    signal_id,
684                         GQuark   detail)
685 {
686   SignalNode *node;
687   
688   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
689   g_return_if_fail (signal_id > 0);
690   
691   G_LOCK (g_signal_mutex);
692   node = LOOKUP_SIGNAL_NODE (signal_id);
693   if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
694     {
695       g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
696       G_UNLOCK (g_signal_mutex);
697       return;
698     }
699   if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
700     {
701       Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
702       Emission *emission = emission_find (emission_list, signal_id, detail, instance);
703       
704       if (emission)
705         {
706           if (*emission->state_p == EMISSION_HOOK)
707             g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
708                        node->name, instance);
709           else if (*emission->state_p == EMISSION_RUN)
710             *emission->state_p = EMISSION_STOP;
711         }
712       else
713         g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
714                    node->name, instance);
715     }
716   else
717     g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
718   G_UNLOCK (g_signal_mutex);
719 }
720
721 static inline guint
722 signal_parse_name (const gchar *name,
723                    GType        itype,
724                    GQuark      *detail_p,
725                    gboolean     force_quark)
726 {
727   const gchar *colon = strchr (name, ':');
728   guint signal_id;
729   
730   if (!colon)
731     {
732       signal_id = signal_id_lookup (g_quark_try_string (name), itype);
733       if (signal_id && detail_p)
734         *detail_p = 0;
735     }
736   else if (colon[1] == ':')
737     {
738       gchar buffer[32];
739       guint l = colon - name;
740       
741       if (l < 32)
742         {
743           memcpy (buffer, name, l);
744           buffer[l] = 0;
745           signal_id = signal_id_lookup (g_quark_try_string (buffer), itype);
746         }
747       else
748         {
749           gchar *signal = g_new (gchar, l + 1);
750           
751           memcpy (signal, name, l);
752           signal[l] = 0;
753           signal_id = signal_id_lookup (g_quark_try_string (signal), itype);
754           g_free (signal);
755         }
756       
757       if (signal_id && detail_p)
758         *detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0;
759     }
760   else
761     signal_id = 0;
762   return signal_id;
763 }
764
765 gboolean
766 g_signal_parse_name (const gchar *detailed_signal,
767                      GType        itype,
768                      guint       *signal_id_p,
769                      GQuark      *detail_p,
770                      gboolean     force_detail_quark)
771 {
772   GQuark detail = 0;
773   guint signal_id;
774   
775   g_return_val_if_fail (detailed_signal != NULL, FALSE);
776   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
777   
778   G_LOCK (g_signal_mutex);
779   signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
780   G_UNLOCK (g_signal_mutex);
781   
782   if (signal_id)
783     {
784       if (signal_id_p)
785         *signal_id_p = signal_id;
786       if (detail_p)
787         *detail_p = detail;
788       
789       return TRUE;
790     }
791   else
792     return FALSE;
793 }
794
795 guint
796 g_signal_lookup (const gchar *name,
797                  GType        itype)
798 {
799   guint signal_id;
800   
801   g_return_val_if_fail (name != NULL, 0);
802   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
803   
804   G_LOCK (g_signal_mutex);
805   signal_id = signal_id_lookup (g_quark_try_string (name), itype);
806   G_UNLOCK (g_signal_mutex);
807   
808   return signal_id;
809 }
810
811 gchar*
812 g_signal_name (guint signal_id)
813 {
814   SignalNode *node;
815   gchar *name;
816   
817   G_LOCK (g_signal_mutex);
818   node = LOOKUP_SIGNAL_NODE (signal_id);
819   name = node ? node->name : NULL;
820   G_UNLOCK (g_signal_mutex);
821   
822   return name;
823 }
824
825 void
826 g_signal_query (guint         signal_id,
827                 GSignalQuery *query)
828 {
829   SignalNode *node;
830   
831   g_return_if_fail (query != NULL);
832   
833   G_LOCK (g_signal_mutex);
834   node = LOOKUP_SIGNAL_NODE (signal_id);
835   if (!node || node->destroyed)
836     query->signal_id = 0;
837   else
838     {
839       query->signal_id = node->signal_id;
840       query->signal_name = node->name;
841       query->itype = node->itype;
842       query->signal_flags = node->flags;
843       query->return_type = node->return_type;
844       query->n_params = node->n_params;
845       query->param_types = node->param_types;
846     }
847   G_UNLOCK (g_signal_mutex);
848 }
849
850 guint*
851 g_signal_list_ids (GType  itype,
852                    guint *n_ids)
853 {
854   SignalKey *keys;
855   GArray *result;
856   guint n_nodes;
857   guint i;
858   
859   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
860   g_return_val_if_fail (n_ids != NULL, NULL);
861   
862   G_LOCK (g_signal_mutex);
863   
864   keys = g_signal_key_bsa.nodes;
865   n_nodes  = g_signal_key_bsa.n_nodes;
866   result = g_array_new (FALSE, FALSE, sizeof (guint));
867   
868   for (i = 0; i < n_nodes; i++)
869     if (keys[i].itype == itype)
870       {
871         gchar *name = g_quark_to_string (keys[i].quark);
872         
873         /* Signal names with "_" in them are aliases to the same
874          * name with "-" instead of "_".
875          */
876         if (!strchr (name, '_'))
877           g_array_append_val (result, keys[i].signal_id);
878       }
879   
880   *n_ids = result->len;
881   
882   G_UNLOCK (g_signal_mutex);
883   
884   return (guint *) g_array_free (result, FALSE);
885 }
886
887 guint
888 g_signal_new_valist (const gchar       *signal_name,
889                      GType              itype,
890                      GSignalFlags       signal_flags,
891                      GClosure          *class_closure,
892                      GSignalAccumulator accumulator,
893                      GSignalCMarshaller c_marshaller,
894                      GType              return_type,
895                      guint              n_params,
896                      va_list            args)
897 {
898   GType *param_types;
899   guint i;
900   guint signal_id;
901
902   if (n_params > 0)
903     {
904       param_types = g_new (GType, n_params);
905
906       for (i = 0; i < n_params; i++)
907         param_types[i] = va_arg (args, GType);
908     }
909   else
910     param_types = NULL;
911
912   signal_id = g_signal_newv (signal_name, itype, signal_flags,
913                              class_closure, accumulator, c_marshaller,
914                              return_type, n_params, param_types);
915   g_free (param_types);
916
917   return signal_id;
918 }
919
920 guint
921 g_signal_newc (const gchar       *signal_name,
922                GType              itype,
923                GSignalFlags       signal_flags,
924                guint              class_offset,
925                GSignalAccumulator accumulator,
926                GSignalCMarshaller c_marshaller,
927                GType              return_type,
928                guint              n_params,
929                ...)
930 {
931   va_list args;
932   guint signal_id;
933
934   g_return_val_if_fail (signal_name != NULL, 0);
935   
936   va_start (args, n_params);
937
938   signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
939                                    g_signal_type_cclosure_new (itype,
940                                                                class_offset),
941                                    accumulator, c_marshaller,
942                                    return_type, n_params, args);
943
944   va_end (args);
945  
946   return signal_id;
947 }
948
949 guint
950 g_signal_newv (const gchar       *signal_name,
951                GType              itype,
952                GSignalFlags       signal_flags,
953                GClosure          *class_closure,
954                GSignalAccumulator accumulator,
955                GSignalCMarshaller c_marshaller,
956                GType              return_type,
957                guint              n_params,
958                GType             *param_types)
959 {
960   gchar *name;
961   guint signal_id, i;
962   SignalNode *node;
963   
964   g_return_val_if_fail (signal_name != NULL, 0);
965   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
966   if (n_params)
967     g_return_val_if_fail (param_types != NULL, 0);
968   if (return_type != G_TYPE_NONE)
969     g_return_val_if_fail (accumulator == NULL, 0);
970   
971   name = g_strdup (signal_name);
972   g_strdelimit (name, G_STR_DELIMITERS ":^", '_');  // FIXME do character checks like for types
973   
974   G_LOCK (g_signal_mutex);
975   
976   signal_id = signal_id_lookup (g_quark_try_string (name), itype);
977   node = LOOKUP_SIGNAL_NODE (signal_id);
978   if (node && !node->destroyed)
979     {
980       g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
981                  name,
982                  g_type_name (node->itype),
983                  G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
984       g_free (name);
985       G_UNLOCK (g_signal_mutex);
986       return 0;
987     }
988   if (node && node->itype != itype)
989     {
990       g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
991                  name,
992                  g_type_name (itype),
993                  g_type_name (node->itype));
994       g_free (name);
995       G_UNLOCK (g_signal_mutex);
996       return 0;
997     }
998   for (i = 0; i < n_params; i++)
999     if (!G_TYPE_IS_VALUE (param_types[i]) ||
1000         param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */
1001       {
1002         g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
1003                    i + 1, g_type_name (param_types[i]), g_type_name (itype), name);
1004         g_free (name);
1005         G_UNLOCK (g_signal_mutex);
1006         return 0;
1007       }
1008   if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type))
1009     {
1010       g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
1011                  g_type_name (param_types[i]), g_type_name (itype), name);
1012       g_free (name);
1013       G_UNLOCK (g_signal_mutex);
1014       return 0;
1015     }
1016   
1017   /* setup permanent portion of signal node */
1018   if (!node)
1019     {
1020       SignalKey key;
1021       
1022       signal_id = g_n_signal_nodes++;
1023       node = g_new (SignalNode, 1);
1024       node->signal_id = signal_id;
1025       g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
1026       g_signal_nodes[signal_id] = node;
1027       node->itype = itype;
1028       node->name = name;
1029       key.itype = itype;
1030       key.quark = g_quark_from_string (node->name);
1031       key.signal_id = signal_id;
1032       g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
1033       g_strdelimit (node->name, "_", '-');
1034       key.quark = g_quark_from_static_string (node->name);
1035       g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
1036     }
1037   node->destroyed = FALSE;
1038   
1039   /* setup reinitializable portion */
1040   node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
1041   node->n_params = n_params;
1042   node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
1043   node->return_type = return_type;
1044   node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL;
1045   node->accumulator = accumulator;
1046   node->c_marshaller = c_marshaller;
1047   node->emission_hooks = NULL;
1048   if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure))
1049     g_closure_set_marshal (class_closure, node->c_marshaller);
1050   
1051   G_UNLOCK (g_signal_mutex);
1052   return signal_id;
1053 }
1054
1055 static void
1056 signal_destroy_R (SignalNode *signal_node)
1057 {
1058   SignalNode node = *signal_node;
1059   
1060   signal_node->destroyed = TRUE;
1061   
1062   /* reentrancy caution, zero out real contents first */
1063   signal_node->n_params = 0;
1064   signal_node->param_types = NULL;
1065   signal_node->return_type = 0;
1066   signal_node->class_closure = NULL;
1067   signal_node->accumulator = NULL;
1068   signal_node->c_marshaller = NULL;
1069   signal_node->emission_hooks = NULL;
1070   
1071 #ifdef  G_ENABLE_DEBUG
1072   /* check current emissions */
1073   {
1074     Emission *emission;
1075     
1076     for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
1077          emission; emission = emission->next)
1078       if (emission->signal_id == node.signal_id)
1079         g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
1080                     node.name, emission->instance);
1081   }
1082 #endif
1083   
1084   /* free contents that need to
1085    */
1086   G_UNLOCK (g_signal_mutex);
1087   g_free (node.param_types);
1088   g_closure_unref (node.class_closure);
1089   if (node.emission_hooks)
1090     {
1091       g_hook_list_clear (node.emission_hooks);
1092       g_free (node.emission_hooks);
1093     }
1094   G_LOCK (g_signal_mutex);
1095 }
1096
1097 guint
1098 g_signal_connect_closure_by_id (gpointer  instance,
1099                                 guint     signal_id,
1100                                 GQuark    detail,
1101                                 GClosure *closure,
1102                                 gboolean  after)
1103 {
1104   SignalNode *node;
1105   guint handler_id = 0;
1106   
1107   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1108   g_return_val_if_fail (signal_id > 0, 0);
1109   g_return_val_if_fail (closure != NULL, 0);
1110   
1111   G_LOCK (g_signal_mutex);
1112   node = LOOKUP_SIGNAL_NODE (signal_id);
1113   if (node)
1114     {
1115       if (detail && !(node->flags & G_SIGNAL_DETAILED))
1116         g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1117       else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1118         g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1119       else
1120         {
1121           Handler *handler = handler_new (after);
1122           
1123           handler_id = handler->id;
1124           handler->detail = detail;
1125           handler->closure = g_closure_ref (closure);
1126           handler_insert (signal_id, instance, handler);
1127           if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
1128             g_closure_set_marshal (closure, node->c_marshaller);
1129         }
1130     }
1131   else
1132     g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1133   G_UNLOCK (g_signal_mutex);
1134   
1135   return handler_id;
1136 }
1137
1138 guint
1139 g_signal_connect_closure (gpointer     instance,
1140                           const gchar *detailed_signal,
1141                           GClosure    *closure,
1142                           gboolean     after)
1143 {
1144   guint signal_id, handler_id = 0;
1145   GQuark detail = 0;
1146   GType itype;
1147
1148   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1149   g_return_val_if_fail (detailed_signal != NULL, 0);
1150   g_return_val_if_fail (closure != NULL, 0);
1151
1152   G_LOCK (g_signal_mutex);
1153   itype = G_TYPE_FROM_INSTANCE (instance);
1154   signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1155   if (signal_id)
1156     {
1157       SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1158
1159       if (detail && !(node->flags & G_SIGNAL_DETAILED))
1160         g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1161       else if (!g_type_is_a (itype, node->itype))
1162         g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1163       else
1164         {
1165           Handler *handler = handler_new (after);
1166
1167           handler_id = handler->id;
1168           handler->detail = detail;
1169           handler->closure = g_closure_ref (closure);
1170           handler_insert (signal_id, instance, handler);
1171           if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1172             g_closure_set_marshal (handler->closure, node->c_marshaller);
1173         }
1174     }
1175   else
1176     g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1177   G_UNLOCK (g_signal_mutex);
1178
1179   return handler_id;
1180 }
1181
1182 guint
1183 g_signal_connect_data (gpointer       instance,
1184                        const gchar   *detailed_signal,
1185                        GCallback      c_handler,
1186                        gpointer       data,
1187                        GClosureNotify destroy_data,
1188                        gboolean       swapped,
1189                        gboolean       after)
1190 {
1191   guint signal_id, handler_id = 0;
1192   GQuark detail = 0;
1193   GType itype;
1194
1195   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1196   g_return_val_if_fail (detailed_signal != NULL, 0);
1197   g_return_val_if_fail (c_handler != NULL, 0);
1198
1199   G_LOCK (g_signal_mutex);
1200   itype = G_TYPE_FROM_INSTANCE (instance);
1201   signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1202   if (signal_id)
1203     {
1204       SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1205
1206       if (detail && !(node->flags & G_SIGNAL_DETAILED))
1207         g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1208       else if (!g_type_is_a (itype, node->itype))
1209         g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1210       else
1211         {
1212           Handler *handler = handler_new (after);
1213
1214           handler_id = handler->id;
1215           handler->detail = detail;
1216           handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
1217           handler_insert (signal_id, instance, handler);
1218           if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1219             g_closure_set_marshal (handler->closure, node->c_marshaller);
1220         }
1221     }
1222   else
1223     g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1224   G_UNLOCK (g_signal_mutex);
1225
1226   return handler_id;
1227 }
1228
1229 void
1230 g_signal_handler_block (gpointer instance,
1231                         guint    handler_id)
1232 {
1233   Handler *handler;
1234   
1235   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1236   g_return_if_fail (handler_id > 0);
1237   
1238   G_LOCK (g_signal_mutex);
1239   handler = handler_lookup (instance, handler_id, NULL);
1240   if (handler)
1241     {
1242 #ifndef G_DISABLE_CHECKS
1243       if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
1244         g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
1245 #endif
1246       
1247       handler->block_count += 1;
1248     }
1249   else
1250     g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1251   G_UNLOCK (g_signal_mutex);
1252 }
1253
1254 void
1255 g_signal_handler_unblock (gpointer instance,
1256                           guint    handler_id)
1257 {
1258   Handler *handler;
1259   
1260   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1261   g_return_if_fail (handler_id > 0);
1262   
1263   G_LOCK (g_signal_mutex);
1264   handler = handler_lookup (instance, handler_id, NULL);
1265   if (handler)
1266     {
1267       if (handler->block_count)
1268         handler->block_count -= 1;
1269       else
1270         g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance);
1271     }
1272   else
1273     g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1274   G_UNLOCK (g_signal_mutex);
1275 }
1276
1277 void
1278 g_signal_handler_disconnect (gpointer instance,
1279                              guint    handler_id)
1280 {
1281   Handler *handler;
1282   guint signal_id;
1283   
1284   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1285   g_return_if_fail (handler_id > 0);
1286   
1287   G_LOCK (g_signal_mutex);
1288   handler = handler_lookup (instance, handler_id, &signal_id);
1289   if (handler)
1290     {
1291       handler->id = 0;
1292       handler->block_count = 1;
1293       handler_unref_R (signal_id, instance, handler);
1294     }
1295   else
1296     g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1297   G_UNLOCK (g_signal_mutex);
1298 }
1299
1300 void
1301 g_signal_handlers_destroy (gpointer instance)
1302 {
1303   GBSearchArray *hlbsa;
1304   
1305   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1306   
1307   G_LOCK (g_signal_mutex);
1308   hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
1309   if (hlbsa)
1310     {
1311       guint i;
1312       
1313       /* reentrancy caution, delete instance trace first */
1314       g_hash_table_remove (g_handler_list_bsa_ht, instance);
1315       
1316       for (i = 0; i < hlbsa->n_nodes; i++)
1317         {
1318           HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
1319           Handler *handler = hlist->handlers;
1320           
1321           while (handler)
1322             {
1323               Handler *tmp = handler;
1324               
1325               handler = tmp->next;
1326               tmp->block_count = 1;
1327               /* cruel unlink, this works because _all_ handlers vanish */
1328               tmp->next = NULL;
1329               tmp->prev = tmp;
1330               if (tmp->id)
1331                 {
1332                   tmp->id = 0;
1333                   handler_unref_R (0, NULL, tmp);
1334                 }
1335             }
1336         }
1337       g_free (hlbsa->nodes);
1338       g_generic_node_free (&g_bsa_ts, hlbsa);
1339     }
1340   G_UNLOCK (g_signal_mutex);
1341 }
1342
1343 guint
1344 g_signal_handler_find (gpointer         instance,
1345                        GSignalMatchType mask,
1346                        guint            signal_id,
1347                        GQuark           detail,
1348                        GClosure        *closure,
1349                        gpointer         func,
1350                        gpointer         data)
1351 {
1352   guint handler_id = 0;
1353   
1354   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1355   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1356   
1357   if (mask & G_SIGNAL_MATCH_MASK)
1358     {
1359       HandlerMatch *mlist;
1360       
1361       G_LOCK (g_signal_mutex);
1362       mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
1363       if (mlist)
1364         {
1365           handler_id = mlist->handler->id;
1366           handler_match_free1_R (mlist, instance);
1367         }
1368       G_UNLOCK (g_signal_mutex);
1369     }
1370   
1371   return handler_id;
1372 }
1373
1374 static guint
1375 signal_handlers_foreach_matched_R (gpointer         instance,
1376                                    GSignalMatchType mask,
1377                                    guint            signal_id,
1378                                    GQuark           detail,
1379                                    GClosure        *closure,
1380                                    gpointer         func,
1381                                    gpointer         data,
1382                                    void           (*callback) (gpointer instance,
1383                                                                guint    handler_id))
1384 {
1385   HandlerMatch *mlist;
1386   guint n_handlers = 0;
1387   
1388   mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
1389   while (mlist)
1390     {
1391       n_handlers++;
1392       G_UNLOCK (g_signal_mutex);
1393       callback (instance, mlist->handler->id);
1394       G_LOCK (g_signal_mutex);
1395       mlist = handler_match_free1_R (mlist, instance);
1396     }
1397   
1398   return n_handlers;
1399 }
1400
1401 guint
1402 g_signal_handlers_block_matched (gpointer         instance,
1403                                  GSignalMatchType mask,
1404                                  guint            signal_id,
1405                                  GQuark           detail,
1406                                  GClosure        *closure,
1407                                  gpointer         func,
1408                                  gpointer         data)
1409 {
1410   guint n_handlers = 0;
1411   
1412   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1413   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1414   
1415   if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1416     {
1417       G_LOCK (g_signal_mutex);
1418       n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1419                                                       closure, func, data,
1420                                                       g_signal_handler_block);
1421       G_UNLOCK (g_signal_mutex);
1422     }
1423   
1424   return n_handlers;
1425 }
1426
1427 guint
1428 g_signal_handlers_unblock_matched (gpointer         instance,
1429                                    GSignalMatchType mask,
1430                                    guint            signal_id,
1431                                    GQuark           detail,
1432                                    GClosure        *closure,
1433                                    gpointer         func,
1434                                    gpointer         data)
1435 {
1436   guint n_handlers = 0;
1437   
1438   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1439   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1440   
1441   if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1442     {
1443       G_LOCK (g_signal_mutex);
1444       n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1445                                                       closure, func, data,
1446                                                       g_signal_handler_unblock);
1447       G_UNLOCK (g_signal_mutex);
1448     }
1449   
1450   return n_handlers;
1451 }
1452
1453 guint
1454 g_signal_handlers_disconnect_matched (gpointer         instance,
1455                                       GSignalMatchType mask,
1456                                       guint            signal_id,
1457                                       GQuark           detail,
1458                                       GClosure        *closure,
1459                                       gpointer         func,
1460                                       gpointer         data)
1461 {
1462   guint n_handlers = 0;
1463   
1464   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1465   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1466   
1467   if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1468     {
1469       G_LOCK (g_signal_mutex);
1470       n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1471                                                       closure, func, data,
1472                                                       g_signal_handler_disconnect);
1473       G_UNLOCK (g_signal_mutex);
1474     }
1475   
1476   return n_handlers;
1477 }
1478
1479 gboolean
1480 g_signal_has_handler_pending (gpointer instance,
1481                               guint    signal_id,
1482                               GQuark   detail,
1483                               gboolean may_be_blocked)
1484 {
1485   HandlerMatch *mlist;
1486   gboolean has_pending;
1487   
1488   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1489   g_return_val_if_fail (signal_id > 0, FALSE);
1490   
1491   G_LOCK (g_signal_mutex);
1492   if (detail)
1493     {
1494       SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1495       
1496       if (!(node->flags & G_SIGNAL_DETAILED))
1497         {
1498           g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1499           G_UNLOCK (g_signal_mutex);
1500           return FALSE;
1501         }
1502     }
1503   mlist = handlers_find (instance,
1504                          (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
1505                          signal_id, detail, NULL, NULL, NULL, TRUE);
1506   if (mlist)
1507     {
1508       has_pending = TRUE;
1509       handler_match_free1_R (mlist, instance);
1510     }
1511   else
1512     has_pending = FALSE;
1513   G_UNLOCK (g_signal_mutex);
1514   
1515   return has_pending;
1516 }
1517
1518 void
1519 g_signal_emitv (const GValue *instance_and_params,
1520                 guint         signal_id,
1521                 GQuark        detail,
1522                 GValue       *return_value)
1523 {
1524   const GValue *param_values;
1525   gpointer instance;
1526   SignalNode *node;
1527   guint i;
1528   
1529   g_return_if_fail (instance_and_params != NULL);
1530   instance = g_value_get_as_pointer (instance_and_params);
1531   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1532   g_return_if_fail (signal_id > 0);
1533
1534   param_values = instance_and_params + 1;
1535   
1536   G_LOCK (g_signal_mutex);
1537   node = LOOKUP_SIGNAL_NODE (signal_id);
1538   if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1539     {
1540       g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1541       G_UNLOCK (g_signal_mutex);
1542       return;
1543     }
1544 #ifdef G_ENABLE_DEBUG
1545   if (detail && !(node->flags & G_SIGNAL_DETAILED))
1546     {
1547       g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1548       G_UNLOCK (g_signal_mutex);
1549       return;
1550     }
1551   for (i = 0; i < node->n_params; i++)
1552     if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
1553       {
1554         g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'",
1555                     G_STRLOC,
1556                     g_type_name (node->param_types[i]),
1557                     i,
1558                     node->name,
1559                     G_VALUE_TYPE_NAME (param_values + i));
1560         G_UNLOCK (g_signal_mutex);
1561         return;
1562       }
1563   if (node->return_type != G_TYPE_NONE)
1564     {
1565       if (!return_value)
1566         {
1567           g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)",
1568                       G_STRLOC,
1569                       g_type_name (node->return_type),
1570                       node->name);
1571           G_UNLOCK (g_signal_mutex);
1572           return;
1573         }
1574       else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
1575         {
1576           g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'",
1577                       G_STRLOC,
1578                       g_type_name (node->return_type),
1579                       node->name,
1580                       G_VALUE_TYPE_NAME (return_value));
1581           G_UNLOCK (g_signal_mutex);
1582           return;
1583         }
1584     }
1585   else
1586     return_value = NULL;
1587 #endif  /* G_ENABLE_DEBUG */
1588
1589   signal_emit_R (node, detail, instance, return_value, instance_and_params);
1590   G_UNLOCK (g_signal_mutex);
1591 }
1592
1593 void
1594 g_signal_emit_valist (gpointer instance,
1595                       guint    signal_id,
1596                       GQuark   detail,
1597                       va_list  var_args)
1598 {
1599   GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL;
1600   GValue *param_values;
1601   SignalNode *node;
1602   guint i;
1603
1604   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1605   g_return_if_fail (signal_id > 0);
1606
1607   G_LOCK (g_signal_mutex);
1608   node = LOOKUP_SIGNAL_NODE (signal_id);
1609   if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1610     {
1611       g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1612       G_UNLOCK (g_signal_mutex);
1613       return;
1614     }
1615 #ifndef G_DISABLE_CHECKS
1616   if (detail && !(node->flags & G_SIGNAL_DETAILED))
1617     {
1618       g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1619       G_UNLOCK (g_signal_mutex);
1620       return;
1621     }
1622 #endif  /* !G_DISABLE_CHECKS */
1623
1624   if (node->n_params < MAX_STACK_VALUES)
1625     instance_and_params = stack_values;
1626   else
1627     {
1628       free_me = g_new (GValue, node->n_params + 1);
1629       instance_and_params = free_me;
1630     }
1631   param_values = instance_and_params + 1;
1632   for (i = 0; i < node->n_params; i++)
1633     {
1634       gchar *error;
1635
1636       param_values[i].g_type = 0;
1637       g_value_init (param_values + i, node->param_types[i]);
1638       G_VALUE_COLLECT (param_values + i, var_args, &error);
1639       if (error)
1640         {
1641           g_warning ("%s: %s", G_STRLOC, error);
1642           g_free (error);
1643
1644           /* we purposely leak the value here, it might not be
1645            * in a sane state if an error condition occoured
1646            */
1647           while (i--)
1648             g_value_unset (param_values + i);
1649
1650           G_UNLOCK (g_signal_mutex);
1651           g_free (free_me);
1652           return;
1653         }
1654     }
1655   instance_and_params->g_type = 0;
1656   g_value_init (instance_and_params, node->itype);
1657   g_value_set_instance (instance_and_params, instance);
1658   if (node->return_type == G_TYPE_NONE)
1659     signal_emit_R (node, detail, instance, NULL, instance_and_params);
1660   else
1661     {
1662       GValue return_value = { 0, };
1663       gchar *error = NULL;
1664
1665       g_value_init (&return_value, node->return_type);
1666       if (signal_emit_R (node, detail, instance, &return_value, instance_and_params))
1667         G_VALUE_LCOPY (&return_value, var_args, &error);
1668       if (!error)
1669         g_value_unset (&return_value);
1670       else
1671         {
1672           g_warning ("%s: %s", G_STRLOC, error);
1673           g_free (error);
1674
1675           /* we purposely leak the value here, it might not be
1676            * in a sane state if an error condition occoured
1677            */
1678         }
1679     }
1680   for (i = 0; i < node->n_params; i++)
1681     g_value_unset (param_values + i);
1682   g_value_unset (instance_and_params);
1683   if (free_me)
1684     g_free (free_me);
1685   G_UNLOCK (g_signal_mutex);
1686 }
1687
1688 void
1689 g_signal_emit (gpointer instance,
1690                guint    signal_id,
1691                GQuark   detail,
1692                ...)
1693 {
1694   va_list var_args;
1695
1696   va_start (var_args, detail);
1697   g_signal_emit_valist (instance, signal_id, detail, var_args);
1698   va_end (var_args);
1699 }
1700
1701 void
1702 g_signal_emit_by_name (gpointer     instance,
1703                        const gchar *detailed_signal,
1704                        ...)
1705 {
1706   GQuark detail = 0;
1707   guint signal_id;
1708
1709   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1710   g_return_if_fail (detailed_signal != NULL);
1711
1712   G_LOCK (g_signal_mutex);
1713   signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE);
1714   G_UNLOCK (g_signal_mutex);
1715
1716   if (signal_id)
1717     {
1718       va_list var_args;
1719
1720       va_start (var_args, detailed_signal);
1721       g_signal_emit_valist (instance, signal_id, detail, var_args);
1722       va_end (var_args);
1723     }
1724   else
1725     g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1726 }
1727
1728 static gboolean
1729 signal_emit_R (SignalNode   *node,
1730                GQuark        detail,
1731                gpointer      instance,
1732                GValue       *return_value,
1733                const GValue *instance_and_params)
1734 {
1735   EmissionState emission_state = 0;
1736   GSignalAccumulator accumulator;
1737   GSignalInvocationHint ihint;
1738   GClosure *class_closure;
1739   HandlerList *hlist;
1740   Handler *handler_list = NULL;
1741   GValue accu = { 0, };
1742   gboolean accu_used = FALSE;
1743   guint signal_id = node->signal_id;
1744   gboolean return_value_altered = FALSE;
1745   
1746   if (node->flags & G_SIGNAL_NO_RECURSE)
1747     {
1748       Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance);
1749       
1750       if (emission)
1751         {
1752           *emission->state_p = EMISSION_RESTART;
1753           return return_value_altered;
1754         }
1755     }
1756   ihint.signal_id = node->signal_id;
1757   ihint.detail = detail;
1758   accumulator = node->accumulator;
1759   if (accumulator)
1760     g_value_init (&accu, node->return_type);
1761   emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
1762                  signal_id, detail, instance, &emission_state);
1763   class_closure = node->class_closure;
1764   
1765  EMIT_RESTART:
1766   
1767   if (handler_list)
1768     handler_unref_R (signal_id, instance, handler_list);
1769   hlist = handler_list_lookup (signal_id, instance);
1770   handler_list = hlist ? hlist->handlers : NULL;
1771   if (handler_list)
1772     handler_ref (handler_list);
1773   
1774   ihint.run_type = G_SIGNAL_RUN_FIRST;
1775   
1776   if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
1777     {
1778       emission_state = EMISSION_RUN;
1779       
1780       G_UNLOCK (g_signal_mutex);
1781       if (accumulator)
1782         {
1783           if (accu_used)
1784             g_value_reset (&accu);
1785           g_closure_invoke (class_closure,
1786                             &accu,
1787                             node->n_params + 1,
1788                             instance_and_params,
1789                             &ihint);
1790           if (!accumulator (&ihint, return_value, &accu) &&
1791               emission_state == EMISSION_RUN)
1792             emission_state = EMISSION_STOP;
1793           accu_used = TRUE;
1794         }
1795       else
1796         g_closure_invoke (class_closure,
1797                           return_value,
1798                           node->n_params + 1,
1799                           instance_and_params,
1800                           &ihint);
1801       G_LOCK (g_signal_mutex);
1802       return_value_altered = TRUE;
1803       
1804       if (emission_state == EMISSION_STOP)
1805         goto EMIT_CLEANUP;
1806       else if (emission_state == EMISSION_RESTART)
1807         goto EMIT_RESTART;
1808     }
1809   
1810   if (node->emission_hooks)
1811     {
1812       emission_state = EMISSION_HOOK;
1813       
1814       G_UNLOCK (g_signal_mutex);
1815       g_print ("emission_hooks()\n");
1816       G_LOCK (g_signal_mutex);
1817       
1818       if (emission_state == EMISSION_RESTART)
1819         goto EMIT_RESTART;
1820     }
1821   
1822   if (handler_list)
1823     {
1824       Handler *handler = handler_list;
1825       
1826       emission_state = EMISSION_RUN;
1827       handler_ref (handler);
1828       do
1829         {
1830           Handler *tmp;
1831           
1832           if (handler->after)
1833             {
1834               handler_unref_R (signal_id, instance, handler_list);
1835               handler_list = handler;
1836               break;
1837             }
1838           else if (!handler->block_count && (!handler->detail || handler->detail == detail))
1839             {
1840               G_UNLOCK (g_signal_mutex);
1841               if (accumulator)
1842                 {
1843                   if (accu_used)
1844                     g_value_reset (&accu);
1845                   g_closure_invoke (handler->closure,
1846                                     &accu,
1847                                     node->n_params + 1,
1848                                     instance_and_params,
1849                                     &ihint);
1850                   if (!accumulator (&ihint, return_value, &accu) &&
1851                       emission_state == EMISSION_RUN)
1852                     emission_state = EMISSION_STOP;
1853                   accu_used = TRUE;
1854                 }
1855               else
1856                 g_closure_invoke (handler->closure,
1857                                   return_value,
1858                                   node->n_params + 1,
1859                                   instance_and_params,
1860                                   &ihint);
1861               G_LOCK (g_signal_mutex);
1862               return_value_altered = TRUE;
1863               
1864               tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1865             }
1866           else
1867             tmp = handler->next;
1868           
1869           if (tmp)
1870             handler_ref (tmp);
1871           handler_unref_R (signal_id, instance, handler_list);
1872           handler_list = handler;
1873           handler = tmp;
1874         }
1875       while (handler);
1876       
1877       if (emission_state == EMISSION_STOP)
1878         goto EMIT_CLEANUP;
1879       else if (emission_state == EMISSION_RESTART)
1880         goto EMIT_RESTART;
1881     }
1882   
1883   ihint.run_type = G_SIGNAL_RUN_LAST;
1884   
1885   if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
1886     {
1887       emission_state = EMISSION_RUN;
1888       
1889       G_UNLOCK (g_signal_mutex);
1890       if (accumulator)
1891         {
1892           if (accu_used)
1893             g_value_reset (&accu);
1894           g_closure_invoke (class_closure,
1895                             &accu,
1896                             node->n_params + 1,
1897                             instance_and_params,
1898                             &ihint);
1899           if (!accumulator (&ihint, return_value, &accu) &&
1900               emission_state == EMISSION_RUN)
1901             emission_state = EMISSION_STOP;
1902           accu_used = TRUE;
1903         }
1904       else
1905         g_closure_invoke (class_closure,
1906                           return_value,
1907                           node->n_params + 1,
1908                           instance_and_params,
1909                           &ihint);
1910       G_LOCK (g_signal_mutex);
1911       return_value_altered = TRUE;
1912       
1913       if (emission_state == EMISSION_STOP)
1914         goto EMIT_CLEANUP;
1915       else if (emission_state == EMISSION_RESTART)
1916         goto EMIT_RESTART;
1917     }
1918   
1919   if (handler_list)
1920     {
1921       Handler *handler = handler_list;
1922       
1923       emission_state = EMISSION_RUN;
1924       handler_ref (handler);
1925       do
1926         {
1927           Handler *tmp;
1928           
1929           if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail))
1930             {
1931               G_UNLOCK (g_signal_mutex);
1932               if (accumulator)
1933                 {
1934                   if (accu_used)
1935                     g_value_reset (&accu);
1936                   g_closure_invoke (handler->closure,
1937                                     &accu,
1938                                     node->n_params + 1,
1939                                     instance_and_params,
1940                                     &ihint);
1941                   if (!accumulator (&ihint, return_value, &accu) &&
1942                       emission_state == EMISSION_RUN)
1943                     emission_state = EMISSION_STOP;
1944                   accu_used = TRUE;
1945                 }
1946               else
1947                 g_closure_invoke (handler->closure,
1948                                   return_value,
1949                                   node->n_params + 1,
1950                                   instance_and_params,
1951                                   &ihint);
1952               G_LOCK (g_signal_mutex);
1953               return_value_altered = TRUE;
1954               
1955               tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1956             }
1957           else
1958             tmp = handler->next;
1959           
1960           if (tmp)
1961             handler_ref (tmp);
1962           handler_unref_R (signal_id, instance, handler);
1963           handler = tmp;
1964         }
1965       while (handler);
1966       
1967       if (emission_state == EMISSION_STOP)
1968         goto EMIT_CLEANUP;
1969       else if (emission_state == EMISSION_RESTART)
1970         goto EMIT_RESTART;
1971     }
1972   
1973  EMIT_CLEANUP:
1974   
1975   ihint.run_type = G_SIGNAL_RUN_CLEANUP;
1976   
1977   if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
1978     {
1979       gboolean need_unset = FALSE;
1980       
1981       emission_state = EMISSION_STOP;
1982       
1983       G_UNLOCK (g_signal_mutex);
1984       if (node->return_type != G_TYPE_NONE)
1985         {
1986           if (!accumulator)
1987             {
1988               g_value_init (&accu, node->return_type);
1989               need_unset = TRUE;
1990             }
1991           else if (accu_used)
1992             g_value_reset (&accu);
1993         }
1994       g_closure_invoke (class_closure,
1995                         node->return_type != G_TYPE_NONE ? &accu : NULL,
1996                         node->n_params + 1,
1997                         instance_and_params,
1998                         &ihint);
1999       if (need_unset)
2000         g_value_unset (&accu);
2001       G_LOCK (g_signal_mutex);
2002       
2003       if (emission_state == EMISSION_RESTART)
2004         goto EMIT_RESTART;
2005     }
2006   
2007   if (handler_list)
2008     handler_unref_R (signal_id, instance, handler_list);
2009   
2010   emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
2011   if (accumulator)
2012     g_value_unset (&accu);
2013
2014   return return_value_altered;
2015 }
2016
2017
2018 /* --- compile standard marshallers --- */
2019 #include        "gvaluetypes.h"
2020 #include        "gmarshal.c"