source: trunk/third/glib2/gobject/gsignal.c @ 21369

Revision 21369, 73.5 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21368, which included commits to RCS files with non-trunk default branches.
Line 
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 <config.h>
28
29#include        "gsignal.h"
30#include        "gbsearcharray.h"
31#include        "gvaluecollector.h"
32#include        "gvaluetypes.h"
33#include        "gboxed.h"
34#include        <string.h>
35#include        <signal.h>
36
37
38/* pre allocation configurations
39 */
40#define MAX_STACK_VALUES        (16)
41#define HANDLER_PRE_ALLOC       (48)
42
43#define REPORT_BUG      "please report occourance circumstances to gtk-devel-list@gnome.org"
44#ifdef  G_ENABLE_DEBUG
45#define IF_DEBUG(debug_type, cond)      if ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || cond)
46static volatile gpointer g_trace_instance_signals = NULL;
47static volatile gpointer g_trap_instance_signals = NULL;
48#endif  /* G_ENABLE_DEBUG */
49
50
51/* --- generic allocation --- */
52/* we special case allocations generically by replacing
53 * these functions with more speed/memory aware variants
54 */
55#ifndef DISABLE_MEM_POOLS
56static inline gpointer
57g_generic_node_alloc (GTrashStack **trash_stack_p,
58                      guint         sizeof_node,
59                      guint         nodes_pre_alloc)
60{
61  gpointer node = g_trash_stack_pop (trash_stack_p);
62 
63  if (!node)
64    {
65      guint8 *block;
66     
67      nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
68      block = g_malloc (sizeof_node * nodes_pre_alloc);
69      while (--nodes_pre_alloc)
70        {
71          g_trash_stack_push (trash_stack_p, block);
72          block += sizeof_node;
73        }
74      node = block;
75    }
76 
77  return node;
78}
79#define g_generic_node_free(trash_stack_p, node) g_trash_stack_push (trash_stack_p, node)
80#else   /* !DISABLE_MEM_POOLS */
81#define g_generic_node_alloc(t,sizeof_node,p)    g_malloc (sizeof_node)
82#define g_generic_node_free(t,node)              g_free (node)
83#endif  /* !DISABLE_MEM_POOLS */
84
85
86/* --- typedefs --- */
87typedef struct _SignalNode   SignalNode;
88typedef struct _SignalKey    SignalKey;
89typedef struct _Emission     Emission;
90typedef struct _Handler      Handler;
91typedef struct _HandlerList  HandlerList;
92typedef struct _HandlerMatch HandlerMatch;
93typedef enum
94{
95  EMISSION_STOP,
96  EMISSION_RUN,
97  EMISSION_HOOK,
98  EMISSION_RESTART
99} EmissionState;
100
101
102/* --- prototypes --- */
103static inline guint             signal_id_lookup        (GQuark           quark,
104                                                         GType            itype);
105static        void              signal_destroy_R        (SignalNode      *signal_node);
106static inline HandlerList*      handler_list_ensure     (guint            signal_id,
107                                                         gpointer         instance);
108static inline HandlerList*      handler_list_lookup     (guint            signal_id,
109                                                         gpointer         instance);
110static inline Handler*          handler_new             (gboolean         after);
111static        void              handler_insert          (guint            signal_id,
112                                                         gpointer         instance,
113                                                         Handler         *handler);
114static        Handler*          handler_lookup          (gpointer         instance,
115                                                         gulong           handler_id,
116                                                         guint           *signal_id_p);
117static inline HandlerMatch*     handler_match_prepend   (HandlerMatch    *list,
118                                                         Handler         *handler,
119                                                         guint            signal_id);
120static inline HandlerMatch*     handler_match_free1_R   (HandlerMatch    *node,
121                                                         gpointer         instance);
122static        HandlerMatch*     handlers_find           (gpointer         instance,
123                                                         GSignalMatchType mask,
124                                                         guint            signal_id,
125                                                         GQuark           detail,
126                                                         GClosure        *closure,
127                                                         gpointer         func,
128                                                         gpointer         data,
129                                                         gboolean         one_and_only);
130static inline void              handler_ref             (Handler         *handler);
131static inline void              handler_unref_R         (guint            signal_id,
132                                                         gpointer         instance,
133                                                         Handler         *handler);
134static gint                     handler_lists_cmp       (gconstpointer    node1,
135                                                         gconstpointer    node2);
136static inline void              emission_push           (Emission       **emission_list_p,
137                                                         Emission        *emission);
138static inline void              emission_pop            (Emission       **emission_list_p,
139                                                         Emission        *emission);
140static inline Emission*         emission_find           (Emission        *emission_list,
141                                                         guint            signal_id,
142                                                         GQuark           detail,
143                                                         gpointer         instance);
144static gint                     class_closures_cmp      (gconstpointer    node1,
145                                                         gconstpointer    node2);
146static gint                     signal_key_cmp          (gconstpointer    node1,
147                                                         gconstpointer    node2);
148static        gboolean          signal_emit_unlocked_R  (SignalNode      *node,
149                                                         GQuark           detail,
150                                                         gpointer         instance,
151                                                         GValue          *return_value,
152                                                         const GValue    *instance_and_params);
153static const gchar *            type_debug_name         (GType            type);
154
155
156/* --- structures --- */
157typedef struct
158{
159  GSignalAccumulator func;
160  gpointer           data;
161} SignalAccumulator;
162typedef struct
163{
164  GHook hook;
165  GQuark detail;
166} SignalHook;
167#define SIGNAL_HOOK(hook)       ((SignalHook*) (hook))
168
169struct _SignalNode
170{
171  /* permanent portion */
172  guint              signal_id;
173  GType              itype;
174  gchar             *name;
175  guint              destroyed : 1;
176 
177  /* reinitializable portion */
178  guint              test_class_offset : 12;
179  guint              flags : 8;
180  guint              n_params : 8;
181  GType             *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
182  GType              return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
183  GBSearchArray     *class_closure_bsa;
184  SignalAccumulator *accumulator;
185  GSignalCMarshaller c_marshaller;
186  GHookList         *emission_hooks;
187};
188#define MAX_TEST_CLASS_OFFSET   (4096)  /* 2^12, 12 bits for test_class_offset */
189#define TEST_CLASS_MAGIC        (1)     /* indicates NULL class closure, candidate for NOP optimization */
190
191struct _SignalKey
192{
193  GType  itype;
194  GQuark quark;
195  guint  signal_id;
196};
197
198struct _Emission
199{
200  Emission             *next;
201  gpointer              instance;
202  GSignalInvocationHint ihint;
203  EmissionState         state;
204  GType                 chain_type;
205};
206
207struct _HandlerList
208{
209  guint    signal_id;
210  Handler *handlers;
211  Handler *tail_before;  /* normal signal handlers are appended here  */
212  Handler *tail_after;   /* CONNECT_AFTER handlers are appended here  */
213};
214
215struct _Handler
216{
217  gulong        sequential_number;
218  Handler      *next;
219  Handler      *prev;
220  GQuark        detail;
221  guint         ref_count : 16;
222#define HANDLER_MAX_REF_COUNT   (1 << 16)
223  guint         block_count : 12;
224#define HANDLER_MAX_BLOCK_COUNT (1 << 12)
225  guint         after : 1;
226  GClosure     *closure;
227};
228struct _HandlerMatch
229{
230  Handler      *handler;
231  HandlerMatch *next;
232  union {
233    guint       signal_id;
234    gpointer    dummy;
235  } d;
236};
237
238typedef struct
239{
240  GType     instance_type; /* 0 for default closure */
241  GClosure *closure;
242} ClassClosure;
243
244
245/* --- variables --- */
246static GBSearchArray *g_signal_key_bsa = NULL;
247static const GBSearchConfig g_signal_key_bconfig = {
248  sizeof (SignalKey),
249  signal_key_cmp,
250  G_BSEARCH_ARRAY_ALIGN_POWER2,
251};
252static GBSearchConfig g_signal_hlbsa_bconfig = {
253  sizeof (HandlerList),
254  handler_lists_cmp,
255  0,
256};
257static GBSearchConfig g_class_closure_bconfig = {
258  sizeof (ClassClosure),
259  class_closures_cmp,
260  0,
261};
262static GHashTable    *g_handler_list_bsa_ht = NULL;
263static Emission      *g_recursive_emissions = NULL;
264static Emission      *g_restart_emissions = NULL;
265#ifndef DISABLE_MEM_POOLS
266static GTrashStack   *g_handler_ts = NULL;
267#endif
268static gulong         g_handler_sequential_number = 1;
269G_LOCK_DEFINE_STATIC (g_signal_mutex);
270#define SIGNAL_LOCK()           G_LOCK (g_signal_mutex)
271#define SIGNAL_UNLOCK()         G_UNLOCK (g_signal_mutex)
272
273
274/* --- signal nodes --- */
275static guint          g_n_signal_nodes = 0;
276static SignalNode   **g_signal_nodes = NULL;
277
278static inline SignalNode*
279LOOKUP_SIGNAL_NODE (register guint signal_id)
280{
281  if (signal_id < g_n_signal_nodes)
282    return g_signal_nodes[signal_id];
283  else
284    return NULL;
285}
286
287
288/* --- functions --- */
289static inline guint
290signal_id_lookup (GQuark quark,
291                  GType  itype)
292{
293  GType *ifaces, type = itype;
294  SignalKey key;
295  guint n_ifaces;
296
297  key.quark = quark;
298
299  /* try looking up signals for this type and its anchestors */
300  do
301    {
302      SignalKey *signal_key;
303     
304      key.itype = type;
305      signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
306     
307      if (signal_key)
308        return signal_key->signal_id;
309     
310      type = g_type_parent (type);
311    }
312  while (type);
313
314  /* no luck, try interfaces it exports */
315  ifaces = g_type_interfaces (itype, &n_ifaces);
316  while (n_ifaces--)
317    {
318      SignalKey *signal_key;
319
320      key.itype = ifaces[n_ifaces];
321      signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
322
323      if (signal_key)
324        {
325          g_free (ifaces);
326          return signal_key->signal_id;
327        }
328    }
329  g_free (ifaces);
330 
331  return 0;
332}
333
334static gint
335class_closures_cmp (gconstpointer node1,
336                    gconstpointer node2)
337{
338  const ClassClosure *c1 = node1, *c2 = node2;
339 
340  return G_BSEARCH_ARRAY_CMP (c1->instance_type, c2->instance_type);
341}
342
343static gint
344handler_lists_cmp (gconstpointer node1,
345                   gconstpointer node2)
346{
347  const HandlerList *hlist1 = node1, *hlist2 = node2;
348 
349  return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
350}
351
352static inline HandlerList*
353handler_list_ensure (guint    signal_id,
354                     gpointer instance)
355{
356  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
357  HandlerList key;
358 
359  key.signal_id = signal_id;
360  key.handlers    = NULL;
361  key.tail_before = NULL;
362  key.tail_after  = NULL;
363  if (!hlbsa)
364    {
365      hlbsa = g_bsearch_array_create (&g_signal_hlbsa_bconfig);
366      hlbsa = g_bsearch_array_insert (hlbsa, &g_signal_hlbsa_bconfig, &key);
367      g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
368    }
369  else
370    {
371      GBSearchArray *o = hlbsa;
372
373      hlbsa = g_bsearch_array_insert (o, &g_signal_hlbsa_bconfig, &key);
374      if (hlbsa != o)
375        g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
376    }
377  return g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key);
378}
379
380static inline HandlerList*
381handler_list_lookup (guint    signal_id,
382                     gpointer instance)
383{
384  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
385  HandlerList key;
386 
387  key.signal_id = signal_id;
388 
389  return hlbsa ? g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key) : NULL;
390}
391
392static Handler*
393handler_lookup (gpointer instance,
394                gulong   handler_id,
395                guint   *signal_id_p)
396{
397  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
398 
399  if (hlbsa)
400    {
401      guint i;
402     
403      for (i = 0; i < hlbsa->n_nodes; i++)
404        {
405          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
406          Handler *handler;
407         
408          for (handler = hlist->handlers; handler; handler = handler->next)
409            if (handler->sequential_number == handler_id)
410              {
411                if (signal_id_p)
412                  *signal_id_p = hlist->signal_id;
413               
414                return handler;
415              }
416        }
417    }
418 
419  return NULL;
420}
421
422static inline HandlerMatch*
423handler_match_prepend (HandlerMatch *list,
424                       Handler      *handler,
425                       guint         signal_id)
426{
427  HandlerMatch *node;
428 
429  /* yeah, we could use our own memchunk here, introducing yet more
430   * rarely used cached nodes and extra allocation overhead.
431   * instead, we use GList* nodes, since they are exactly the size
432   * we need and are already cached. g_signal_init() asserts this.
433   */
434  node = (HandlerMatch*) g_list_alloc ();
435  node->handler = handler;
436  node->next = list;
437  node->d.signal_id = signal_id;
438  handler_ref (handler);
439 
440  return node;
441}
442static inline HandlerMatch*
443handler_match_free1_R (HandlerMatch *node,
444                       gpointer      instance)
445{
446  HandlerMatch *next = node->next;
447 
448  handler_unref_R (node->d.signal_id, instance, node->handler);
449  g_list_free_1 ((GList*) node);
450 
451  return next;
452}
453
454static HandlerMatch*
455handlers_find (gpointer         instance,
456               GSignalMatchType mask,
457               guint            signal_id,
458               GQuark           detail,
459               GClosure        *closure,
460               gpointer         func,
461               gpointer         data,
462               gboolean         one_and_only)
463{
464  HandlerMatch *mlist = NULL;
465 
466  if (mask & G_SIGNAL_MATCH_ID)
467    {
468      HandlerList *hlist = handler_list_lookup (signal_id, instance);
469      Handler *handler;
470      SignalNode *node = NULL;
471     
472      if (mask & G_SIGNAL_MATCH_FUNC)
473        {
474          node = LOOKUP_SIGNAL_NODE (signal_id);
475          if (!node || !node->c_marshaller)
476            return NULL;
477        }
478     
479      mask = ~mask;
480      for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
481        if (handler->sequential_number &&
482            ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
483            ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
484            ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
485            ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
486            ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
487                                              handler->closure->meta_marshal == 0 &&
488                                              ((GCClosure*) handler->closure)->callback == func)))
489          {
490            mlist = handler_match_prepend (mlist, handler, signal_id);
491            if (one_and_only)
492              return mlist;
493          }
494    }
495  else
496    {
497      GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
498     
499      mask = ~mask;
500      if (hlbsa)
501        {
502          guint i;
503         
504          for (i = 0; i < hlbsa->n_nodes; i++)
505            {
506              HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
507              SignalNode *node = NULL;
508              Handler *handler;
509             
510              if (!(mask & G_SIGNAL_MATCH_FUNC))
511                {
512                  node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
513                  if (!node->c_marshaller)
514                    continue;
515                }
516             
517              for (handler = hlist->handlers; handler; handler = handler->next)
518                if (handler->sequential_number &&
519                    ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
520                    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
521                    ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
522                    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
523                    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
524                                                      handler->closure->meta_marshal == 0 &&
525                                                      ((GCClosure*) handler->closure)->callback == func)))
526                  {
527                    mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
528                    if (one_and_only)
529                      return mlist;
530                  }
531            }
532        }
533    }
534 
535  return mlist;
536}
537
538static inline Handler*
539handler_new (gboolean after)
540{
541  Handler *handler = g_generic_node_alloc (&g_handler_ts,
542                                           sizeof (Handler),
543                                           HANDLER_PRE_ALLOC);
544#ifndef G_DISABLE_CHECKS
545  if (g_handler_sequential_number < 1)
546    g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
547#endif
548 
549  handler->sequential_number = g_handler_sequential_number++;
550  handler->prev = NULL;
551  handler->next = NULL;
552  handler->detail = 0;
553  handler->ref_count = 1;
554  handler->block_count = 0;
555  handler->after = after != FALSE;
556  handler->closure = NULL;
557 
558  return handler;
559}
560
561static inline void
562handler_ref (Handler *handler)
563{
564  g_return_if_fail (handler->ref_count > 0);
565 
566#ifndef G_DISABLE_CHECKS
567  if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
568    g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
569#endif
570 
571  handler->ref_count += 1;
572}
573
574static inline void
575handler_unref_R (guint    signal_id,
576                 gpointer instance,
577                 Handler *handler)
578{
579  g_return_if_fail (handler->ref_count > 0);
580 
581  handler->ref_count -= 1;
582  if (!handler->ref_count)
583    {
584      HandlerList *hlist = NULL;
585
586      if (handler->next)
587        handler->next->prev = handler->prev;
588      if (handler->prev)    /* watch out for g_signal_handlers_destroy()! */
589        handler->prev->next = handler->next;
590      else
591        {
592          hlist = handler_list_lookup (signal_id, instance);
593          hlist->handlers = handler->next;
594        }
595
596      if (instance)
597        {
598          /*  check if we are removing the handler pointed to by tail_before  */
599          if (!handler->after && (!handler->next || handler->next->after))
600            {
601              if (!hlist)
602                hlist = handler_list_lookup (signal_id, instance);
603              if (hlist)
604                {
605                  g_assert (hlist->tail_before == handler); /* paranoid */
606                  hlist->tail_before = handler->prev;
607                }
608            }
609
610          /*  check if we are removing the handler pointed to by tail_after  */
611          if (!handler->next)
612            {
613              if (!hlist)
614                hlist = handler_list_lookup (signal_id, instance);
615              if (hlist)
616                {
617                  g_assert (hlist->tail_after == handler); /* paranoid */
618                  hlist->tail_after = handler->prev;
619                }
620            }
621        }
622
623      SIGNAL_UNLOCK ();
624      g_closure_unref (handler->closure);
625      SIGNAL_LOCK ();
626      g_generic_node_free (&g_handler_ts, handler);
627    }
628}
629
630static void
631handler_insert (guint    signal_id,
632                gpointer instance,
633                Handler  *handler)
634{
635  HandlerList *hlist;
636 
637  g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
638 
639  hlist = handler_list_ensure (signal_id, instance);
640  if (!hlist->handlers)
641    {
642      hlist->handlers = handler;
643      if (!handler->after)
644        hlist->tail_before = handler;
645    }
646  else if (handler->after)
647    {
648      handler->prev = hlist->tail_after;
649      hlist->tail_after->next = handler;
650    }
651  else
652    {
653      if (hlist->tail_before)
654        {
655          handler->next = hlist->tail_before->next;
656          if (handler->next)
657            handler->next->prev = handler;
658          handler->prev = hlist->tail_before;
659          hlist->tail_before->next = handler;
660        }
661      else /* insert !after handler into a list of only after handlers */
662        {
663          handler->next = hlist->handlers;
664          if (handler->next)
665            handler->next->prev = handler;
666          hlist->handlers = handler;
667        }
668      hlist->tail_before = handler;
669    }
670
671  if (!handler->next)
672    hlist->tail_after = handler;
673}
674
675static inline void
676emission_push (Emission **emission_list_p,
677               Emission  *emission)
678{
679  emission->next = *emission_list_p;
680  *emission_list_p = emission;
681}
682
683static inline void
684emission_pop (Emission **emission_list_p,
685              Emission  *emission)
686{
687  Emission *node, *last = NULL;
688
689  for (node = *emission_list_p; node; last = node, node = last->next)
690    if (node == emission)
691      {
692        if (last)
693          last->next = node->next;
694        else
695          *emission_list_p = node->next;
696        return;
697      }
698  g_assert_not_reached ();
699}
700
701static inline Emission*
702emission_find (Emission *emission_list,
703               guint     signal_id,
704               GQuark    detail,
705               gpointer  instance)
706{
707  Emission *emission;
708 
709  for (emission = emission_list; emission; emission = emission->next)
710    if (emission->instance == instance &&
711        emission->ihint.signal_id == signal_id &&
712        emission->ihint.detail == detail)
713      return emission;
714  return NULL;
715}
716
717static inline Emission*
718emission_find_innermost (gpointer instance)
719{
720  Emission *emission, *s = NULL, *c = NULL;
721 
722  for (emission = g_restart_emissions; emission; emission = emission->next)
723    if (emission->instance == instance)
724      {
725        s = emission;
726        break;
727      }
728  for (emission = g_recursive_emissions; emission; emission = emission->next)
729    if (emission->instance == instance)
730      {
731        c = emission;
732        break;
733      }
734  if (!s)
735    return c;
736  else if (!c)
737    return s;
738  else
739    return G_HAVE_GROWING_STACK ? MAX (c, s) : MIN (c, s);
740}
741
742static gint
743signal_key_cmp (gconstpointer node1,
744                gconstpointer node2)
745{
746  const SignalKey *key1 = node1, *key2 = node2;
747 
748  if (key1->itype == key2->itype)
749    return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
750  else
751    return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
752}
753
754void
755g_signal_init (void) /* sync with gtype.c */
756{
757  SIGNAL_LOCK ();
758  if (!g_n_signal_nodes)
759    {
760      /* handler_id_node_prepend() requires this */
761      g_assert (sizeof (GList) == sizeof (HandlerMatch));
762     
763      /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
764      g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
765      g_signal_key_bsa = g_bsearch_array_create (&g_signal_key_bconfig);
766     
767      /* invalid (0) signal_id */
768      g_n_signal_nodes = 1;
769      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
770      g_signal_nodes[0] = NULL;
771    }
772  SIGNAL_UNLOCK ();
773}
774
775void
776_g_signals_destroy (GType itype)
777{
778  guint i;
779 
780  SIGNAL_LOCK ();
781  for (i = 1; i < g_n_signal_nodes; i++)
782    {
783      SignalNode *node = g_signal_nodes[i];
784     
785      if (node->itype == itype)
786        {
787          if (node->destroyed)
788            g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
789                       node->name,
790                       type_debug_name (node->itype));
791          else
792            signal_destroy_R (node);
793        }
794    }
795  SIGNAL_UNLOCK ();
796}
797
798void
799g_signal_stop_emission (gpointer instance,
800                        guint    signal_id,
801                        GQuark   detail)
802{
803  SignalNode *node;
804 
805  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
806  g_return_if_fail (signal_id > 0);
807 
808  SIGNAL_LOCK ();
809  node = LOOKUP_SIGNAL_NODE (signal_id);
810  if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
811    {
812      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
813      SIGNAL_UNLOCK ();
814      return;
815    }
816  if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
817    {
818      Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
819      Emission *emission = emission_find (emission_list, signal_id, detail, instance);
820     
821      if (emission)
822        {
823          if (emission->state == EMISSION_HOOK)
824            g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
825                       node->name, instance);
826          else if (emission->state == EMISSION_RUN)
827            emission->state = EMISSION_STOP;
828        }
829      else
830        g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
831                   node->name, instance);
832    }
833  else
834    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
835  SIGNAL_UNLOCK ();
836}
837
838static void
839signal_finalize_hook (GHookList *hook_list,
840                      GHook     *hook)
841{
842  GDestroyNotify destroy = hook->destroy;
843
844  if (destroy)
845    {
846      hook->destroy = NULL;
847      SIGNAL_UNLOCK ();
848      destroy (hook->data);
849      SIGNAL_LOCK ();
850    }
851}
852
853gulong
854g_signal_add_emission_hook (guint               signal_id,
855                            GQuark              detail,
856                            GSignalEmissionHook hook_func,
857                            gpointer            hook_data,
858                            GDestroyNotify      data_destroy)
859{
860  static gulong seq_hook_id = 1;
861  SignalNode *node;
862  GHook *hook;
863  SignalHook *signal_hook;
864
865  g_return_val_if_fail (signal_id > 0, 0);
866  g_return_val_if_fail (hook_func != NULL, 0);
867
868  SIGNAL_LOCK ();
869  node = LOOKUP_SIGNAL_NODE (signal_id);
870  if (!node || node->destroyed || (node->flags & G_SIGNAL_NO_HOOKS))
871    {
872      g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id);
873      SIGNAL_UNLOCK ();
874      return 0;
875    }
876  if (detail && !(node->flags & G_SIGNAL_DETAILED))
877    {
878      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
879      SIGNAL_UNLOCK ();
880      return 0;
881    }
882  if (!node->emission_hooks)
883    {
884      node->emission_hooks = g_new (GHookList, 1);
885      g_hook_list_init (node->emission_hooks, sizeof (SignalHook));
886      node->emission_hooks->finalize_hook = signal_finalize_hook;
887    }
888  hook = g_hook_alloc (node->emission_hooks);
889  hook->data = hook_data;
890  hook->func = (gpointer) hook_func;
891  hook->destroy = data_destroy;
892  signal_hook = SIGNAL_HOOK (hook);
893  signal_hook->detail = detail;
894  node->emission_hooks->seq_id = seq_hook_id;
895  g_hook_append (node->emission_hooks, hook);
896  seq_hook_id = node->emission_hooks->seq_id;
897  SIGNAL_UNLOCK ();
898
899  return hook->hook_id;
900}
901
902void
903g_signal_remove_emission_hook (guint  signal_id,
904                               gulong hook_id)
905{
906  SignalNode *node;
907
908  g_return_if_fail (signal_id > 0);
909  g_return_if_fail (hook_id > 0);
910
911  SIGNAL_LOCK ();
912  node = LOOKUP_SIGNAL_NODE (signal_id);
913  if (!node || node->destroyed)
914    g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id);
915  else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id))
916    g_warning ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id);
917  SIGNAL_UNLOCK ();
918}
919
920static inline guint
921signal_parse_name (const gchar *name,
922                   GType        itype,
923                   GQuark      *detail_p,
924                   gboolean     force_quark)
925{
926  const gchar *colon = strchr (name, ':');
927  guint signal_id;
928 
929  if (!colon)
930    {
931      signal_id = signal_id_lookup (g_quark_try_string (name), itype);
932      if (signal_id && detail_p)
933        *detail_p = 0;
934    }
935  else if (colon[1] == ':')
936    {
937      gchar buffer[32];
938      guint l = colon - name;
939     
940      if (l < 32)
941        {
942          memcpy (buffer, name, l);
943          buffer[l] = 0;
944          signal_id = signal_id_lookup (g_quark_try_string (buffer), itype);
945        }
946      else
947        {
948          gchar *signal = g_new (gchar, l + 1);
949         
950          memcpy (signal, name, l);
951          signal[l] = 0;
952          signal_id = signal_id_lookup (g_quark_try_string (signal), itype);
953          g_free (signal);
954        }
955     
956      if (signal_id && detail_p)
957        *detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0;
958    }
959  else
960    signal_id = 0;
961  return signal_id;
962}
963
964gboolean
965g_signal_parse_name (const gchar *detailed_signal,
966                     GType        itype,
967                     guint       *signal_id_p,
968                     GQuark      *detail_p,
969                     gboolean     force_detail_quark)
970{
971  SignalNode *node;
972  GQuark detail = 0;
973  guint signal_id;
974 
975  g_return_val_if_fail (detailed_signal != NULL, FALSE);
976  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
977 
978  SIGNAL_LOCK ();
979  signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
980  SIGNAL_UNLOCK ();
981
982  node = signal_id ? LOOKUP_SIGNAL_NODE (signal_id) : NULL;
983  if (!node || node->destroyed ||
984      (detail && !(node->flags & G_SIGNAL_DETAILED)))
985    return FALSE;
986
987  if (signal_id_p)
988    *signal_id_p = signal_id;
989  if (detail_p)
990    *detail_p = detail;
991 
992  return TRUE;
993}
994
995void
996g_signal_stop_emission_by_name (gpointer     instance,
997                                const gchar *detailed_signal)
998{
999  guint signal_id;
1000  GQuark detail = 0;
1001  GType itype;
1002 
1003  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1004  g_return_if_fail (detailed_signal != NULL);
1005 
1006  SIGNAL_LOCK ();
1007  itype = G_TYPE_FROM_INSTANCE (instance);
1008  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1009  if (signal_id)
1010    {
1011      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1012     
1013      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1014        g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1015      else if (!g_type_is_a (itype, node->itype))
1016        g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1017      else
1018        {
1019          Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
1020          Emission *emission = emission_find (emission_list, signal_id, detail, instance);
1021         
1022          if (emission)
1023            {
1024              if (emission->state == EMISSION_HOOK)
1025                g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
1026                           node->name, instance);
1027              else if (emission->state == EMISSION_RUN)
1028                emission->state = EMISSION_STOP;
1029            }
1030          else
1031            g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
1032                       node->name, instance);
1033        }
1034    }
1035  else
1036    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1037  SIGNAL_UNLOCK ();
1038}
1039
1040guint
1041g_signal_lookup (const gchar *name,
1042                 GType        itype)
1043{
1044  guint signal_id;
1045  g_return_val_if_fail (name != NULL, 0);
1046  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
1047 
1048  SIGNAL_LOCK ();
1049  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
1050  SIGNAL_UNLOCK ();
1051  if (!signal_id)
1052    {
1053      /* give elaborate warnings */
1054      if (!g_type_name (itype))
1055        g_warning (G_STRLOC ": unable to lookup signal \"%s\" for invalid type id `%lu'",
1056                   name, itype);
1057      else if (!G_TYPE_IS_INSTANTIATABLE (itype))
1058        g_warning (G_STRLOC ": unable to lookup signal \"%s\" for non instantiatable type `%s'",
1059                   name, g_type_name (itype));
1060      else if (!g_type_class_peek (itype))
1061        g_warning (G_STRLOC ": unable to lookup signal \"%s\" of unloaded type `%s'",
1062                   name, g_type_name (itype));
1063    }
1064 
1065  return signal_id;
1066}
1067
1068guint*
1069g_signal_list_ids (GType  itype,
1070                   guint *n_ids)
1071{
1072  SignalKey *keys;
1073  GArray *result;
1074  guint n_nodes;
1075  guint i;
1076 
1077  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
1078  g_return_val_if_fail (n_ids != NULL, NULL);
1079 
1080  SIGNAL_LOCK ();
1081  keys = g_bsearch_array_get_nth (g_signal_key_bsa, &g_signal_key_bconfig, 0);
1082  n_nodes = g_bsearch_array_get_n_nodes (g_signal_key_bsa);
1083  result = g_array_new (FALSE, FALSE, sizeof (guint));
1084 
1085  for (i = 0; i < n_nodes; i++)
1086    if (keys[i].itype == itype)
1087      {
1088        const gchar *name = g_quark_to_string (keys[i].quark);
1089       
1090        /* Signal names with "_" in them are aliases to the same
1091         * name with "-" instead of "_".
1092         */
1093        if (!strchr (name, '_'))
1094          g_array_append_val (result, keys[i].signal_id);
1095      }
1096  *n_ids = result->len;
1097  SIGNAL_UNLOCK ();
1098  if (!n_nodes)
1099    {
1100      /* give elaborate warnings */
1101      if (!g_type_name (itype))
1102        g_warning (G_STRLOC ": unable to list signals for invalid type id `%lu'",
1103                   itype);
1104      else if (!G_TYPE_IS_INSTANTIATABLE (itype))
1105        g_warning (G_STRLOC ": unable to list signals of non instantiatable type `%s'",
1106                   g_type_name (itype));
1107      else if (!g_type_class_peek (itype))
1108        g_warning (G_STRLOC ": unable to list signals of unloaded type `%s'",
1109                   g_type_name (itype));
1110    }
1111 
1112  return (guint*) g_array_free (result, FALSE);
1113}
1114
1115G_CONST_RETURN gchar*
1116g_signal_name (guint signal_id)
1117{
1118  SignalNode *node;
1119  gchar *name;
1120 
1121  SIGNAL_LOCK ();
1122  node = LOOKUP_SIGNAL_NODE (signal_id);
1123  name = node ? node->name : NULL;
1124  SIGNAL_UNLOCK ();
1125 
1126  return name;
1127}
1128
1129void
1130g_signal_query (guint         signal_id,
1131                GSignalQuery *query)
1132{
1133  SignalNode *node;
1134 
1135  g_return_if_fail (query != NULL);
1136 
1137  SIGNAL_LOCK ();
1138  node = LOOKUP_SIGNAL_NODE (signal_id);
1139  if (!node || node->destroyed)
1140    query->signal_id = 0;
1141  else
1142    {
1143      query->signal_id = node->signal_id;
1144      query->signal_name = node->name;
1145      query->itype = node->itype;
1146      query->signal_flags = node->flags;
1147      query->return_type = node->return_type;
1148      query->n_params = node->n_params;
1149      query->param_types = node->param_types;
1150    }
1151  SIGNAL_UNLOCK ();
1152}
1153
1154guint
1155g_signal_new (const gchar        *signal_name,
1156              GType               itype,
1157              GSignalFlags        signal_flags,
1158              guint               class_offset,
1159              GSignalAccumulator  accumulator,
1160              gpointer            accu_data,
1161              GSignalCMarshaller  c_marshaller,
1162              GType               return_type,
1163              guint               n_params,
1164              ...)
1165{
1166  va_list args;
1167  guint signal_id;
1168
1169  g_return_val_if_fail (signal_name != NULL, 0);
1170 
1171  va_start (args, n_params);
1172
1173  signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
1174                                   class_offset ? g_signal_type_cclosure_new (itype, class_offset) : NULL,
1175                                   accumulator, accu_data, c_marshaller,
1176                                   return_type, n_params, args);
1177
1178  va_end (args);
1179
1180  /* optimize NOP emissions with NULL class handlers */
1181  if (signal_id && G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE &&
1182      class_offset && class_offset < MAX_TEST_CLASS_OFFSET)
1183    {
1184      SignalNode *node;
1185
1186      SIGNAL_LOCK ();
1187      node = LOOKUP_SIGNAL_NODE (signal_id);
1188      node->test_class_offset = class_offset;
1189      SIGNAL_UNLOCK ();
1190    }
1191 
1192  return signal_id;
1193}
1194
1195static inline ClassClosure*
1196signal_find_class_closure (SignalNode *node,
1197                           GType       itype)
1198{
1199  GBSearchArray *bsa = node->class_closure_bsa;
1200  ClassClosure *cc;
1201
1202  if (bsa)
1203    {
1204      ClassClosure key;
1205
1206      /* cc->instance_type is 0 for default closure */
1207     
1208      key.instance_type = itype;
1209      cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key);
1210      while (!cc && key.instance_type)
1211        {
1212          key.instance_type = g_type_parent (key.instance_type);
1213          cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key);
1214        }
1215    }
1216  else
1217    cc = NULL;
1218  return cc;
1219}
1220
1221static inline GClosure*
1222signal_lookup_closure (SignalNode    *node,
1223                       GTypeInstance *instance)
1224{
1225  ClassClosure *cc;
1226
1227  if (node->class_closure_bsa && g_bsearch_array_get_n_nodes (node->class_closure_bsa) == 1)
1228    cc = g_bsearch_array_get_nth (node->class_closure_bsa, &g_class_closure_bconfig, 0);
1229  else
1230    cc = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance));
1231  return cc ? cc->closure : NULL;
1232}
1233
1234static void
1235signal_add_class_closure (SignalNode *node,
1236                          GType       itype,
1237                          GClosure   *closure)
1238{
1239  ClassClosure key;
1240
1241  /* can't optimize NOP emissions with overridden class closures */
1242  node->test_class_offset = 0;
1243
1244  if (!node->class_closure_bsa)
1245    node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig);
1246  key.instance_type = itype;
1247  key.closure = g_closure_ref (closure);
1248  node->class_closure_bsa = g_bsearch_array_insert (node->class_closure_bsa,
1249                                                    &g_class_closure_bconfig,
1250                                                    &key);
1251  g_closure_sink (closure);
1252  if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (closure))
1253    g_closure_set_marshal (closure, node->c_marshaller);
1254}
1255
1256guint
1257g_signal_newv (const gchar       *signal_name,
1258               GType              itype,
1259               GSignalFlags       signal_flags,
1260               GClosure          *class_closure,
1261               GSignalAccumulator accumulator,
1262               gpointer           accu_data,
1263               GSignalCMarshaller c_marshaller,
1264               GType              return_type,
1265               guint              n_params,
1266               GType             *param_types)
1267{
1268  gchar *name;
1269  guint signal_id, i;
1270  SignalNode *node;
1271 
1272  g_return_val_if_fail (signal_name != NULL, 0);
1273  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
1274  if (n_params)
1275    g_return_val_if_fail (param_types != NULL, 0);
1276  g_return_val_if_fail ((return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == 0, 0);
1277  if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1278    g_return_val_if_fail (accumulator == NULL, 0);
1279  if (!accumulator)
1280    g_return_val_if_fail (accu_data == NULL, 0);
1281
1282  name = g_strdup (signal_name);
1283  g_strdelimit (name, G_STR_DELIMITERS ":^", '_');  /* FIXME do character checks like for types */
1284 
1285  SIGNAL_LOCK ();
1286 
1287  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
1288  node = LOOKUP_SIGNAL_NODE (signal_id);
1289  if (node && !node->destroyed)
1290    {
1291      g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
1292                 name,
1293                 type_debug_name (node->itype),
1294                 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
1295      g_free (name);
1296      SIGNAL_UNLOCK ();
1297      return 0;
1298    }
1299  if (node && node->itype != itype)
1300    {
1301      g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
1302                 name,
1303                 type_debug_name (itype),
1304                 type_debug_name (node->itype));
1305      g_free (name);
1306      SIGNAL_UNLOCK ();
1307      return 0;
1308    }
1309  for (i = 0; i < n_params; i++)
1310    if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1311      {
1312        g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
1313                   i + 1, type_debug_name (param_types[i]), type_debug_name (itype), name);
1314        g_free (name);
1315        SIGNAL_UNLOCK ();
1316        return 0;
1317      }
1318  if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1319    {
1320      g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
1321                 type_debug_name (return_type), type_debug_name (itype), name);
1322      g_free (name);
1323      SIGNAL_UNLOCK ();
1324      return 0;
1325    }
1326  if (return_type != G_TYPE_NONE &&
1327      (signal_flags & (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP)) == G_SIGNAL_RUN_FIRST)
1328    {
1329      g_warning (G_STRLOC ": signal \"%s::%s\" has return type `%s' and is only G_SIGNAL_RUN_FIRST",
1330                 type_debug_name (itype), name, type_debug_name (return_type));
1331      g_free (name);
1332      SIGNAL_UNLOCK ();
1333      return 0;
1334    }
1335 
1336  /* setup permanent portion of signal node */
1337  if (!node)
1338    {
1339      SignalKey key;
1340     
1341      signal_id = g_n_signal_nodes++;
1342      node = g_new (SignalNode, 1);
1343      node->signal_id = signal_id;
1344      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
1345      g_signal_nodes[signal_id] = node;
1346      node->itype = itype;
1347      node->name = name;
1348      key.itype = itype;
1349      key.quark = g_quark_from_string (node->name);
1350      key.signal_id = signal_id;
1351      g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key);
1352      g_strdelimit (node->name, "_", '-');
1353      key.quark = g_quark_from_static_string (node->name);
1354      g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key);
1355    }
1356  node->destroyed = FALSE;
1357  node->test_class_offset = 0;
1358
1359  /* setup reinitializable portion */
1360  node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
1361  node->n_params = n_params;
1362  node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
1363  node->return_type = return_type;
1364  node->class_closure_bsa = NULL;
1365  if (accumulator)
1366    {
1367      node->accumulator = g_new (SignalAccumulator, 1);
1368      node->accumulator->func = accumulator;
1369      node->accumulator->data = accu_data;
1370    }
1371  else
1372    node->accumulator = NULL;
1373  node->c_marshaller = c_marshaller;
1374  node->emission_hooks = NULL;
1375  if (class_closure)
1376    signal_add_class_closure (node, 0, class_closure);
1377  else if (G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE)
1378    {
1379      /* optimize NOP emissions */
1380      node->test_class_offset = TEST_CLASS_MAGIC;
1381    }
1382  SIGNAL_UNLOCK ();
1383
1384  return signal_id;
1385}
1386
1387guint
1388g_signal_new_valist (const gchar       *signal_name,
1389                     GType              itype,
1390                     GSignalFlags       signal_flags,
1391                     GClosure          *class_closure,
1392                     GSignalAccumulator accumulator,
1393                     gpointer           accu_data,
1394                     GSignalCMarshaller c_marshaller,
1395                     GType              return_type,
1396                     guint              n_params,
1397                     va_list            args)
1398{
1399  GType *param_types;
1400  guint i;
1401  guint signal_id;
1402
1403  if (n_params > 0)
1404    {
1405      param_types = g_new (GType, n_params);
1406
1407      for (i = 0; i < n_params; i++)
1408        param_types[i] = va_arg (args, GType);
1409    }
1410  else
1411    param_types = NULL;
1412
1413  signal_id = g_signal_newv (signal_name, itype, signal_flags,
1414                             class_closure, accumulator, accu_data, c_marshaller,
1415                             return_type, n_params, param_types);
1416  g_free (param_types);
1417
1418  return signal_id;
1419}
1420
1421static void
1422signal_destroy_R (SignalNode *signal_node)
1423{
1424  SignalNode node = *signal_node;
1425
1426  signal_node->destroyed = TRUE;
1427 
1428  /* reentrancy caution, zero out real contents first */
1429  signal_node->test_class_offset = 0;
1430  signal_node->n_params = 0;
1431  signal_node->param_types = NULL;
1432  signal_node->return_type = 0;
1433  signal_node->class_closure_bsa = NULL;
1434  signal_node->accumulator = NULL;
1435  signal_node->c_marshaller = NULL;
1436  signal_node->emission_hooks = NULL;
1437 
1438#ifdef  G_ENABLE_DEBUG
1439  /* check current emissions */
1440  {
1441    Emission *emission;
1442   
1443    for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
1444         emission; emission = emission->next)
1445      if (emission->ihint.signal_id == node.signal_id)
1446        g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
1447                    node.name, emission->instance);
1448  }
1449#endif
1450 
1451  /* free contents that need to
1452   */
1453  SIGNAL_UNLOCK ();
1454  g_free (node.param_types);
1455  if (node.class_closure_bsa)
1456    {
1457      guint i;
1458
1459      for (i = 0; i < node.class_closure_bsa->n_nodes; i++)
1460        {
1461          ClassClosure *cc = g_bsearch_array_get_nth (node.class_closure_bsa, &g_class_closure_bconfig, i);
1462
1463          g_closure_unref (cc->closure);
1464        }
1465      g_bsearch_array_free (node.class_closure_bsa, &g_class_closure_bconfig);
1466    }
1467  g_free (node.accumulator);
1468  if (node.emission_hooks)
1469    {
1470      g_hook_list_clear (node.emission_hooks);
1471      g_free (node.emission_hooks);
1472    }
1473  SIGNAL_LOCK ();
1474}
1475
1476void
1477g_signal_override_class_closure (guint     signal_id,
1478                                 GType     instance_type,
1479                                 GClosure *class_closure)
1480{
1481  SignalNode *node;
1482 
1483  g_return_if_fail (signal_id > 0);
1484  g_return_if_fail (class_closure != NULL);
1485 
1486  SIGNAL_LOCK ();
1487  node = LOOKUP_SIGNAL_NODE (signal_id);
1488  if (!g_type_is_a (instance_type, node->itype))
1489    g_warning ("%s: type `%s' cannot be overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id);
1490  else
1491    {
1492      ClassClosure *cc = signal_find_class_closure (node, instance_type);
1493     
1494      if (cc && cc->instance_type == instance_type)
1495        g_warning ("%s: type `%s' is already overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id);
1496      else
1497        signal_add_class_closure (node, instance_type, class_closure);
1498    }
1499  SIGNAL_UNLOCK ();
1500}
1501
1502void
1503g_signal_chain_from_overridden (const GValue *instance_and_params,
1504                                GValue       *return_value)
1505{
1506  GType chain_type = 0, restore_type = 0;
1507  Emission *emission = NULL;
1508  GClosure *closure = NULL;
1509  guint n_params = 0;
1510  gpointer instance;
1511 
1512  g_return_if_fail (instance_and_params != NULL);
1513  instance = g_value_peek_pointer (instance_and_params);
1514  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1515 
1516  SIGNAL_LOCK ();
1517  emission = emission_find_innermost (instance);
1518  if (emission)
1519    {
1520      SignalNode *node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id);
1521     
1522      g_assert (node != NULL);  /* paranoid */
1523     
1524      /* we should probably do the same parameter checks as g_signal_emit() here.
1525       */
1526      if (emission->chain_type != G_TYPE_NONE)
1527        {
1528          ClassClosure *cc = signal_find_class_closure (node, emission->chain_type);
1529         
1530          g_assert (cc != NULL);        /* closure currently in call stack */
1531
1532          n_params = node->n_params;
1533          restore_type = cc->instance_type;
1534          cc = signal_find_class_closure (node, g_type_parent (cc->instance_type));
1535          if (cc && cc->instance_type != restore_type)
1536            {
1537              closure = cc->closure;
1538              chain_type = cc->instance_type;
1539            }
1540        }
1541      else
1542        g_warning ("%s: signal id `%u' cannot be chained from current emission stage for instance `%p'", G_STRLOC, node->signal_id, instance);
1543    }
1544  else
1545    g_warning ("%s: no signal is currently being emitted for instance `%p'", G_STRLOC, instance);
1546  if (closure)
1547    {
1548      emission->chain_type = chain_type;
1549      SIGNAL_UNLOCK ();
1550      g_closure_invoke (closure,
1551                        return_value,
1552                        n_params + 1,
1553                        instance_and_params,
1554                        &emission->ihint);
1555      SIGNAL_LOCK ();
1556      emission->chain_type = restore_type;
1557    }
1558  SIGNAL_UNLOCK ();
1559}
1560
1561GSignalInvocationHint*
1562g_signal_get_invocation_hint (gpointer instance)
1563{
1564  Emission *emission = NULL;
1565 
1566  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), NULL);
1567
1568  SIGNAL_LOCK ();
1569  emission = emission_find_innermost (instance);
1570  SIGNAL_UNLOCK ();
1571 
1572  return emission ? &emission->ihint : NULL;
1573}
1574
1575gulong
1576g_signal_connect_closure_by_id (gpointer  instance,
1577                                guint     signal_id,
1578                                GQuark    detail,
1579                                GClosure *closure,
1580                                gboolean  after)
1581{
1582  SignalNode *node;
1583  gulong handler_seq_no = 0;
1584 
1585  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1586  g_return_val_if_fail (signal_id > 0, 0);
1587  g_return_val_if_fail (closure != NULL, 0);
1588 
1589  SIGNAL_LOCK ();
1590  node = LOOKUP_SIGNAL_NODE (signal_id);
1591  if (node)
1592    {
1593      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1594        g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1595      else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1596        g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1597      else
1598        {
1599          Handler *handler = handler_new (after);
1600         
1601          handler_seq_no = handler->sequential_number;
1602          handler->detail = detail;
1603          handler->closure = g_closure_ref (closure);
1604          g_closure_sink (closure);
1605          handler_insert (signal_id, instance, handler);
1606          if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
1607            g_closure_set_marshal (closure, node->c_marshaller);
1608        }
1609    }
1610  else
1611    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1612  SIGNAL_UNLOCK ();
1613 
1614  return handler_seq_no;
1615}
1616
1617gulong
1618g_signal_connect_closure (gpointer     instance,
1619                          const gchar *detailed_signal,
1620                          GClosure    *closure,
1621                          gboolean     after)
1622{
1623  guint signal_id;
1624  gulong handler_seq_no = 0;
1625  GQuark detail = 0;
1626  GType itype;
1627
1628  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1629  g_return_val_if_fail (detailed_signal != NULL, 0);
1630  g_return_val_if_fail (closure != NULL, 0);
1631
1632  SIGNAL_LOCK ();
1633  itype = G_TYPE_FROM_INSTANCE (instance);
1634  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1635  if (signal_id)
1636    {
1637      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1638
1639      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1640        g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1641      else if (!g_type_is_a (itype, node->itype))
1642        g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1643      else
1644        {
1645          Handler *handler = handler_new (after);
1646
1647          handler_seq_no = handler->sequential_number;
1648          handler->detail = detail;
1649          handler->closure = g_closure_ref (closure);
1650          g_closure_sink (closure);
1651          handler_insert (signal_id, instance, handler);
1652          if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1653            g_closure_set_marshal (handler->closure, node->c_marshaller);
1654        }
1655    }
1656  else
1657    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1658  SIGNAL_UNLOCK ();
1659
1660  return handler_seq_no;
1661}
1662
1663gulong
1664g_signal_connect_data (gpointer       instance,
1665                       const gchar   *detailed_signal,
1666                       GCallback      c_handler,
1667                       gpointer       data,
1668                       GClosureNotify destroy_data,
1669                       GConnectFlags  connect_flags)
1670{
1671  guint signal_id;
1672  gulong handler_seq_no = 0;
1673  GQuark detail = 0;
1674  GType itype;
1675  gboolean swapped, after;
1676 
1677  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1678  g_return_val_if_fail (detailed_signal != NULL, 0);
1679  g_return_val_if_fail (c_handler != NULL, 0);
1680
1681  swapped = (connect_flags & G_CONNECT_SWAPPED) != FALSE;
1682  after = (connect_flags & G_CONNECT_AFTER) != FALSE;
1683
1684  SIGNAL_LOCK ();
1685  itype = G_TYPE_FROM_INSTANCE (instance);
1686  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1687  if (signal_id)
1688    {
1689      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1690
1691      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1692        g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1693      else if (!g_type_is_a (itype, node->itype))
1694        g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1695      else
1696        {
1697          Handler *handler = handler_new (after);
1698
1699          handler_seq_no = handler->sequential_number;
1700          handler->detail = detail;
1701          handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
1702          g_closure_sink (handler->closure);
1703          handler_insert (signal_id, instance, handler);
1704          if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1705            g_closure_set_marshal (handler->closure, node->c_marshaller);
1706        }
1707    }
1708  else
1709    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1710  SIGNAL_UNLOCK ();
1711
1712  return handler_seq_no;
1713}
1714
1715void
1716g_signal_handler_block (gpointer instance,
1717                        gulong   handler_id)
1718{
1719  Handler *handler;
1720 
1721  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1722  g_return_if_fail (handler_id > 0);
1723 
1724  SIGNAL_LOCK ();
1725  handler = handler_lookup (instance, handler_id, NULL);
1726  if (handler)
1727    {
1728#ifndef G_DISABLE_CHECKS
1729      if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
1730        g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
1731#endif
1732      handler->block_count += 1;
1733    }
1734  else
1735    g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id);
1736  SIGNAL_UNLOCK ();
1737}
1738
1739void
1740g_signal_handler_unblock (gpointer instance,
1741                          gulong   handler_id)
1742{
1743  Handler *handler;
1744 
1745  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1746  g_return_if_fail (handler_id > 0);
1747 
1748  SIGNAL_LOCK ();
1749  handler = handler_lookup (instance, handler_id, NULL);
1750  if (handler)
1751    {
1752      if (handler->block_count)
1753        handler->block_count -= 1;
1754      else
1755        g_warning (G_STRLOC ": handler `%lu' of instance `%p' is not blocked", handler_id, instance);
1756    }
1757  else
1758    g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id);
1759  SIGNAL_UNLOCK ();
1760}
1761
1762void
1763g_signal_handler_disconnect (gpointer instance,
1764                             gulong   handler_id)
1765{
1766  Handler *handler;
1767  guint signal_id;
1768 
1769  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1770  g_return_if_fail (handler_id > 0);
1771 
1772  SIGNAL_LOCK ();
1773  handler = handler_lookup (instance, handler_id, &signal_id);
1774  if (handler)
1775    {
1776      handler->sequential_number = 0;
1777      handler->block_count = 1;
1778      handler_unref_R (signal_id, instance, handler);
1779    }
1780  else
1781    g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id);
1782  SIGNAL_UNLOCK ();
1783}
1784
1785gboolean
1786g_signal_handler_is_connected (gpointer instance,
1787                               gulong   handler_id)
1788{
1789  Handler *handler;
1790  gboolean connected;
1791
1792  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1793
1794  SIGNAL_LOCK ();
1795  handler = handler_lookup (instance, handler_id, NULL);
1796  connected = handler != NULL;
1797  SIGNAL_UNLOCK ();
1798
1799  return connected;
1800}
1801
1802void
1803g_signal_handlers_destroy (gpointer instance)
1804{
1805  GBSearchArray *hlbsa;
1806 
1807  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1808 
1809  SIGNAL_LOCK ();
1810  hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
1811  if (hlbsa)
1812    {
1813      guint i;
1814     
1815      /* reentrancy caution, delete instance trace first */
1816      g_hash_table_remove (g_handler_list_bsa_ht, instance);
1817     
1818      for (i = 0; i < hlbsa->n_nodes; i++)
1819        {
1820          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
1821          Handler *handler = hlist->handlers;
1822         
1823          while (handler)
1824            {
1825              Handler *tmp = handler;
1826             
1827              handler = tmp->next;
1828              tmp->block_count = 1;
1829              /* cruel unlink, this works because _all_ handlers vanish */
1830              tmp->next = NULL;
1831              tmp->prev = tmp;
1832              if (tmp->sequential_number)
1833                {
1834                  tmp->sequential_number = 0;
1835                  handler_unref_R (0, NULL, tmp);
1836                }
1837            }
1838        }
1839      g_bsearch_array_free (hlbsa, &g_signal_hlbsa_bconfig);
1840    }
1841  SIGNAL_UNLOCK ();
1842}
1843
1844gulong
1845g_signal_handler_find (gpointer         instance,
1846                       GSignalMatchType mask,
1847                       guint            signal_id,
1848                       GQuark           detail,
1849                       GClosure        *closure,
1850                       gpointer         func,
1851                       gpointer         data)
1852{
1853  gulong handler_seq_no = 0;
1854 
1855  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1856  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1857 
1858  if (mask & G_SIGNAL_MATCH_MASK)
1859    {
1860      HandlerMatch *mlist;
1861     
1862      SIGNAL_LOCK ();
1863      mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
1864      if (mlist)
1865        {
1866          handler_seq_no = mlist->handler->sequential_number;
1867          handler_match_free1_R (mlist, instance);
1868        }
1869      SIGNAL_UNLOCK ();
1870    }
1871 
1872  return handler_seq_no;
1873}
1874
1875static guint
1876signal_handlers_foreach_matched_R (gpointer         instance,
1877                                   GSignalMatchType mask,
1878                                   guint            signal_id,
1879                                   GQuark           detail,
1880                                   GClosure        *closure,
1881                                   gpointer         func,
1882                                   gpointer         data,
1883                                   void           (*callback) (gpointer instance,
1884                                                               gulong   handler_seq_no))
1885{
1886  HandlerMatch *mlist;
1887  guint n_handlers = 0;
1888 
1889  mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
1890  while (mlist)
1891    {
1892      n_handlers++;
1893      if (mlist->handler->sequential_number)
1894        {
1895          SIGNAL_UNLOCK ();
1896          callback (instance, mlist->handler->sequential_number);
1897          SIGNAL_LOCK ();
1898        }
1899      mlist = handler_match_free1_R (mlist, instance);
1900    }
1901 
1902  return n_handlers;
1903}
1904
1905guint
1906g_signal_handlers_block_matched (gpointer         instance,
1907                                 GSignalMatchType mask,
1908                                 guint            signal_id,
1909                                 GQuark           detail,
1910                                 GClosure        *closure,
1911                                 gpointer         func,
1912                                 gpointer         data)
1913{
1914  guint n_handlers = 0;
1915 
1916  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1917  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1918 
1919  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1920    {
1921      SIGNAL_LOCK ();
1922      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1923                                                      closure, func, data,
1924                                                      g_signal_handler_block);
1925      SIGNAL_UNLOCK ();
1926    }
1927 
1928  return n_handlers;
1929}
1930
1931guint
1932g_signal_handlers_unblock_matched (gpointer         instance,
1933                                   GSignalMatchType mask,
1934                                   guint            signal_id,
1935                                   GQuark           detail,
1936                                   GClosure        *closure,
1937                                   gpointer         func,
1938                                   gpointer         data)
1939{
1940  guint n_handlers = 0;
1941 
1942  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1943  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1944 
1945  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1946    {
1947      SIGNAL_LOCK ();
1948      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1949                                                      closure, func, data,
1950                                                      g_signal_handler_unblock);
1951      SIGNAL_UNLOCK ();
1952    }
1953 
1954  return n_handlers;
1955}
1956
1957guint
1958g_signal_handlers_disconnect_matched (gpointer         instance,
1959                                      GSignalMatchType mask,
1960                                      guint            signal_id,
1961                                      GQuark           detail,
1962                                      GClosure        *closure,
1963                                      gpointer         func,
1964                                      gpointer         data)
1965{
1966  guint n_handlers = 0;
1967 
1968  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1969  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1970 
1971  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1972    {
1973      SIGNAL_LOCK ();
1974      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
1975                                                      closure, func, data,
1976                                                      g_signal_handler_disconnect);
1977      SIGNAL_UNLOCK ();
1978    }
1979 
1980  return n_handlers;
1981}
1982
1983gboolean
1984g_signal_has_handler_pending (gpointer instance,
1985                              guint    signal_id,
1986                              GQuark   detail,
1987                              gboolean may_be_blocked)
1988{
1989  HandlerMatch *mlist;
1990  gboolean has_pending;
1991 
1992  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1993  g_return_val_if_fail (signal_id > 0, FALSE);
1994 
1995  SIGNAL_LOCK ();
1996  if (detail)
1997    {
1998      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1999     
2000      if (!(node->flags & G_SIGNAL_DETAILED))
2001        {
2002          g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
2003          SIGNAL_UNLOCK ();
2004          return FALSE;
2005        }
2006    }
2007  mlist = handlers_find (instance,
2008                         (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
2009                         signal_id, detail, NULL, NULL, NULL, TRUE);
2010  if (mlist)
2011    {
2012      has_pending = TRUE;
2013      handler_match_free1_R (mlist, instance);
2014    }
2015  else
2016    has_pending = FALSE;
2017  SIGNAL_UNLOCK ();
2018 
2019  return has_pending;
2020}
2021
2022static inline gboolean
2023signal_check_skip_emission (SignalNode *node,
2024                            gpointer    instance,
2025                            GQuark      detail)
2026{
2027  HandlerList *hlist;
2028
2029  /* are we able to check for NULL class handlers? */
2030  if (!node->test_class_offset)
2031    return FALSE;
2032
2033  /* are there emission hooks pending? */
2034  if (node->emission_hooks && node->emission_hooks->hooks)
2035    return FALSE;
2036
2037  /* is there a non-NULL class handler? */
2038  if (node->test_class_offset != TEST_CLASS_MAGIC)
2039    {
2040      GTypeClass *class = G_TYPE_INSTANCE_GET_CLASS (instance, G_TYPE_FROM_INSTANCE (instance), GTypeClass);
2041
2042      if (G_STRUCT_MEMBER (gpointer, class, node->test_class_offset))
2043        return FALSE;
2044    }
2045
2046  /* are signals being debugged? */
2047#ifdef  G_ENABLE_DEBUG
2048  IF_DEBUG (SIGNALS, g_trace_instance_signals || g_trap_instance_signals)
2049    return FALSE;
2050#endif /* G_ENABLE_DEBUG */
2051
2052  /* is this a no-recurse signal already in emission? */
2053  if (node->flags & G_SIGNAL_NO_RECURSE &&
2054      emission_find (g_restart_emissions, node->signal_id, detail, instance))
2055    return FALSE;
2056
2057  /* do we have pending handlers? */
2058  hlist = handler_list_lookup (node->signal_id, instance);
2059  if (hlist && hlist->handlers)
2060    return FALSE;
2061
2062  /* none of the above, no emission required */
2063  return TRUE;
2064}
2065
2066void
2067g_signal_emitv (const GValue *instance_and_params,
2068                guint         signal_id,
2069                GQuark        detail,
2070                GValue       *return_value)
2071{
2072  const GValue *param_values;
2073  gpointer instance;
2074  SignalNode *node;
2075#ifdef G_ENABLE_DEBUG
2076  guint i;
2077#endif
2078 
2079  g_return_if_fail (instance_and_params != NULL);
2080  instance = g_value_peek_pointer (instance_and_params);
2081  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2082  g_return_if_fail (signal_id > 0);
2083
2084  param_values = instance_and_params + 1;
2085 
2086  SIGNAL_LOCK ();
2087  node = LOOKUP_SIGNAL_NODE (signal_id);
2088  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
2089    {
2090      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
2091      SIGNAL_UNLOCK ();
2092      return;
2093    }
2094#ifdef G_ENABLE_DEBUG
2095  if (detail && !(node->flags & G_SIGNAL_DETAILED))
2096    {
2097      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
2098      SIGNAL_UNLOCK ();
2099      return;
2100    }
2101  for (i = 0; i < node->n_params; i++)
2102    if (!G_TYPE_CHECK_VALUE_TYPE (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
2103      {
2104        g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'",
2105                    G_STRLOC,
2106                    type_debug_name (node->param_types[i]),
2107                    i,
2108                    node->name,
2109                    G_VALUE_TYPE_NAME (param_values + i));
2110        SIGNAL_UNLOCK ();
2111        return;
2112      }
2113  if (node->return_type != G_TYPE_NONE)
2114    {
2115      if (!return_value)
2116        {
2117          g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)",
2118                      G_STRLOC,
2119                      type_debug_name (node->return_type),
2120                      node->name);
2121          SIGNAL_UNLOCK ();
2122          return;
2123        }
2124      else if (!node->accumulator && !G_TYPE_CHECK_VALUE_TYPE (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
2125        {
2126          g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'",
2127                      G_STRLOC,
2128                      type_debug_name (node->return_type),
2129                      node->name,
2130                      G_VALUE_TYPE_NAME (return_value));
2131          SIGNAL_UNLOCK ();
2132          return;
2133        }
2134    }
2135  else
2136    return_value = NULL;
2137#endif  /* G_ENABLE_DEBUG */
2138
2139  /* optimize NOP emissions */
2140  if (signal_check_skip_emission (node, instance, detail))
2141    {
2142      /* nothing to do to emit this signal */
2143      SIGNAL_UNLOCK ();
2144      /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
2145      return;
2146    }
2147
2148  SIGNAL_UNLOCK ();
2149  signal_emit_unlocked_R (node, detail, instance, return_value, instance_and_params);
2150}
2151
2152void
2153g_signal_emit_valist (gpointer instance,
2154                      guint    signal_id,
2155                      GQuark   detail,
2156                      va_list  var_args)
2157{
2158  GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL;
2159  GType signal_return_type;
2160  GValue *param_values;
2161  SignalNode *node;
2162  guint i, n_params;
2163 
2164  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2165  g_return_if_fail (signal_id > 0);
2166
2167  SIGNAL_LOCK ();
2168  node = LOOKUP_SIGNAL_NODE (signal_id);
2169  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
2170    {
2171      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
2172      SIGNAL_UNLOCK ();
2173      return;
2174    }
2175#ifndef G_DISABLE_CHECKS
2176  if (detail && !(node->flags & G_SIGNAL_DETAILED))
2177    {
2178      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
2179      SIGNAL_UNLOCK ();
2180      return;
2181    }
2182#endif  /* !G_DISABLE_CHECKS */
2183
2184  /* optimize NOP emissions */
2185  if (signal_check_skip_emission (node, instance, detail))
2186    {
2187      /* nothing to do to emit this signal */
2188      SIGNAL_UNLOCK ();
2189      /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
2190      return;
2191    }
2192
2193  n_params = node->n_params;
2194  signal_return_type = node->return_type;
2195  if (node->n_params < MAX_STACK_VALUES)
2196    instance_and_params = stack_values;
2197  else
2198    {
2199      free_me = g_new (GValue, node->n_params + 1);
2200      instance_and_params = free_me;
2201    }
2202  param_values = instance_and_params + 1;
2203  for (i = 0; i < node->n_params; i++)
2204    {
2205      gchar *error;
2206      GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
2207      gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
2208     
2209      param_values[i].g_type = 0;
2210      SIGNAL_UNLOCK ();
2211      g_value_init (param_values + i, ptype);
2212      G_VALUE_COLLECT (param_values + i,
2213                       var_args,
2214                       static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
2215                       &error);
2216      if (error)
2217        {
2218          g_warning ("%s: %s", G_STRLOC, error);
2219          g_free (error);
2220
2221          /* we purposely leak the value here, it might not be
2222           * in a sane state if an error condition occoured
2223           */
2224          while (i--)
2225            g_value_unset (param_values + i);
2226
2227          g_free (free_me);
2228          return;
2229        }
2230      SIGNAL_LOCK ();
2231    }
2232  SIGNAL_UNLOCK ();
2233  instance_and_params->g_type = 0;
2234  g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (instance));
2235  g_value_set_instance (instance_and_params, instance);
2236  if (signal_return_type == G_TYPE_NONE)
2237    signal_emit_unlocked_R (node, detail, instance, NULL, instance_and_params);
2238  else
2239    {
2240      GValue return_value = { 0, };
2241      gchar *error = NULL;
2242      GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
2243      gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
2244     
2245      g_value_init (&return_value, rtype);
2246
2247      signal_emit_unlocked_R (node, detail, instance, &return_value, instance_and_params);
2248
2249      G_VALUE_LCOPY (&return_value,
2250                     var_args,
2251                     static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
2252                     &error);
2253      if (!error)
2254        g_value_unset (&return_value);
2255      else
2256        {
2257          g_warning ("%s: %s", G_STRLOC, error);
2258          g_free (error);
2259         
2260          /* we purposely leak the value here, it might not be
2261           * in a sane state if an error condition occoured
2262           */
2263        }
2264    }
2265  for (i = 0; i < n_params; i++)
2266    g_value_unset (param_values + i);
2267  g_value_unset (instance_and_params);
2268  if (free_me)
2269    g_free (free_me);
2270}
2271
2272void
2273g_signal_emit (gpointer instance,
2274               guint    signal_id,
2275               GQuark   detail,
2276               ...)
2277{
2278  va_list var_args;
2279
2280  va_start (var_args, detail);
2281  g_signal_emit_valist (instance, signal_id, detail, var_args);
2282  va_end (var_args);
2283}
2284
2285void
2286g_signal_emit_by_name (gpointer     instance,
2287                       const gchar *detailed_signal,
2288                       ...)
2289{
2290  GQuark detail = 0;
2291  guint signal_id;
2292
2293  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2294  g_return_if_fail (detailed_signal != NULL);
2295
2296  SIGNAL_LOCK ();
2297  signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE);
2298  SIGNAL_UNLOCK ();
2299
2300  if (signal_id)
2301    {
2302      va_list var_args;
2303
2304      va_start (var_args, detailed_signal);
2305      g_signal_emit_valist (instance, signal_id, detail, var_args);
2306      va_end (var_args);
2307    }
2308  else
2309    g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
2310}
2311
2312static inline gboolean
2313accumulate (GSignalInvocationHint *ihint,
2314            GValue                *return_accu,
2315            GValue                *handler_return,
2316            SignalAccumulator     *accumulator)
2317{
2318  gboolean continue_emission;
2319
2320  if (!accumulator)
2321    return TRUE;
2322
2323  continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data);
2324  g_value_reset (handler_return);
2325
2326  return continue_emission;
2327}
2328
2329static gboolean
2330signal_emit_unlocked_R (SignalNode   *node,
2331                        GQuark        detail,
2332                        gpointer      instance,
2333                        GValue       *emission_return,
2334                        const GValue *instance_and_params)
2335{
2336  SignalAccumulator *accumulator;
2337  Emission emission;
2338  GClosure *class_closure;
2339  HandlerList *hlist;
2340  Handler *handler_list = NULL;
2341  GValue *return_accu, accu = { 0, };
2342  guint signal_id;
2343  gulong max_sequential_handler_number;
2344  gboolean return_value_altered = FALSE;
2345 
2346#ifdef  G_ENABLE_DEBUG
2347  IF_DEBUG (SIGNALS, g_trace_instance_signals == instance || g_trap_instance_signals == instance)
2348    {
2349      g_message ("%s::%s(%u) emitted (instance=%p, signal-node=%p)",
2350                 g_type_name (G_TYPE_FROM_INSTANCE (instance)),
2351                 node->name, detail,
2352                 instance, node);
2353      if (g_trap_instance_signals == instance)
2354        G_BREAKPOINT ();
2355    }
2356#endif  /* G_ENABLE_DEBUG */
2357 
2358  SIGNAL_LOCK ();
2359  signal_id = node->signal_id;
2360  if (node->flags & G_SIGNAL_NO_RECURSE)
2361    {
2362      Emission *node = emission_find (g_restart_emissions, signal_id, detail, instance);
2363     
2364      if (node)
2365        {
2366          node->state = EMISSION_RESTART;
2367          SIGNAL_UNLOCK ();
2368          return return_value_altered;
2369        }
2370    }
2371  accumulator = node->accumulator;
2372  if (accumulator)
2373    {
2374      SIGNAL_UNLOCK ();
2375      g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
2376      return_accu = &accu;
2377      SIGNAL_LOCK ();
2378    }
2379  else
2380    return_accu = emission_return;
2381  emission.instance = instance;
2382  emission.ihint.signal_id = node->signal_id;
2383  emission.ihint.detail = detail;
2384  emission.ihint.run_type = 0;
2385  emission.state = 0;
2386  emission.chain_type = G_TYPE_NONE;
2387  emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission);
2388  class_closure = signal_lookup_closure (node, instance);
2389 
2390 EMIT_RESTART:
2391 
2392  if (handler_list)
2393    handler_unref_R (signal_id, instance, handler_list);
2394  max_sequential_handler_number = g_handler_sequential_number;
2395  hlist = handler_list_lookup (signal_id, instance);
2396  handler_list = hlist ? hlist->handlers : NULL;
2397  if (handler_list)
2398    handler_ref (handler_list);
2399 
2400  emission.ihint.run_type = G_SIGNAL_RUN_FIRST;
2401 
2402  if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
2403    {
2404      emission.state = EMISSION_RUN;
2405
2406      emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
2407      SIGNAL_UNLOCK ();
2408      g_closure_invoke (class_closure,
2409                        return_accu,
2410                        node->n_params + 1,
2411                        instance_and_params,
2412                        &emission.ihint);
2413      if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2414          emission.state == EMISSION_RUN)
2415        emission.state = EMISSION_STOP;
2416      SIGNAL_LOCK ();
2417      emission.chain_type = G_TYPE_NONE;
2418      return_value_altered = TRUE;
2419     
2420      if (emission.state == EMISSION_STOP)
2421        goto EMIT_CLEANUP;
2422      else if (emission.state == EMISSION_RESTART)
2423        goto EMIT_RESTART;
2424    }
2425 
2426  if (node->emission_hooks)
2427    {
2428      gboolean need_destroy, was_in_call, may_recurse = TRUE;
2429      GHook *hook;
2430
2431      emission.state = EMISSION_HOOK;
2432      hook = g_hook_first_valid (node->emission_hooks, may_recurse);
2433      while (hook)
2434        {
2435          SignalHook *signal_hook = SIGNAL_HOOK (hook);
2436         
2437          if (!signal_hook->detail || signal_hook->detail == detail)
2438            {
2439              GSignalEmissionHook hook_func = (GSignalEmissionHook) hook->func;
2440             
2441              was_in_call = G_HOOK_IN_CALL (hook);
2442              hook->flags |= G_HOOK_FLAG_IN_CALL;
2443              SIGNAL_UNLOCK ();
2444              need_destroy = !hook_func (&emission.ihint, node->n_params + 1, instance_and_params, hook->data);
2445              SIGNAL_LOCK ();
2446              if (!was_in_call)
2447                hook->flags &= ~G_HOOK_FLAG_IN_CALL;
2448              if (need_destroy)
2449                g_hook_destroy_link (node->emission_hooks, hook);
2450            }
2451          hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse);
2452        }
2453     
2454      if (emission.state == EMISSION_RESTART)
2455        goto EMIT_RESTART;
2456    }
2457 
2458  if (handler_list)
2459    {
2460      Handler *handler = handler_list;
2461     
2462      emission.state = EMISSION_RUN;
2463      handler_ref (handler);
2464      do
2465        {
2466          Handler *tmp;
2467         
2468          if (handler->after)
2469            {
2470              handler_unref_R (signal_id, instance, handler_list);
2471              handler_list = handler;
2472              break;
2473            }
2474          else if (!handler->block_count && (!handler->detail || handler->detail == detail) &&
2475                   handler->sequential_number < max_sequential_handler_number)
2476            {
2477              SIGNAL_UNLOCK ();
2478              g_closure_invoke (handler->closure,
2479                                return_accu,
2480                                node->n_params + 1,
2481                                instance_and_params,
2482                                &emission.ihint);
2483              if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2484                  emission.state == EMISSION_RUN)
2485                emission.state = EMISSION_STOP;
2486              SIGNAL_LOCK ();
2487              return_value_altered = TRUE;
2488             
2489              tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
2490            }
2491          else
2492            tmp = handler->next;
2493         
2494          if (tmp)
2495            handler_ref (tmp);
2496          handler_unref_R (signal_id, instance, handler_list);
2497          handler_list = handler;
2498          handler = tmp;
2499        }
2500      while (handler);
2501     
2502      if (emission.state == EMISSION_STOP)
2503        goto EMIT_CLEANUP;
2504      else if (emission.state == EMISSION_RESTART)
2505        goto EMIT_RESTART;
2506    }
2507 
2508  emission.ihint.run_type = G_SIGNAL_RUN_LAST;
2509 
2510  if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
2511    {
2512      emission.state = EMISSION_RUN;
2513     
2514      emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
2515      SIGNAL_UNLOCK ();
2516      g_closure_invoke (class_closure,
2517                        return_accu,
2518                        node->n_params + 1,
2519                        instance_and_params,
2520                        &emission.ihint);
2521      if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2522          emission.state == EMISSION_RUN)
2523        emission.state = EMISSION_STOP;
2524      SIGNAL_LOCK ();
2525      emission.chain_type = G_TYPE_NONE;
2526      return_value_altered = TRUE;
2527     
2528      if (emission.state == EMISSION_STOP)
2529        goto EMIT_CLEANUP;
2530      else if (emission.state == EMISSION_RESTART)
2531        goto EMIT_RESTART;
2532    }
2533 
2534  if (handler_list)
2535    {
2536      Handler *handler = handler_list;
2537     
2538      emission.state = EMISSION_RUN;
2539      handler_ref (handler);
2540      do
2541        {
2542          Handler *tmp;
2543         
2544          if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail) &&
2545              handler->sequential_number < max_sequential_handler_number)
2546            {
2547              SIGNAL_UNLOCK ();
2548              g_closure_invoke (handler->closure,
2549                                return_accu,
2550                                node->n_params + 1,
2551                                instance_and_params,
2552                                &emission.ihint);
2553              if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2554                  emission.state == EMISSION_RUN)
2555                emission.state = EMISSION_STOP;
2556              SIGNAL_LOCK ();
2557              return_value_altered = TRUE;
2558             
2559              tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
2560            }
2561          else
2562            tmp = handler->next;
2563         
2564          if (tmp)
2565            handler_ref (tmp);
2566          handler_unref_R (signal_id, instance, handler);
2567          handler = tmp;
2568        }
2569      while (handler);
2570     
2571      if (emission.state == EMISSION_STOP)
2572        goto EMIT_CLEANUP;
2573      else if (emission.state == EMISSION_RESTART)
2574        goto EMIT_RESTART;
2575    }
2576 
2577 EMIT_CLEANUP:
2578 
2579  emission.ihint.run_type = G_SIGNAL_RUN_CLEANUP;
2580 
2581  if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
2582    {
2583      gboolean need_unset = FALSE;
2584     
2585      emission.state = EMISSION_STOP;
2586     
2587      emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
2588      SIGNAL_UNLOCK ();
2589      if (node->return_type != G_TYPE_NONE && !accumulator)
2590        {
2591          g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
2592          need_unset = TRUE;
2593        }
2594      g_closure_invoke (class_closure,
2595                        node->return_type != G_TYPE_NONE ? &accu : NULL,
2596                        node->n_params + 1,
2597                        instance_and_params,
2598                        &emission.ihint);
2599      if (need_unset)
2600        g_value_unset (&accu);
2601      SIGNAL_LOCK ();
2602      emission.chain_type = G_TYPE_NONE;
2603     
2604      if (emission.state == EMISSION_RESTART)
2605        goto EMIT_RESTART;
2606    }
2607 
2608  if (handler_list)
2609    handler_unref_R (signal_id, instance, handler_list);
2610 
2611  emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission);
2612  SIGNAL_UNLOCK ();
2613  if (accumulator)
2614    g_value_unset (&accu);
2615 
2616  return return_value_altered;
2617}
2618
2619static const gchar*
2620type_debug_name (GType type)
2621{
2622  if (type)
2623    {
2624      const char *name = g_type_name (type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
2625      return name ? name : "<unknown>";
2626    }
2627  else
2628    return "<invalid>";
2629}
2630
2631gboolean
2632g_signal_accumulator_true_handled (GSignalInvocationHint *ihint,
2633                                   GValue                *return_accu,
2634                                   const GValue          *handler_return,
2635                                   gpointer               dummy)
2636{
2637  gboolean continue_emission;
2638  gboolean signal_handled;
2639 
2640  signal_handled = g_value_get_boolean (handler_return);
2641  g_value_set_boolean (return_accu, signal_handled);
2642  continue_emission = !signal_handled;
2643 
2644  return continue_emission;
2645}
2646
2647/* --- compile standard marshallers --- */
2648#include        "gobject.h"
2649#include        "genums.h"
2650#include        "gmarshal.c"
Note: See TracBrowser for help on using the repository browser.