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

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