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