gsignal.c revision ca4e2341135a8212ba45f2b3091f6f3cd9302b24
1ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* GObject - GLib Type, Object, Parameter and Signal Library
237e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik * Copyright (C) 2000-2001 Red Hat, Inc.
3ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik *
4ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * This library is free software; you can redistribute it and/or
5ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * modify it under the terms of the GNU Lesser General Public
6ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * License as published by the Free Software Foundation; either
7ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * version 2 of the License, or (at your option) any later version.
8ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik *
9ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * This library is distributed in the hope that it will be useful,
10ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * but WITHOUT ANY WARRANTY; without even the implied warranty of
11ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Lesser General Public License for more details.
13ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik *
14ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * You should have received a copy of the GNU Lesser General
15ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Public License along with this library; if not, write to the
16ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
17ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Boston, MA 02111-1307, USA.
18ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik *
19ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * this code is based on the original GtkSignal implementation
20ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * for the Gtk+ library by Peter Mattis <petm@xcf.berkeley.edu>
21ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */
22f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik
23f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik/*
24f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik * MT safe
25f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik */
26fbe5df779cd39c9587f665118074ac828a805c26Owen Taylor
27d4407e38fae560bae6a66dd9ae5b2f58b9d89134Owen Taylor#include <config.h>
28d4407e38fae560bae6a66dd9ae5b2f58b9d89134Owen Taylor
29465c7d1ead296b70b8d47ca333554a18f71da11dMatthias Clasen#include	"gobjectalias.h"
30ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#include        "gsignal.h"
31ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#include        "gbsearcharray.h"
32e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#include        "gvaluecollector.h"
33617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik#include	"gvaluetypes.h"
34617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik#include	"gboxed.h"
35f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#include	<string.h>
36e1afbb7e037c78b258e563dbdedab3e63d9a7901Tim Janik#include	<signal.h>
37ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
38ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
39ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* pre allocation configurations
40ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */
41e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#define	MAX_STACK_VALUES	(16)
42ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_PRE_ALLOC       (48)
43ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
44160cd96ae26a571e76af717c27ae29b8125a54a5Matthias Clasen#define REPORT_BUG      "please report occurrence circumstances to gtk-devel-list@gnome.org"
4522357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#ifdef	G_ENABLE_DEBUG
4622357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#define IF_DEBUG(debug_type, cond)	if ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || cond)
47115366f6630596afc6f9c858ea9ea61464e92d18Tim Janikstatic volatile gpointer g_trace_instance_signals = NULL;
48115366f6630596afc6f9c858ea9ea61464e92d18Tim Janikstatic volatile gpointer g_trap_instance_signals = NULL;
4922357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#endif	/* G_ENABLE_DEBUG */
50ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
51ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
52ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- generic allocation --- */
53782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik/* we special case allocations generically by replacing
54ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * these functions with more speed/memory aware variants
55ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */
56782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifndef	DISABLE_MEM_POOLS
57ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline gpointer
58ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_generic_node_alloc (GTrashStack **trash_stack_p,
59ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                      guint         sizeof_node,
60ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                      guint         nodes_pre_alloc)
61ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
62ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gpointer node = g_trash_stack_pop (trash_stack_p);
63ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
64ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!node)
65ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
66ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      guint8 *block;
67ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
68ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
69ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      block = g_malloc (sizeof_node * nodes_pre_alloc);
70ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      while (--nodes_pre_alloc)
71ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
72ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          g_trash_stack_push (trash_stack_p, block);
73ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          block += sizeof_node;
74ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
75ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node = block;
76ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
77ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
78ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return node;
79ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
80f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#define	g_generic_node_free(trash_stack_p, node) g_trash_stack_push (trash_stack_p, node)
81782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#else	/* !DISABLE_MEM_POOLS */
82f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#define	g_generic_node_alloc(t,sizeof_node,p)	 g_malloc (sizeof_node)
83f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#define	g_generic_node_free(t,node)		 g_free (node)
84782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#endif	/* !DISABLE_MEM_POOLS */
85ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
86ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
87ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- typedefs --- */
8883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _SignalNode   SignalNode;
8983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _SignalKey    SignalKey;
9083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _Emission     Emission;
9183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _Handler      Handler;
9283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _HandlerList  HandlerList;
9383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _HandlerMatch HandlerMatch;
94ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiktypedef enum
95ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
96ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_STOP,
97ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_RUN,
98ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_HOOK,
99ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_RESTART
100ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} EmissionState;
101ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
102ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
103ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- prototypes --- */
10483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline guint		signal_id_lookup	(GQuark		  quark,
10583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GType		  itype);
10683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      void		signal_destroy_R	(SignalNode	 *signal_node);
10783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerList*	handler_list_ensure	(guint		  signal_id,
10883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
10983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerList*	handler_list_lookup	(guint		  signal_id,
11083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
11183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline Handler*		handler_new		(gboolean	  after);
11283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      void		handler_insert		(guint		  signal_id,
11383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance,
11483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 Handler	 *handler);
11583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      Handler*		handler_lookup		(gpointer	  instance,
116abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik							 gulong		  handler_id,
11783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		 *signal_id_p);
11883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*	handler_match_prepend	(HandlerMatch	 *list,
11983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 Handler	 *handler,
12083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  signal_id);
12183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*	handler_match_free1_R	(HandlerMatch	 *node,
12283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
12383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      HandlerMatch*	handlers_find		(gpointer	  instance,
12483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GSignalMatchType mask,
12583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  signal_id,
12683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GQuark		  detail,
12783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GClosure	 *closure,
12883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  func,
12983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  data,
13083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gboolean	  one_and_only);
13183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		handler_ref		(Handler	 *handler);
13283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		handler_unref_R		(guint		  signal_id,
13383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance,
13483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 Handler	 *handler);
135a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic gint			handler_lists_cmp	(gconstpointer	  node1,
136a05a4b766073561baea10ba697fc7042c308719cTim Janik							 gconstpointer	  node2);
13783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		emission_push		(Emission	**emission_list_p,
138a05a4b766073561baea10ba697fc7042c308719cTim Janik							 Emission	 *emission);
13983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		emission_pop		(Emission	**emission_list_p,
140a05a4b766073561baea10ba697fc7042c308719cTim Janik							 Emission	 *emission);
14183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline Emission*		emission_find		(Emission	 *emission_list,
14283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  signal_id,
14383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GQuark		  detail,
14483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
145a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic gint			class_closures_cmp	(gconstpointer	  node1,
146a05a4b766073561baea10ba697fc7042c308719cTim Janik							 gconstpointer	  node2);
14745fb71949a0c0e27fe8d0948b345334f61a5c924Tim Janikstatic gint			signal_key_cmp		(gconstpointer	  node1,
14845fb71949a0c0e27fe8d0948b345334f61a5c924Tim Janik							 gconstpointer	  node2);
149e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janikstatic	      gboolean		signal_emit_unlocked_R	(SignalNode	 *node,
15083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GQuark		  detail,
15183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance,
15283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GValue		 *return_value,
15383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 const GValue	 *instance_and_params);
154116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylorstatic const gchar *            type_debug_name         (GType            type);
155ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
156ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
157ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- structures --- */
158617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janiktypedef struct
159617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{
160617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  GSignalAccumulator func;
161617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  gpointer           data;
162617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik} SignalAccumulator;
1639490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janiktypedef struct
1649490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik{
1659490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik  GHook hook;
1669490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik  GQuark detail;
1679490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik} SignalHook;
1689490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik#define	SIGNAL_HOOK(hook)	((SignalHook*) (hook))
1699490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik
170ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _SignalNode
171ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
172ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* permanent portion */
173ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              signal_id;
174ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GType              itype;
175ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gchar             *name;
176ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              destroyed : 1;
177ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
178ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* reinitializable portion */
179779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  guint		     test_class_offset : 12;
180ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              flags : 8;
181ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              n_params : 8;
182bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik  GType		    *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
183bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik  GType		     return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
184a05a4b766073561baea10ba697fc7042c308719cTim Janik  GBSearchArray     *class_closure_bsa;
185617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  SignalAccumulator *accumulator;
186ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GSignalCMarshaller c_marshaller;
187ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GHookList         *emission_hooks;
188ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
189779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik#define	MAX_TEST_CLASS_OFFSET	(4096)	/* 2^12, 12 bits for test_class_offset */
190779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik#define	TEST_CLASS_MAGIC	(1)	/* indicates NULL class closure, candidate for NOP optimization */
191ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
192ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _SignalKey
193ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
194ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GType  itype;
195ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GQuark quark;
196ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint  signal_id;
197ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
198ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
199ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _Emission
200ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
201a05a4b766073561baea10ba697fc7042c308719cTim Janik  Emission             *next;
202a05a4b766073561baea10ba697fc7042c308719cTim Janik  gpointer              instance;
203a05a4b766073561baea10ba697fc7042c308719cTim Janik  GSignalInvocationHint ihint;
204a05a4b766073561baea10ba697fc7042c308719cTim Janik  EmissionState         state;
205a05a4b766073561baea10ba697fc7042c308719cTim Janik  GType			chain_type;
206ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
207ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
208ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _HandlerList
209ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
210ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint    signal_id;
211ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler *handlers;
212ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
213ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _Handler
214ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
215abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  gulong        sequential_number;
216ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler      *next;
217ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler      *prev;
218830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  GQuark	detail;
219ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint         ref_count : 16;
220ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_MAX_REF_COUNT   (1 << 16)
221ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint         block_count : 12;
222ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_MAX_BLOCK_COUNT (1 << 12)
223ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint         after : 1;
224ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GClosure     *closure;
225ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
22683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstruct _HandlerMatch
22783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{
22883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  Handler      *handler;
22983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *next;
23083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  union {
23183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    guint       signal_id;
23283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    gpointer	dummy;
23383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  } d;
23483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik};
235ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
236a05a4b766073561baea10ba697fc7042c308719cTim Janiktypedef struct
237a05a4b766073561baea10ba697fc7042c308719cTim Janik{
238a05a4b766073561baea10ba697fc7042c308719cTim Janik  GType     instance_type; /* 0 for default closure */
239a05a4b766073561baea10ba697fc7042c308719cTim Janik  GClosure *closure;
240a05a4b766073561baea10ba697fc7042c308719cTim Janik} ClassClosure;
241a05a4b766073561baea10ba697fc7042c308719cTim Janik
242ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
243ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- variables --- */
244a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic GBSearchArray *g_signal_key_bsa = NULL;
2456d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janikstatic const GBSearchConfig g_signal_key_bconfig = {
2466d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  sizeof (SignalKey),
2476d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  signal_key_cmp,
2486d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  G_BSEARCH_ARRAY_ALIGN_POWER2,
2496d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik};
2506d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janikstatic GBSearchConfig g_signal_hlbsa_bconfig = {
2516d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  sizeof (HandlerList),
2526d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  handler_lists_cmp,
2536d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  0,
2546d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik};
2556d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janikstatic GBSearchConfig g_class_closure_bconfig = {
2566d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  sizeof (ClassClosure),
2576d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  class_closures_cmp,
2586d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  0,
2596d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik};
260ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GHashTable    *g_handler_list_bsa_ht = NULL;
261ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Emission      *g_recursive_emissions = NULL;
262ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Emission      *g_restart_emissions = NULL;
263d4407e38fae560bae6a66dd9ae5b2f58b9d89134Owen Taylor#ifndef DISABLE_MEM_POOLS
264ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GTrashStack   *g_handler_ts = NULL;
265d4407e38fae560bae6a66dd9ae5b2f58b9d89134Owen Taylor#endif
266abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janikstatic gulong         g_handler_sequential_number = 1;
267ee23c09e83d06a0d131ebd234c132f1c3602c019Tim JanikG_LOCK_DEFINE_STATIC (g_signal_mutex);
2689369e1e022978100c521634a968968a901dd934cTim Janik#define	SIGNAL_LOCK()		G_LOCK (g_signal_mutex)
2699369e1e022978100c521634a968968a901dd934cTim Janik#define	SIGNAL_UNLOCK()		G_UNLOCK (g_signal_mutex)
270ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
271ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
272ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- signal nodes --- */
273ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic guint          g_n_signal_nodes = 0;
274ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic SignalNode   **g_signal_nodes = NULL;
275ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
276ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline SignalNode*
277ee23c09e83d06a0d131ebd234c132f1c3602c019Tim JanikLOOKUP_SIGNAL_NODE (register guint signal_id)
278ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
279ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (signal_id < g_n_signal_nodes)
280ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return g_signal_nodes[signal_id];
281ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
282ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return NULL;
283ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
284ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
285ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
286ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- functions --- */
287ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline guint
288ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_id_lookup (GQuark quark,
289ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  GType  itype)
290ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
291e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GType *ifaces, type = itype;
292e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  SignalKey key;
293e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint n_ifaces;
294e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
295e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  key.quark = quark;
296e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
297160cd96ae26a571e76af717c27ae29b8125a54a5Matthias Clasen  /* try looking up signals for this type and its ancestors */
2988a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  do
2998a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik    {
300e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalKey *signal_key;
3018a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik
302e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      key.itype = type;
303a05a4b766073561baea10ba697fc7042c308719cTim Janik      signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
3048a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik
3058a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik      if (signal_key)
3068a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik	return signal_key->signal_id;
3078a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik
308e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      type = g_type_parent (type);
3098a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik    }
310e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  while (type);
311e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
312e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  /* no luck, try interfaces it exports */
313e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  ifaces = g_type_interfaces (itype, &n_ifaces);
314e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  while (n_ifaces--)
315e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
316e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalKey *signal_key;
317e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
318e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      key.itype = ifaces[n_ifaces];
319a05a4b766073561baea10ba697fc7042c308719cTim Janik      signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
320e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
321e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (signal_key)
322e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
323e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (ifaces);
324e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  return signal_key->signal_id;
325e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
326e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
327e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_free (ifaces);
328ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
3298a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  return 0;
330ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
331ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
332ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic gint
333a05a4b766073561baea10ba697fc7042c308719cTim Janikclass_closures_cmp (gconstpointer node1,
334a05a4b766073561baea10ba697fc7042c308719cTim Janik		    gconstpointer node2)
335a05a4b766073561baea10ba697fc7042c308719cTim Janik{
336a05a4b766073561baea10ba697fc7042c308719cTim Janik  const ClassClosure *c1 = node1, *c2 = node2;
337a05a4b766073561baea10ba697fc7042c308719cTim Janik
338a05a4b766073561baea10ba697fc7042c308719cTim Janik  return G_BSEARCH_ARRAY_CMP (c1->instance_type, c2->instance_type);
339a05a4b766073561baea10ba697fc7042c308719cTim Janik}
340a05a4b766073561baea10ba697fc7042c308719cTim Janik
341a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic gint
342ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_lists_cmp (gconstpointer node1,
343ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                   gconstpointer node2)
344ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
345ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  const HandlerList *hlist1 = node1, *hlist2 = node2;
346ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
347ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
348ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
349ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
350ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline HandlerList*
351ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_list_ensure (guint    signal_id,
352ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		     gpointer instance)
353ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
354ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
355ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList key;
356ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
357a05a4b766073561baea10ba697fc7042c308719cTim Janik  key.signal_id = signal_id;
358a05a4b766073561baea10ba697fc7042c308719cTim Janik  key.handlers = NULL;
359ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!hlbsa)
360ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
3616d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik      hlbsa = g_bsearch_array_create (&g_signal_hlbsa_bconfig);
3626d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik      hlbsa = g_bsearch_array_insert (hlbsa, &g_signal_hlbsa_bconfig, &key);
363ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
364ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
365a05a4b766073561baea10ba697fc7042c308719cTim Janik  else
366a05a4b766073561baea10ba697fc7042c308719cTim Janik    {
367a05a4b766073561baea10ba697fc7042c308719cTim Janik      GBSearchArray *o = hlbsa;
368a05a4b766073561baea10ba697fc7042c308719cTim Janik
3696d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik      hlbsa = g_bsearch_array_insert (o, &g_signal_hlbsa_bconfig, &key);
370a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (hlbsa != o)
371a05a4b766073561baea10ba697fc7042c308719cTim Janik	g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
372a05a4b766073561baea10ba697fc7042c308719cTim Janik    }
373a05a4b766073561baea10ba697fc7042c308719cTim Janik  return g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key);
374ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
375ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
376ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline HandlerList*
377ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_list_lookup (guint    signal_id,
378ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		     gpointer instance)
379ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
380ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
381ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList key;
382ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
383ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  key.signal_id = signal_id;
384ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
385a05a4b766073561baea10ba697fc7042c308719cTim Janik  return hlbsa ? g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key) : NULL;
386ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
387ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
388ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Handler*
389ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_lookup (gpointer instance,
390abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik		gulong   handler_id,
391ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		guint   *signal_id_p)
392ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
393ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
394ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
395ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (hlbsa)
396ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
397ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      guint i;
398ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
399ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      for (i = 0; i < hlbsa->n_nodes; i++)
400ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
401a05a4b766073561baea10ba697fc7042c308719cTim Janik          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
402ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          Handler *handler;
403ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
404ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          for (handler = hlist->handlers; handler; handler = handler->next)
405abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik            if (handler->sequential_number == handler_id)
406ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              {
407ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                if (signal_id_p)
408ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                  *signal_id_p = hlist->signal_id;
409ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
410ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                return handler;
411ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              }
412ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
413ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
414ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
415ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return NULL;
416ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
417ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
41883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*
41983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandler_match_prepend (HandlerMatch *list,
42083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		       Handler      *handler,
42183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		       guint	     signal_id)
42283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{
42383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *node;
42483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
42583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  /* yeah, we could use our own memchunk here, introducing yet more
42683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   * rarely used cached nodes and extra allocation overhead.
42783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   * instead, we use GList* nodes, since they are exactly the size
42883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   * we need and are already cached. g_signal_init() asserts this.
42983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   */
43083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node = (HandlerMatch*) g_list_alloc ();
43183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node->handler = handler;
43283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node->next = list;
43383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node->d.signal_id = signal_id;
43483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  handler_ref (handler);
43583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
43683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return node;
43783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik}
43883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*
43983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandler_match_free1_R (HandlerMatch *node,
44083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		       gpointer      instance)
44183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{
44283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *next = node->next;
44383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
44483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  handler_unref_R (node->d.signal_id, instance, node->handler);
44583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  g_list_free_1 ((GList*) node);
44683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
44783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return next;
44883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik}
44983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
45083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic HandlerMatch*
45183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandlers_find (gpointer         instance,
45283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       GSignalMatchType mask,
45383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       guint            signal_id,
45483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       GQuark           detail,
45583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       GClosure        *closure,
45683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       gpointer         func,
45783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       gpointer         data,
45883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       gboolean         one_and_only)
459ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
46083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *mlist = NULL;
46183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
462ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (mask & G_SIGNAL_MATCH_ID)
463ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
464ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      HandlerList *hlist = handler_list_lookup (signal_id, instance);
465ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      Handler *handler;
466790a7bd3be608d9b12a18711d4400490d96b2a46Elliot Lee      SignalNode *node = NULL;
467ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
46855ec7f32a6852dba73abb29e650615b66b065ef9Tim Janik      if (mask & G_SIGNAL_MATCH_FUNC)
469ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
470ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  node = LOOKUP_SIGNAL_NODE (signal_id);
471ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (!node || !node->c_marshaller)
472ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    return NULL;
473ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
47483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
475ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      mask = ~mask;
476ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
477abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik        if (handler->sequential_number &&
47883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	    ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
479830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
480ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
481830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
482ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
483ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik					      handler->closure->meta_marshal == 0 &&
484ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik					      ((GCClosure*) handler->closure)->callback == func)))
48583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	  {
48683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	    mlist = handler_match_prepend (mlist, handler, signal_id);
48783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	    if (one_and_only)
48883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	      return mlist;
48983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	  }
490ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
491ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
492ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
493ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
494ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
495ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      mask = ~mask;
496ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (hlbsa)
497ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
498ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          guint i;
499ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
500ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          for (i = 0; i < hlbsa->n_nodes; i++)
501ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            {
502a05a4b766073561baea10ba697fc7042c308719cTim Janik              HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
503790a7bd3be608d9b12a18711d4400490d96b2a46Elliot Lee	      SignalNode *node = NULL;
504ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              Handler *handler;
505ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
506ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      if (!(mask & G_SIGNAL_MATCH_FUNC))
507ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		{
508ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
509ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  if (!node->c_marshaller)
510ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    continue;
511ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		}
51283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
513ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              for (handler = hlist->handlers; handler; handler = handler->next)
514abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik		if (handler->sequential_number &&
51583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		    ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
516830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik                    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
517ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                    ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
518830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
519ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
520ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik						      handler->closure->meta_marshal == 0 &&
521ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik						      ((GCClosure*) handler->closure)->callback == func)))
52283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		  {
523a453526f350a3956a26f71db481bd8b436c65f97Owen Taylor		    mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
52483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		    if (one_and_only)
52583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		      return mlist;
52683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		  }
527ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            }
528ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
529ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
530ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
53183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return mlist;
532ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
533ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
534ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline Handler*
535ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_new (gboolean after)
536ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
537ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler *handler = g_generic_node_alloc (&g_handler_ts,
538ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                           sizeof (Handler),
539ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                           HANDLER_PRE_ALLOC);
540ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#ifndef G_DISABLE_CHECKS
541abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  if (g_handler_sequential_number < 1)
542ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
543ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif
544ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
545abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  handler->sequential_number = g_handler_sequential_number++;
546ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->prev = NULL;
547ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->next = NULL;
548830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  handler->detail = 0;
549ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->ref_count = 1;
550ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->block_count = 0;
551ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->after = after != FALSE;
552ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->closure = NULL;
553ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
554ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return handler;
555ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
556ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
557ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
558ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_ref (Handler *handler)
559ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
560ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (handler->ref_count > 0);
561ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
562ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#ifndef G_DISABLE_CHECKS
563ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
564ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
565ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif
566ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
567ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->ref_count += 1;
568ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
569ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
570ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
571ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_unref_R (guint    signal_id,
572ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		 gpointer instance,
573ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		 Handler *handler)
574ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
575ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (handler->ref_count > 0);
576ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
577ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->ref_count -= 1;
578ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!handler->ref_count)
579ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
580ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (handler->next)
581ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        handler->next->prev = handler->prev;
58283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      if (handler->prev)	/* watch out for g_signal_handlers_destroy()! */
583ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        handler->prev->next = handler->next;
584ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
585ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
586ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          HandlerList *hlist = handler_list_lookup (signal_id, instance);
587ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
588ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          hlist->handlers = handler->next;
589ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
5909369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
591ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_closure_unref (handler->closure);
5929369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_LOCK ();
593ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_generic_node_free (&g_handler_ts, handler);
594ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
595ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
596ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
597ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic void
598ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_insert (guint    signal_id,
599ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		gpointer instance,
600ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		Handler  *handler)
601ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
602ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList *hlist;
603ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
604e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
605ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
606ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  hlist = handler_list_ensure (signal_id, instance);
607ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!hlist->handlers)
608ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    hlist->handlers = handler;
609ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else if (hlist->handlers->after && !handler->after)
610ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
611ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->next = hlist->handlers;
612ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlist->handlers->prev = handler;
613ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlist->handlers = handler;
614ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
615ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
616ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
617ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      Handler *tmp = hlist->handlers;
618ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
619ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (handler->after)
620ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        while (tmp->next)
621ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          tmp = tmp->next;
622ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
623ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        while (tmp->next && !tmp->next->after)
624ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          tmp = tmp->next;
625ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (tmp->next)
626ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        tmp->next->prev = handler;
627ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->next = tmp->next;
628ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->prev = tmp;
629ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      tmp->next = handler;
630ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
631ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
632ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
633ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
634a05a4b766073561baea10ba697fc7042c308719cTim Janikemission_push (Emission **emission_list_p,
635a05a4b766073561baea10ba697fc7042c308719cTim Janik	       Emission  *emission)
636a05a4b766073561baea10ba697fc7042c308719cTim Janik{
637ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  emission->next = *emission_list_p;
638ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  *emission_list_p = emission;
639ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
640ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
641ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
642a05a4b766073561baea10ba697fc7042c308719cTim Janikemission_pop (Emission **emission_list_p,
643a05a4b766073561baea10ba697fc7042c308719cTim Janik	      Emission  *emission)
644ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
645a05a4b766073561baea10ba697fc7042c308719cTim Janik  Emission *node, *last = NULL;
646a05a4b766073561baea10ba697fc7042c308719cTim Janik
647a05a4b766073561baea10ba697fc7042c308719cTim Janik  for (node = *emission_list_p; node; last = node, node = last->next)
648a05a4b766073561baea10ba697fc7042c308719cTim Janik    if (node == emission)
649a05a4b766073561baea10ba697fc7042c308719cTim Janik      {
650a05a4b766073561baea10ba697fc7042c308719cTim Janik	if (last)
651a05a4b766073561baea10ba697fc7042c308719cTim Janik	  last->next = node->next;
652a05a4b766073561baea10ba697fc7042c308719cTim Janik	else
653a05a4b766073561baea10ba697fc7042c308719cTim Janik	  *emission_list_p = node->next;
654a05a4b766073561baea10ba697fc7042c308719cTim Janik	return;
655a05a4b766073561baea10ba697fc7042c308719cTim Janik      }
656a05a4b766073561baea10ba697fc7042c308719cTim Janik  g_assert_not_reached ();
657ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
658ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
659ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline Emission*
660ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikemission_find (Emission *emission_list,
661ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       guint     signal_id,
662830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	       GQuark    detail,
663ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       gpointer  instance)
664ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
665ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Emission *emission;
666ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
667ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  for (emission = emission_list; emission; emission = emission->next)
668830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    if (emission->instance == instance &&
669a05a4b766073561baea10ba697fc7042c308719cTim Janik	emission->ihint.signal_id == signal_id &&
670a05a4b766073561baea10ba697fc7042c308719cTim Janik	emission->ihint.detail == detail)
671a05a4b766073561baea10ba697fc7042c308719cTim Janik      return emission;
672a05a4b766073561baea10ba697fc7042c308719cTim Janik  return NULL;
673a05a4b766073561baea10ba697fc7042c308719cTim Janik}
674a05a4b766073561baea10ba697fc7042c308719cTim Janik
675a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic inline Emission*
67669c000f069ae934760678577506495fed061d9e4Tim Janikemission_find_innermost (gpointer instance)
677a05a4b766073561baea10ba697fc7042c308719cTim Janik{
67869c000f069ae934760678577506495fed061d9e4Tim Janik  Emission *emission, *s = NULL, *c = NULL;
679a05a4b766073561baea10ba697fc7042c308719cTim Janik
68069c000f069ae934760678577506495fed061d9e4Tim Janik  for (emission = g_restart_emissions; emission; emission = emission->next)
681a05a4b766073561baea10ba697fc7042c308719cTim Janik    if (emission->instance == instance)
68269c000f069ae934760678577506495fed061d9e4Tim Janik      {
68369c000f069ae934760678577506495fed061d9e4Tim Janik	s = emission;
68469c000f069ae934760678577506495fed061d9e4Tim Janik	break;
68569c000f069ae934760678577506495fed061d9e4Tim Janik      }
68669c000f069ae934760678577506495fed061d9e4Tim Janik  for (emission = g_recursive_emissions; emission; emission = emission->next)
68769c000f069ae934760678577506495fed061d9e4Tim Janik    if (emission->instance == instance)
68869c000f069ae934760678577506495fed061d9e4Tim Janik      {
68969c000f069ae934760678577506495fed061d9e4Tim Janik	c = emission;
69069c000f069ae934760678577506495fed061d9e4Tim Janik	break;
69169c000f069ae934760678577506495fed061d9e4Tim Janik      }
69269c000f069ae934760678577506495fed061d9e4Tim Janik  if (!s)
69369c000f069ae934760678577506495fed061d9e4Tim Janik    return c;
69469c000f069ae934760678577506495fed061d9e4Tim Janik  else if (!c)
69569c000f069ae934760678577506495fed061d9e4Tim Janik    return s;
69669c000f069ae934760678577506495fed061d9e4Tim Janik  else
69769c000f069ae934760678577506495fed061d9e4Tim Janik    return G_HAVE_GROWING_STACK ? MAX (c, s) : MIN (c, s);
698ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
699ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
700ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic gint
701ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_key_cmp (gconstpointer node1,
702ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                gconstpointer node2)
703ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
704ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  const SignalKey *key1 = node1, *key2 = node2;
705ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
706ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (key1->itype == key2->itype)
707ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
708ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
709ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
710ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
711ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
712ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
713465c7d1ead296b70b8d47ca333554a18f71da11dMatthias Claseng_signal_init (void)
714ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
7159369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
716ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!g_n_signal_nodes)
717ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
71883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      /* handler_id_node_prepend() requires this */
71983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      g_assert (sizeof (GList) == sizeof (HandlerMatch));
72083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
721ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
722ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
7236d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik      g_signal_key_bsa = g_bsearch_array_create (&g_signal_key_bconfig);
724ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
725ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      /* invalid (0) signal_id */
726ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_n_signal_nodes = 1;
727ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
728ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes[0] = NULL;
729ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
7309369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
731ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
732ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
733ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
7343cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik_g_signals_destroy (GType itype)
735ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
736ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint i;
737ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
7389369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
73983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  for (i = 1; i < g_n_signal_nodes; i++)
740ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
741ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      SignalNode *node = g_signal_nodes[i];
742ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
743ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (node->itype == itype)
744ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
745ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          if (node->destroyed)
746ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
747ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                       node->name,
748116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor                       type_debug_name (node->itype));
749ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          else
750cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik	    signal_destroy_R (node);
751ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
752ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
7539369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
754ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
755ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
756ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
757ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_stop_emission (gpointer instance,
758830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik                        guint    signal_id,
759830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			GQuark   detail)
760ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
761ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
762ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
763ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
764ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (signal_id > 0);
765ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
7669369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
767ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
768830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
769830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
770830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
7719369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
772830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      return;
773830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    }
774e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
775ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
776ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
777830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      Emission *emission = emission_find (emission_list, signal_id, detail, instance);
778ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
779ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission)
780ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
781a05a4b766073561baea10ba697fc7042c308719cTim Janik          if (emission->state == EMISSION_HOOK)
782ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
783ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                       node->name, instance);
784a05a4b766073561baea10ba697fc7042c308719cTim Janik          else if (emission->state == EMISSION_RUN)
785a05a4b766073561baea10ba697fc7042c308719cTim Janik            emission->state = EMISSION_STOP;
786ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
787ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
788ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
789ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                   node->name, instance);
790ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
791ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
792ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
7939369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
794ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
795ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
796617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikstatic void
797617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janiksignal_finalize_hook (GHookList *hook_list,
798617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik		      GHook     *hook)
799617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{
800617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  GDestroyNotify destroy = hook->destroy;
801617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
802617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  if (destroy)
803617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    {
804617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      hook->destroy = NULL;
8059369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
806617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      destroy (hook->data);
8079369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_LOCK ();
808617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    }
809617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik}
810617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
811abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janikgulong
812617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikg_signal_add_emission_hook (guint               signal_id,
813617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik			    GQuark              detail,
814617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik			    GSignalEmissionHook hook_func,
815617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik			    gpointer            hook_data,
816617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik			    GDestroyNotify      data_destroy)
817617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{
818abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  static gulong seq_hook_id = 1;
819617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  SignalNode *node;
820617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  GHook *hook;
8219490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik  SignalHook *signal_hook;
822617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
823617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  g_return_val_if_fail (signal_id > 0, 0);
824617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  g_return_val_if_fail (hook_func != NULL, 0);
825617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
8269369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
827617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
828ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen  if (!node || node->destroyed)
829617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    {
830617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id);
8319369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
832617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      return 0;
833617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    }
834ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen  if (node->flags & G_SIGNAL_NO_HOOKS)
835ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen    {
836ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen      g_warning ("%s: signal id `%u' does not support emission hooks (G_SIGNAL_NO_HOOKS flag set)", G_STRLOC, signal_id);
837ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen      SIGNAL_UNLOCK ();
838ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen      return 0;
839ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen    }
840617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  if (detail && !(node->flags & G_SIGNAL_DETAILED))
841617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    {
842617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
8439369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
844617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      return 0;
845617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    }
846617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  if (!node->emission_hooks)
847617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    {
848617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      node->emission_hooks = g_new (GHookList, 1);
8499490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik      g_hook_list_init (node->emission_hooks, sizeof (SignalHook));
850617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      node->emission_hooks->finalize_hook = signal_finalize_hook;
851617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    }
852617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  hook = g_hook_alloc (node->emission_hooks);
853617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  hook->data = hook_data;
854738c1cfd6bc87a410324209e8e96f76f90ada720Erwann Chenede  hook->func = (gpointer) hook_func;
855617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  hook->destroy = data_destroy;
8569490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik  signal_hook = SIGNAL_HOOK (hook);
8579490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik  signal_hook->detail = detail;
858617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  node->emission_hooks->seq_id = seq_hook_id;
859617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  g_hook_append (node->emission_hooks, hook);
860617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  seq_hook_id = node->emission_hooks->seq_id;
8619369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
862617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
863617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  return hook->hook_id;
864617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik}
865617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
866617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikvoid
867abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janikg_signal_remove_emission_hook (guint  signal_id,
868abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik			       gulong hook_id)
869617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{
870617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  SignalNode *node;
871617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
872617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  g_return_if_fail (signal_id > 0);
873617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  g_return_if_fail (hook_id > 0);
874617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
8759369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
876617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
877617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  if (!node || node->destroyed)
878617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id);
879617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id))
880abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik    g_warning ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id);
8819369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
882617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik}
883617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
8843cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikstatic inline guint
8853cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janiksignal_parse_name (const gchar *name,
8863cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		   GType        itype,
8873cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		   GQuark      *detail_p,
8883cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		   gboolean     force_quark)
8893cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik{
8903cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  const gchar *colon = strchr (name, ':');
8913cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  guint signal_id;
8923cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
8933cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  if (!colon)
8943cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    {
8953cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      signal_id = signal_id_lookup (g_quark_try_string (name), itype);
8963cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (signal_id && detail_p)
8973cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	*detail_p = 0;
8983cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    }
8993cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  else if (colon[1] == ':')
9003cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    {
9013cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      gchar buffer[32];
9023cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      guint l = colon - name;
9033cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
9043cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (l < 32)
9053cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	{
9063cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  memcpy (buffer, name, l);
9073cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  buffer[l] = 0;
9083cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  signal_id = signal_id_lookup (g_quark_try_string (buffer), itype);
9093cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	}
9103cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      else
9113cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	{
9123cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  gchar *signal = g_new (gchar, l + 1);
9133cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
9143cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  memcpy (signal, name, l);
9153cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  signal[l] = 0;
9163cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  signal_id = signal_id_lookup (g_quark_try_string (signal), itype);
9173cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  g_free (signal);
9183cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	}
9193cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
9203cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (signal_id && detail_p)
9213cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	*detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0;
9223cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    }
9233cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  else
9243cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    signal_id = 0;
9253cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  return signal_id;
9263cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik}
9273cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
9283cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikgboolean
9293cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikg_signal_parse_name (const gchar *detailed_signal,
9303cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     GType        itype,
9313cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     guint       *signal_id_p,
9323cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     GQuark      *detail_p,
9333cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     gboolean	  force_detail_quark)
9343cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik{
93537e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik  SignalNode *node;
9363cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  GQuark detail = 0;
9373cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  guint signal_id;
93883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
9393cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  g_return_val_if_fail (detailed_signal != NULL, FALSE);
9403cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
94183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
9429369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
9433cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
9449369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
94537e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik
94637e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik  node = signal_id ? LOOKUP_SIGNAL_NODE (signal_id) : NULL;
94737e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik  if (!node || node->destroyed ||
94837e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik      (detail && !(node->flags & G_SIGNAL_DETAILED)))
9493cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    return FALSE;
95037e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik
95137e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik  if (signal_id_p)
95237e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik    *signal_id_p = signal_id;
95337e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik  if (detail_p)
95437e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik    *detail_p = detail;
95537e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik
95637e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik  return TRUE;
9573cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik}
9583cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
959e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janikvoid
960e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janikg_signal_stop_emission_by_name (gpointer     instance,
961e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik				const gchar *detailed_signal)
962e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik{
963e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  guint signal_id;
964e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  GQuark detail = 0;
965e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  GType itype;
966e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik
967e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
968e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  g_return_if_fail (detailed_signal != NULL);
969e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik
9709369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
971e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  itype = G_TYPE_FROM_INSTANCE (instance);
972e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
973e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  if (signal_id)
974e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik    {
975e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
976e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik
977e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik      if (detail && !(node->flags & G_SIGNAL_DETAILED))
978e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik	g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
979e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik      else if (!g_type_is_a (itype, node->itype))
980e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik	g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
981e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik      else
982e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik	{
983e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik	  Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
984e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik	  Emission *emission = emission_find (emission_list, signal_id, detail, instance);
985e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik
986e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik	  if (emission)
987e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik	    {
988a05a4b766073561baea10ba697fc7042c308719cTim Janik	      if (emission->state == EMISSION_HOOK)
989e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik		g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
990e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik			   node->name, instance);
991a05a4b766073561baea10ba697fc7042c308719cTim Janik	      else if (emission->state == EMISSION_RUN)
992a05a4b766073561baea10ba697fc7042c308719cTim Janik		emission->state = EMISSION_STOP;
993e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik	    }
994e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik	  else
995e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik	    g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
996e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik		       node->name, instance);
997e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik	}
998e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik    }
999e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  else
1000e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
10019369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1002e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik}
1003e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik
1004ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint
1005ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_lookup (const gchar *name,
1006ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 GType        itype)
1007ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
10088a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  guint signal_id;
1009ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (name != NULL, 0);
1010ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
1011ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
10129369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
10138a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
10149369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1015fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  if (!signal_id)
1016fd860cb987e0bc77b8a69363576c01069b40244eTim Janik    {
1017fd860cb987e0bc77b8a69363576c01069b40244eTim Janik      /* give elaborate warnings */
1018fd860cb987e0bc77b8a69363576c01069b40244eTim Janik      if (!g_type_name (itype))
10195c2f442088c65a67534e22a3ef7016bed7b7fd9bTim Janik	g_warning (G_STRLOC ": unable to lookup signal \"%s\" for invalid type id `%lu'",
1020fd860cb987e0bc77b8a69363576c01069b40244eTim Janik		   name, itype);
1021fd860cb987e0bc77b8a69363576c01069b40244eTim Janik      else if (!G_TYPE_IS_INSTANTIATABLE (itype))
1022fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	g_warning (G_STRLOC ": unable to lookup signal \"%s\" for non instantiatable type `%s'",
1023fd860cb987e0bc77b8a69363576c01069b40244eTim Janik		   name, g_type_name (itype));
1024fd860cb987e0bc77b8a69363576c01069b40244eTim Janik      else if (!g_type_class_peek (itype))
1025fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	g_warning (G_STRLOC ": unable to lookup signal \"%s\" of unloaded type `%s'",
1026fd860cb987e0bc77b8a69363576c01069b40244eTim Janik		   name, g_type_name (itype));
1027fd860cb987e0bc77b8a69363576c01069b40244eTim Janik    }
1028ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
10298a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  return signal_id;
1030ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1031ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1032fd860cb987e0bc77b8a69363576c01069b40244eTim Janikguint*
1033fd860cb987e0bc77b8a69363576c01069b40244eTim Janikg_signal_list_ids (GType  itype,
1034fd860cb987e0bc77b8a69363576c01069b40244eTim Janik		   guint *n_ids)
1035fd860cb987e0bc77b8a69363576c01069b40244eTim Janik{
1036fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  SignalKey *keys;
1037fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  GArray *result;
1038fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  guint n_nodes;
1039fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  guint i;
1040fd860cb987e0bc77b8a69363576c01069b40244eTim Janik
1041fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
1042fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  g_return_val_if_fail (n_ids != NULL, NULL);
1043fd860cb987e0bc77b8a69363576c01069b40244eTim Janik
1044fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  SIGNAL_LOCK ();
10456d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  keys = g_bsearch_array_get_nth (g_signal_key_bsa, &g_signal_key_bconfig, 0);
10466d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  n_nodes = g_bsearch_array_get_n_nodes (g_signal_key_bsa);
1047fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  result = g_array_new (FALSE, FALSE, sizeof (guint));
1048fd860cb987e0bc77b8a69363576c01069b40244eTim Janik
1049fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  for (i = 0; i < n_nodes; i++)
1050fd860cb987e0bc77b8a69363576c01069b40244eTim Janik    if (keys[i].itype == itype)
1051fd860cb987e0bc77b8a69363576c01069b40244eTim Janik      {
1052fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	const gchar *name = g_quark_to_string (keys[i].quark);
1053fd860cb987e0bc77b8a69363576c01069b40244eTim Janik
1054fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	/* Signal names with "_" in them are aliases to the same
1055fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	 * name with "-" instead of "_".
1056fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	 */
1057fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	if (!strchr (name, '_'))
1058fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	  g_array_append_val (result, keys[i].signal_id);
1059fd860cb987e0bc77b8a69363576c01069b40244eTim Janik      }
1060fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  *n_ids = result->len;
1061fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  SIGNAL_UNLOCK ();
1062fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  if (!n_nodes)
1063fd860cb987e0bc77b8a69363576c01069b40244eTim Janik    {
1064fd860cb987e0bc77b8a69363576c01069b40244eTim Janik      /* give elaborate warnings */
1065fd860cb987e0bc77b8a69363576c01069b40244eTim Janik      if (!g_type_name (itype))
10665c2f442088c65a67534e22a3ef7016bed7b7fd9bTim Janik	g_warning (G_STRLOC ": unable to list signals for invalid type id `%lu'",
1067fd860cb987e0bc77b8a69363576c01069b40244eTim Janik		   itype);
1068fd860cb987e0bc77b8a69363576c01069b40244eTim Janik      else if (!G_TYPE_IS_INSTANTIATABLE (itype))
1069fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	g_warning (G_STRLOC ": unable to list signals of non instantiatable type `%s'",
1070fd860cb987e0bc77b8a69363576c01069b40244eTim Janik		   g_type_name (itype));
1071fd860cb987e0bc77b8a69363576c01069b40244eTim Janik      else if (!g_type_class_peek (itype))
1072fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	g_warning (G_STRLOC ": unable to list signals of unloaded type `%s'",
1073fd860cb987e0bc77b8a69363576c01069b40244eTim Janik		   g_type_name (itype));
1074fd860cb987e0bc77b8a69363576c01069b40244eTim Janik    }
1075fd860cb987e0bc77b8a69363576c01069b40244eTim Janik
1076fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  return (guint*) g_array_free (result, FALSE);
1077fd860cb987e0bc77b8a69363576c01069b40244eTim Janik}
1078fd860cb987e0bc77b8a69363576c01069b40244eTim Janik
10791c391cc69846713b0406545146ea232efc5f34e2Havoc PenningtonG_CONST_RETURN gchar*
1080ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_name (guint signal_id)
1081ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1082ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
1083ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gchar *name;
108483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
10859369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1086ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
1087ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  name = node ? node->name : NULL;
10889369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1089ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1090ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return name;
1091ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1092ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1093ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
1094ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_query (guint         signal_id,
1095ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		GSignalQuery *query)
1096ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1097ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
109883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1099ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (query != NULL);
110083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
11019369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1102ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
1103ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!node || node->destroyed)
1104ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    query->signal_id = 0;
1105ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
1106ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1107ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->signal_id = node->signal_id;
1108ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->signal_name = node->name;
1109ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->itype = node->itype;
1110ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->signal_flags = node->flags;
1111ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->return_type = node->return_type;
1112ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->n_params = node->n_params;
1113ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->param_types = node->param_types;
1114ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
11159369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1116ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1117ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1118ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint
1119fd860cb987e0bc77b8a69363576c01069b40244eTim Janikg_signal_new (const gchar	 *signal_name,
1120fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	      GType		  itype,
1121fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	      GSignalFlags	  signal_flags,
1122fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	      guint               class_offset,
1123fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	      GSignalAccumulator  accumulator,
1124fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	      gpointer		  accu_data,
1125fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	      GSignalCMarshaller  c_marshaller,
1126fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	      GType		  return_type,
1127fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	      guint		  n_params,
1128fd860cb987e0bc77b8a69363576c01069b40244eTim Janik	      ...)
1129b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington{
1130b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  va_list args;
1131b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  guint signal_id;
1132b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
1133b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  g_return_val_if_fail (signal_name != NULL, 0);
1134b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
1135b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  va_start (args, n_params);
1136b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
1137b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
113843b692c8eb49a82657d9cb09a222dc66f2cc0199Tim Janik                                   class_offset ? g_signal_type_cclosure_new (itype, class_offset) : NULL,
1139617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik				   accumulator, accu_data, c_marshaller,
1140b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                                   return_type, n_params, args);
1141b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
1142b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  va_end (args);
1143779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
1144779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  /* optimize NOP emissions with NULL class handlers */
1145779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  if (signal_id && G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE &&
1146779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      class_offset && class_offset < MAX_TEST_CLASS_OFFSET)
1147779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    {
1148779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      SignalNode *node;
1149779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
1150779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      SIGNAL_LOCK ();
1151779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      node = LOOKUP_SIGNAL_NODE (signal_id);
1152779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      node->test_class_offset = class_offset;
1153779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      SIGNAL_UNLOCK ();
1154779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    }
1155b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
1156b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  return signal_id;
1157b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington}
1158b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
1159a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic inline ClassClosure*
1160a05a4b766073561baea10ba697fc7042c308719cTim Janiksignal_find_class_closure (SignalNode *node,
1161a05a4b766073561baea10ba697fc7042c308719cTim Janik			   GType       itype)
1162a05a4b766073561baea10ba697fc7042c308719cTim Janik{
1163a05a4b766073561baea10ba697fc7042c308719cTim Janik  GBSearchArray *bsa = node->class_closure_bsa;
1164a05a4b766073561baea10ba697fc7042c308719cTim Janik  ClassClosure *cc;
1165a05a4b766073561baea10ba697fc7042c308719cTim Janik
1166a05a4b766073561baea10ba697fc7042c308719cTim Janik  if (bsa)
1167a05a4b766073561baea10ba697fc7042c308719cTim Janik    {
1168a05a4b766073561baea10ba697fc7042c308719cTim Janik      ClassClosure key;
1169a05a4b766073561baea10ba697fc7042c308719cTim Janik
1170a05a4b766073561baea10ba697fc7042c308719cTim Janik      /* cc->instance_type is 0 for default closure */
1171a05a4b766073561baea10ba697fc7042c308719cTim Janik
1172a05a4b766073561baea10ba697fc7042c308719cTim Janik      key.instance_type = itype;
1173a05a4b766073561baea10ba697fc7042c308719cTim Janik      cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key);
1174a05a4b766073561baea10ba697fc7042c308719cTim Janik      while (!cc && key.instance_type)
1175a05a4b766073561baea10ba697fc7042c308719cTim Janik	{
1176a05a4b766073561baea10ba697fc7042c308719cTim Janik	  key.instance_type = g_type_parent (key.instance_type);
1177a05a4b766073561baea10ba697fc7042c308719cTim Janik	  cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key);
1178a05a4b766073561baea10ba697fc7042c308719cTim Janik	}
1179a05a4b766073561baea10ba697fc7042c308719cTim Janik    }
1180a05a4b766073561baea10ba697fc7042c308719cTim Janik  else
1181a05a4b766073561baea10ba697fc7042c308719cTim Janik    cc = NULL;
1182a05a4b766073561baea10ba697fc7042c308719cTim Janik  return cc;
1183a05a4b766073561baea10ba697fc7042c308719cTim Janik}
1184a05a4b766073561baea10ba697fc7042c308719cTim Janik
1185a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic inline GClosure*
1186a05a4b766073561baea10ba697fc7042c308719cTim Janiksignal_lookup_closure (SignalNode    *node,
1187a05a4b766073561baea10ba697fc7042c308719cTim Janik		       GTypeInstance *instance)
1188a05a4b766073561baea10ba697fc7042c308719cTim Janik{
1189a05a4b766073561baea10ba697fc7042c308719cTim Janik  ClassClosure *cc;
1190a05a4b766073561baea10ba697fc7042c308719cTim Janik
11916d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik  if (node->class_closure_bsa && g_bsearch_array_get_n_nodes (node->class_closure_bsa) == 1)
11926d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik    cc = g_bsearch_array_get_nth (node->class_closure_bsa, &g_class_closure_bconfig, 0);
1193a05a4b766073561baea10ba697fc7042c308719cTim Janik  else
1194a05a4b766073561baea10ba697fc7042c308719cTim Janik    cc = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance));
1195a05a4b766073561baea10ba697fc7042c308719cTim Janik  return cc ? cc->closure : NULL;
1196a05a4b766073561baea10ba697fc7042c308719cTim Janik}
1197a05a4b766073561baea10ba697fc7042c308719cTim Janik
1198a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic void
1199a05a4b766073561baea10ba697fc7042c308719cTim Janiksignal_add_class_closure (SignalNode *node,
1200a05a4b766073561baea10ba697fc7042c308719cTim Janik			  GType       itype,
1201a05a4b766073561baea10ba697fc7042c308719cTim Janik			  GClosure   *closure)
1202a05a4b766073561baea10ba697fc7042c308719cTim Janik{
1203a05a4b766073561baea10ba697fc7042c308719cTim Janik  ClassClosure key;
1204a05a4b766073561baea10ba697fc7042c308719cTim Janik
1205779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  /* can't optimize NOP emissions with overridden class closures */
1206779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  node->test_class_offset = 0;
1207779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
1208a05a4b766073561baea10ba697fc7042c308719cTim Janik  if (!node->class_closure_bsa)
12096d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik    node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig);
1210a05a4b766073561baea10ba697fc7042c308719cTim Janik  key.instance_type = itype;
1211a05a4b766073561baea10ba697fc7042c308719cTim Janik  key.closure = g_closure_ref (closure);
1212a05a4b766073561baea10ba697fc7042c308719cTim Janik  node->class_closure_bsa = g_bsearch_array_insert (node->class_closure_bsa,
1213a05a4b766073561baea10ba697fc7042c308719cTim Janik						    &g_class_closure_bconfig,
12146d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik						    &key);
1215a05a4b766073561baea10ba697fc7042c308719cTim Janik  g_closure_sink (closure);
1216a05a4b766073561baea10ba697fc7042c308719cTim Janik  if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (closure))
1217a05a4b766073561baea10ba697fc7042c308719cTim Janik    g_closure_set_marshal (closure, node->c_marshaller);
1218a05a4b766073561baea10ba697fc7042c308719cTim Janik}
1219a05a4b766073561baea10ba697fc7042c308719cTim Janik
1220b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Penningtonguint
1221ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_newv (const gchar       *signal_name,
1222ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GType              itype,
1223830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik               GSignalFlags       signal_flags,
1224ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GClosure          *class_closure,
1225ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GSignalAccumulator accumulator,
1226617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	       gpointer		  accu_data,
1227ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GSignalCMarshaller c_marshaller,
1228ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GType		  return_type,
1229ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               guint              n_params,
1230ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GType		 *param_types)
1231ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1232ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gchar *name;
1233ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint signal_id, i;
1234ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
1235ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1236ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (signal_name != NULL, 0);
1237ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
1238ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (n_params)
1239ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_return_val_if_fail (param_types != NULL, 0);
124043b692c8eb49a82657d9cb09a222dc66f2cc0199Tim Janik  g_return_val_if_fail ((return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == 0, 0);
1241617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1242ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_return_val_if_fail (accumulator == NULL, 0);
1243617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  if (!accumulator)
1244617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    g_return_val_if_fail (accu_data == NULL, 0);
1245617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
1246ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  name = g_strdup (signal_name);
12479abb30720036dfd464a142555aae7cce5e85c3d6Owen Taylor  g_strdelimit (name, G_STR_DELIMITERS ":^", '_');  /* FIXME do character checks like for types */
1248ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
12499369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1250ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
12518a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
1252ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
1253ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node && !node->destroyed)
1254ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1255ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
1256ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 name,
1257116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor                 type_debug_name (node->itype),
1258ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
1259ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (name);
12609369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
1261ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      return 0;
1262ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1263ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node && node->itype != itype)
1264ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1265ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
1266ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 name,
1267116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor                 type_debug_name (itype),
1268116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor                 type_debug_name (node->itype));
1269ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (name);
12709369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
1271ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      return 0;
1272ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1273ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  for (i = 0; i < n_params; i++)
127437e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik    if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1275ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      {
1276ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
1277116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor		   i + 1, type_debug_name (param_types[i]), type_debug_name (itype), name);
1278ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_free (name);
12799369e1e022978100c521634a968968a901dd934cTim Janik	SIGNAL_UNLOCK ();
1280ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	return 0;
1281ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      }
1282bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik  if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
1283ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1284ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
1285116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor		 type_debug_name (return_type), type_debug_name (itype), name);
1286ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (name);
12879369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
1288ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      return 0;
1289ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1290b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik  if (return_type != G_TYPE_NONE &&
1291b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik      (signal_flags & (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP)) == G_SIGNAL_RUN_FIRST)
1292b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik    {
1293b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik      g_warning (G_STRLOC ": signal \"%s::%s\" has return type `%s' and is only G_SIGNAL_RUN_FIRST",
1294116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor		 type_debug_name (itype), name, type_debug_name (return_type));
1295b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik      g_free (name);
12969369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
1297b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik      return 0;
1298b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik    }
1299ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1300ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* setup permanent portion of signal node */
1301ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!node)
1302ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1303ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      SignalKey key;
1304ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1305ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      signal_id = g_n_signal_nodes++;
1306ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node = g_new (SignalNode, 1);
1307ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node->signal_id = signal_id;
1308ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
1309ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes[signal_id] = node;
1310ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node->itype = itype;
1311ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node->name = name;
1312ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.itype = itype;
1313ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.quark = g_quark_from_string (node->name);
1314ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.signal_id = signal_id;
13156d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik      g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key);
1316ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_strdelimit (node->name, "_", '-');
1317ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.quark = g_quark_from_static_string (node->name);
13186d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik      g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key);
1319ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1320ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->destroyed = FALSE;
1321779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  node->test_class_offset = 0;
1322779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
1323ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* setup reinitializable portion */
1324830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
1325ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->n_params = n_params;
1326ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
1327ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->return_type = return_type;
1328a05a4b766073561baea10ba697fc7042c308719cTim Janik  node->class_closure_bsa = NULL;
1329617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  if (accumulator)
1330617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    {
1331617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      node->accumulator = g_new (SignalAccumulator, 1);
1332617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      node->accumulator->func = accumulator;
1333617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      node->accumulator->data = accu_data;
1334617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    }
1335617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  else
1336617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    node->accumulator = NULL;
1337ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->c_marshaller = c_marshaller;
1338ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->emission_hooks = NULL;
1339a05a4b766073561baea10ba697fc7042c308719cTim Janik  if (class_closure)
1340a05a4b766073561baea10ba697fc7042c308719cTim Janik    signal_add_class_closure (node, 0, class_closure);
1341779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  else if (G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE)
1342779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    {
1343779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      /* optimize NOP emissions */
1344779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      node->test_class_offset = TEST_CLASS_MAGIC;
1345779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    }
13469369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1347a05a4b766073561baea10ba697fc7042c308719cTim Janik
1348a05a4b766073561baea10ba697fc7042c308719cTim Janik  return signal_id;
1349a05a4b766073561baea10ba697fc7042c308719cTim Janik}
1350a05a4b766073561baea10ba697fc7042c308719cTim Janik
1351a05a4b766073561baea10ba697fc7042c308719cTim Janikguint
1352a05a4b766073561baea10ba697fc7042c308719cTim Janikg_signal_new_valist (const gchar       *signal_name,
1353a05a4b766073561baea10ba697fc7042c308719cTim Janik                     GType              itype,
1354a05a4b766073561baea10ba697fc7042c308719cTim Janik                     GSignalFlags       signal_flags,
1355a05a4b766073561baea10ba697fc7042c308719cTim Janik                     GClosure          *class_closure,
1356a05a4b766073561baea10ba697fc7042c308719cTim Janik                     GSignalAccumulator accumulator,
1357a05a4b766073561baea10ba697fc7042c308719cTim Janik		     gpointer		accu_data,
1358a05a4b766073561baea10ba697fc7042c308719cTim Janik                     GSignalCMarshaller c_marshaller,
1359a05a4b766073561baea10ba697fc7042c308719cTim Janik                     GType              return_type,
1360a05a4b766073561baea10ba697fc7042c308719cTim Janik                     guint              n_params,
1361a05a4b766073561baea10ba697fc7042c308719cTim Janik                     va_list            args)
1362a05a4b766073561baea10ba697fc7042c308719cTim Janik{
1363a05a4b766073561baea10ba697fc7042c308719cTim Janik  GType *param_types;
1364a05a4b766073561baea10ba697fc7042c308719cTim Janik  guint i;
1365a05a4b766073561baea10ba697fc7042c308719cTim Janik  guint signal_id;
1366a05a4b766073561baea10ba697fc7042c308719cTim Janik
1367a05a4b766073561baea10ba697fc7042c308719cTim Janik  if (n_params > 0)
1368a05a4b766073561baea10ba697fc7042c308719cTim Janik    {
1369a05a4b766073561baea10ba697fc7042c308719cTim Janik      param_types = g_new (GType, n_params);
1370a05a4b766073561baea10ba697fc7042c308719cTim Janik
1371a05a4b766073561baea10ba697fc7042c308719cTim Janik      for (i = 0; i < n_params; i++)
1372a05a4b766073561baea10ba697fc7042c308719cTim Janik	param_types[i] = va_arg (args, GType);
1373a05a4b766073561baea10ba697fc7042c308719cTim Janik    }
1374a05a4b766073561baea10ba697fc7042c308719cTim Janik  else
1375a05a4b766073561baea10ba697fc7042c308719cTim Janik    param_types = NULL;
1376a05a4b766073561baea10ba697fc7042c308719cTim Janik
1377a05a4b766073561baea10ba697fc7042c308719cTim Janik  signal_id = g_signal_newv (signal_name, itype, signal_flags,
1378a05a4b766073561baea10ba697fc7042c308719cTim Janik			     class_closure, accumulator, accu_data, c_marshaller,
1379a05a4b766073561baea10ba697fc7042c308719cTim Janik			     return_type, n_params, param_types);
1380a05a4b766073561baea10ba697fc7042c308719cTim Janik  g_free (param_types);
1381a05a4b766073561baea10ba697fc7042c308719cTim Janik
1382ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return signal_id;
1383ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1384ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1385ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic void
1386ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_destroy_R (SignalNode *signal_node)
1387ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1388ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode node = *signal_node;
1389a05a4b766073561baea10ba697fc7042c308719cTim Janik
1390ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->destroyed = TRUE;
1391ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1392ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* reentrancy caution, zero out real contents first */
1393779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  signal_node->test_class_offset = 0;
1394ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->n_params = 0;
1395ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->param_types = NULL;
1396ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->return_type = 0;
1397a05a4b766073561baea10ba697fc7042c308719cTim Janik  signal_node->class_closure_bsa = NULL;
1398ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->accumulator = NULL;
1399ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->c_marshaller = NULL;
1400ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->emission_hooks = NULL;
1401ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1402782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifdef	G_ENABLE_DEBUG
1403ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* check current emissions */
1404ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  {
1405ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    Emission *emission;
1406ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1407ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
1408ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik         emission; emission = emission->next)
1409a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (emission->ihint.signal_id == node.signal_id)
1410ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
1411ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                    node.name, emission->instance);
1412ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  }
1413ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif
1414ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1415ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* free contents that need to
1416ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik   */
14179369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1418ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_free (node.param_types);
1419a05a4b766073561baea10ba697fc7042c308719cTim Janik  if (node.class_closure_bsa)
1420a05a4b766073561baea10ba697fc7042c308719cTim Janik    {
1421a05a4b766073561baea10ba697fc7042c308719cTim Janik      guint i;
1422a05a4b766073561baea10ba697fc7042c308719cTim Janik
1423a05a4b766073561baea10ba697fc7042c308719cTim Janik      for (i = 0; i < node.class_closure_bsa->n_nodes; i++)
1424a05a4b766073561baea10ba697fc7042c308719cTim Janik	{
1425a05a4b766073561baea10ba697fc7042c308719cTim Janik	  ClassClosure *cc = g_bsearch_array_get_nth (node.class_closure_bsa, &g_class_closure_bconfig, i);
1426a05a4b766073561baea10ba697fc7042c308719cTim Janik
1427a05a4b766073561baea10ba697fc7042c308719cTim Janik	  g_closure_unref (cc->closure);
1428a05a4b766073561baea10ba697fc7042c308719cTim Janik	}
14296d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik      g_bsearch_array_free (node.class_closure_bsa, &g_class_closure_bconfig);
1430a05a4b766073561baea10ba697fc7042c308719cTim Janik    }
1431617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  g_free (node.accumulator);
1432ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node.emission_hooks)
1433ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1434ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_hook_list_clear (node.emission_hooks);
1435ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (node.emission_hooks);
1436ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
14379369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1438ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1439ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
144035bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janikvoid
144135bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janikg_signal_override_class_closure (guint     signal_id,
144235bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik				 GType     instance_type,
144335bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik				 GClosure *class_closure)
144435bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik{
1445a05a4b766073561baea10ba697fc7042c308719cTim Janik  SignalNode *node;
144669c000f069ae934760678577506495fed061d9e4Tim Janik
1447a05a4b766073561baea10ba697fc7042c308719cTim Janik  g_return_if_fail (signal_id > 0);
1448a05a4b766073561baea10ba697fc7042c308719cTim Janik  g_return_if_fail (class_closure != NULL);
144969c000f069ae934760678577506495fed061d9e4Tim Janik
1450a05a4b766073561baea10ba697fc7042c308719cTim Janik  SIGNAL_LOCK ();
1451a05a4b766073561baea10ba697fc7042c308719cTim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
1452a05a4b766073561baea10ba697fc7042c308719cTim Janik  if (!g_type_is_a (instance_type, node->itype))
1453116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor    g_warning ("%s: type `%s' cannot be overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id);
1454a05a4b766073561baea10ba697fc7042c308719cTim Janik  else
1455a05a4b766073561baea10ba697fc7042c308719cTim Janik    {
1456a05a4b766073561baea10ba697fc7042c308719cTim Janik      ClassClosure *cc = signal_find_class_closure (node, instance_type);
145769c000f069ae934760678577506495fed061d9e4Tim Janik
1458a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (cc && cc->instance_type == instance_type)
1459116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor	g_warning ("%s: type `%s' is already overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id);
1460a05a4b766073561baea10ba697fc7042c308719cTim Janik      else
1461a05a4b766073561baea10ba697fc7042c308719cTim Janik	signal_add_class_closure (node, instance_type, class_closure);
1462a05a4b766073561baea10ba697fc7042c308719cTim Janik    }
1463a05a4b766073561baea10ba697fc7042c308719cTim Janik  SIGNAL_UNLOCK ();
146435bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik}
146535bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik
146635bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janikvoid
146735bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janikg_signal_chain_from_overridden (const GValue *instance_and_params,
146835bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik				GValue       *return_value)
146935bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik{
1470a05a4b766073561baea10ba697fc7042c308719cTim Janik  GType chain_type = 0, restore_type = 0;
1471a05a4b766073561baea10ba697fc7042c308719cTim Janik  Emission *emission = NULL;
1472a05a4b766073561baea10ba697fc7042c308719cTim Janik  GClosure *closure = NULL;
147369c000f069ae934760678577506495fed061d9e4Tim Janik  guint n_params = 0;
1474a05a4b766073561baea10ba697fc7042c308719cTim Janik  gpointer instance;
1475a05a4b766073561baea10ba697fc7042c308719cTim Janik
1476a05a4b766073561baea10ba697fc7042c308719cTim Janik  g_return_if_fail (instance_and_params != NULL);
1477a05a4b766073561baea10ba697fc7042c308719cTim Janik  instance = g_value_peek_pointer (instance_and_params);
1478a05a4b766073561baea10ba697fc7042c308719cTim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1479a05a4b766073561baea10ba697fc7042c308719cTim Janik
1480a05a4b766073561baea10ba697fc7042c308719cTim Janik  SIGNAL_LOCK ();
148169c000f069ae934760678577506495fed061d9e4Tim Janik  emission = emission_find_innermost (instance);
148269c000f069ae934760678577506495fed061d9e4Tim Janik  if (emission)
1483a05a4b766073561baea10ba697fc7042c308719cTim Janik    {
148469c000f069ae934760678577506495fed061d9e4Tim Janik      SignalNode *node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id);
148569c000f069ae934760678577506495fed061d9e4Tim Janik
148669c000f069ae934760678577506495fed061d9e4Tim Janik      g_assert (node != NULL);	/* paranoid */
148769c000f069ae934760678577506495fed061d9e4Tim Janik
148869c000f069ae934760678577506495fed061d9e4Tim Janik      /* we should probably do the same parameter checks as g_signal_emit() here.
1489a05a4b766073561baea10ba697fc7042c308719cTim Janik       */
149069c000f069ae934760678577506495fed061d9e4Tim Janik      if (emission->chain_type != G_TYPE_NONE)
1491a05a4b766073561baea10ba697fc7042c308719cTim Janik	{
1492a05a4b766073561baea10ba697fc7042c308719cTim Janik	  ClassClosure *cc = signal_find_class_closure (node, emission->chain_type);
149369c000f069ae934760678577506495fed061d9e4Tim Janik
1494a05a4b766073561baea10ba697fc7042c308719cTim Janik	  g_assert (cc != NULL);	/* closure currently in call stack */
1495a05a4b766073561baea10ba697fc7042c308719cTim Janik
149669c000f069ae934760678577506495fed061d9e4Tim Janik	  n_params = node->n_params;
1497a05a4b766073561baea10ba697fc7042c308719cTim Janik	  restore_type = cc->instance_type;
1498a05a4b766073561baea10ba697fc7042c308719cTim Janik	  cc = signal_find_class_closure (node, g_type_parent (cc->instance_type));
1499a05a4b766073561baea10ba697fc7042c308719cTim Janik	  if (cc && cc->instance_type != restore_type)
1500a05a4b766073561baea10ba697fc7042c308719cTim Janik	    {
1501a05a4b766073561baea10ba697fc7042c308719cTim Janik	      closure = cc->closure;
1502a05a4b766073561baea10ba697fc7042c308719cTim Janik	      chain_type = cc->instance_type;
1503a05a4b766073561baea10ba697fc7042c308719cTim Janik	    }
1504a05a4b766073561baea10ba697fc7042c308719cTim Janik	}
1505a05a4b766073561baea10ba697fc7042c308719cTim Janik      else
150669c000f069ae934760678577506495fed061d9e4Tim Janik	g_warning ("%s: signal id `%u' cannot be chained from current emission stage for instance `%p'", G_STRLOC, node->signal_id, instance);
1507a05a4b766073561baea10ba697fc7042c308719cTim Janik    }
1508a05a4b766073561baea10ba697fc7042c308719cTim Janik  else
150969c000f069ae934760678577506495fed061d9e4Tim Janik    g_warning ("%s: no signal is currently being emitted for instance `%p'", G_STRLOC, instance);
1510a05a4b766073561baea10ba697fc7042c308719cTim Janik  if (closure)
1511a05a4b766073561baea10ba697fc7042c308719cTim Janik    {
1512a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission->chain_type = chain_type;
1513a05a4b766073561baea10ba697fc7042c308719cTim Janik      SIGNAL_UNLOCK ();
1514a05a4b766073561baea10ba697fc7042c308719cTim Janik      g_closure_invoke (closure,
1515a05a4b766073561baea10ba697fc7042c308719cTim Janik			return_value,
151669c000f069ae934760678577506495fed061d9e4Tim Janik			n_params + 1,
1517a05a4b766073561baea10ba697fc7042c308719cTim Janik			instance_and_params,
1518a05a4b766073561baea10ba697fc7042c308719cTim Janik			&emission->ihint);
1519a05a4b766073561baea10ba697fc7042c308719cTim Janik      SIGNAL_LOCK ();
1520a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission->chain_type = restore_type;
1521a05a4b766073561baea10ba697fc7042c308719cTim Janik    }
1522a05a4b766073561baea10ba697fc7042c308719cTim Janik  SIGNAL_UNLOCK ();
152335bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik}
152435bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik
152569c000f069ae934760678577506495fed061d9e4Tim JanikGSignalInvocationHint*
152669c000f069ae934760678577506495fed061d9e4Tim Janikg_signal_get_invocation_hint (gpointer instance)
152769c000f069ae934760678577506495fed061d9e4Tim Janik{
152869c000f069ae934760678577506495fed061d9e4Tim Janik  Emission *emission = NULL;
152969c000f069ae934760678577506495fed061d9e4Tim Janik
153069c000f069ae934760678577506495fed061d9e4Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), NULL);
153169c000f069ae934760678577506495fed061d9e4Tim Janik
153269c000f069ae934760678577506495fed061d9e4Tim Janik  SIGNAL_LOCK ();
153369c000f069ae934760678577506495fed061d9e4Tim Janik  emission = emission_find_innermost (instance);
153469c000f069ae934760678577506495fed061d9e4Tim Janik  SIGNAL_UNLOCK ();
153569c000f069ae934760678577506495fed061d9e4Tim Janik
153669c000f069ae934760678577506495fed061d9e4Tim Janik  return emission ? &emission->ihint : NULL;
153769c000f069ae934760678577506495fed061d9e4Tim Janik}
153869c000f069ae934760678577506495fed061d9e4Tim Janik
1539abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janikgulong
15403cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikg_signal_connect_closure_by_id (gpointer  instance,
15413cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				guint     signal_id,
15423cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				GQuark    detail,
15433cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				GClosure *closure,
15443cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				gboolean  after)
1545ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1546ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
1547abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  gulong handler_seq_no = 0;
1548ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1549ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1550ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (signal_id > 0, 0);
1551ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (closure != NULL, 0);
1552ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
15539369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1554ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
1555e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (node)
1556830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
1557e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1558e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1559e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1560e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1561e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
1562e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1563e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  Handler *handler = handler_new (after);
1564e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1565abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik	  handler_seq_no = handler->sequential_number;
1566e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->detail = detail;
1567e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->closure = g_closure_ref (closure);
156812a0d19c11c29e3d4b7a5f02a07576309e2787a6Tim Janik	  g_closure_sink (closure);
1569e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_insert (signal_id, instance, handler);
1570e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
1571e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_closure_set_marshal (closure, node->c_marshaller);
1572e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1573ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1574ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
1575ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
15769369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1577ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1578abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  return handler_seq_no;
1579ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1580ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1581abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janikgulong
1582e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_connect_closure (gpointer     instance,
1583e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			  const gchar *detailed_signal,
1584e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			  GClosure    *closure,
1585e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			  gboolean     after)
1586e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1587abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  guint signal_id;
1588abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  gulong handler_seq_no = 0;
1589e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GQuark detail = 0;
1590e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GType itype;
1591e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1592e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1593e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (detailed_signal != NULL, 0);
1594e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (closure != NULL, 0);
1595e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
15969369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1597e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  itype = G_TYPE_FROM_INSTANCE (instance);
1598e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1599e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (signal_id)
1600e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1601e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1602e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1603e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1604e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1605e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else if (!g_type_is_a (itype, node->itype))
1606e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1607e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
1608e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1609e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  Handler *handler = handler_new (after);
1610e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1611abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik	  handler_seq_no = handler->sequential_number;
1612e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->detail = detail;
1613e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->closure = g_closure_ref (closure);
161412a0d19c11c29e3d4b7a5f02a07576309e2787a6Tim Janik	  g_closure_sink (closure);
1615e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_insert (signal_id, instance, handler);
1616e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1617e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_closure_set_marshal (handler->closure, node->c_marshaller);
1618e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1619e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1620e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1621e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
16229369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1623e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1624abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  return handler_seq_no;
1625e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1626e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1627abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janikgulong
1628e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_connect_data (gpointer       instance,
1629e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       const gchar   *detailed_signal,
1630e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       GCallback      c_handler,
1631e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       gpointer       data,
1632e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       GClosureNotify destroy_data,
1633fd860cb987e0bc77b8a69363576c01069b40244eTim Janik		       GConnectFlags  connect_flags)
1634e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1635abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  guint signal_id;
1636abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  gulong handler_seq_no = 0;
1637e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GQuark detail = 0;
1638e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GType itype;
1639fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  gboolean swapped, after;
1640fd860cb987e0bc77b8a69363576c01069b40244eTim Janik
1641e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1642e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (detailed_signal != NULL, 0);
1643e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (c_handler != NULL, 0);
1644e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1645fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  swapped = (connect_flags & G_CONNECT_SWAPPED) != FALSE;
1646fd860cb987e0bc77b8a69363576c01069b40244eTim Janik  after = (connect_flags & G_CONNECT_AFTER) != FALSE;
1647fd860cb987e0bc77b8a69363576c01069b40244eTim Janik
16489369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1649e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  itype = G_TYPE_FROM_INSTANCE (instance);
1650e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1651e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (signal_id)
1652e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1653e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1654e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1655e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1656e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1657e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else if (!g_type_is_a (itype, node->itype))
1658e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1659e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
1660e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1661e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  Handler *handler = handler_new (after);
1662e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1663abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik	  handler_seq_no = handler->sequential_number;
1664e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->detail = detail;
1665e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
166612a0d19c11c29e3d4b7a5f02a07576309e2787a6Tim Janik	  g_closure_sink (handler->closure);
1667e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_insert (signal_id, instance, handler);
1668e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1669e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_closure_set_marshal (handler->closure, node->c_marshaller);
1670e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1671e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1672e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1673e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
16749369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1675e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1676abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  return handler_seq_no;
1677e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1678e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1679ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
1680cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_block (gpointer instance,
1681abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik                        gulong   handler_id)
1682cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1683cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  Handler *handler;
1684cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1685cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1686cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (handler_id > 0);
1687cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
16889369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1689cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  handler = handler_lookup (instance, handler_id, NULL);
1690cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (handler)
1691cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1692cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik#ifndef G_DISABLE_CHECKS
1693cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
1694cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik        g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
1695cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik#endif
1696cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      handler->block_count += 1;
1697cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
1698cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  else
1699abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik    g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id);
17009369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1701cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1702cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1703cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikvoid
1704cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_unblock (gpointer instance,
1705abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik                          gulong   handler_id)
1706cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1707cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  Handler *handler;
1708cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1709cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1710cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (handler_id > 0);
1711cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
17129369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1713cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  handler = handler_lookup (instance, handler_id, NULL);
1714cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (handler)
1715cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1716cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      if (handler->block_count)
1717cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik        handler->block_count -= 1;
1718cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      else
1719abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik        g_warning (G_STRLOC ": handler `%lu' of instance `%p' is not blocked", handler_id, instance);
1720cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
1721cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  else
1722abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik    g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id);
17239369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1724cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1725cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1726cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikvoid
1727ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_handler_disconnect (gpointer instance,
1728abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik                             gulong   handler_id)
1729ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1730ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler *handler;
1731ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint signal_id;
1732ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1733ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1734ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (handler_id > 0);
1735ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
17369369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1737ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler = handler_lookup (instance, handler_id, &signal_id);
1738ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (handler)
1739ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1740abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik      handler->sequential_number = 0;
1741ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->block_count = 1;
1742ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler_unref_R (signal_id, instance, handler);
1743ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1744ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
1745abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik    g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id);
17469369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1747ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1748ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
174972df5e6cabe02f155ff767650cdaf10046c26e0eTim Janikgboolean
175072df5e6cabe02f155ff767650cdaf10046c26e0eTim Janikg_signal_handler_is_connected (gpointer instance,
175172df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik			       gulong   handler_id)
175272df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik{
175372df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik  Handler *handler;
175472df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik  gboolean connected;
175572df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik
175672df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
175772df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik
17589369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
175972df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik  handler = handler_lookup (instance, handler_id, NULL);
176072df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik  connected = handler != NULL;
17619369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
176272df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik
176372df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik  return connected;
176472df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik}
176572df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik
1766ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
176783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikg_signal_handlers_destroy (gpointer instance)
1768ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1769ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa;
1770ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1771ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1772ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
17739369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1774ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
1775ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (hlbsa)
1776ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1777ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      guint i;
1778ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1779ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      /* reentrancy caution, delete instance trace first */
1780ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_hash_table_remove (g_handler_list_bsa_ht, instance);
178183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1782ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      for (i = 0; i < hlbsa->n_nodes; i++)
1783ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
1784a05a4b766073561baea10ba697fc7042c308719cTim Janik          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
1785ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          Handler *handler = hlist->handlers;
1786ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1787ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          while (handler)
1788ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            {
1789ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              Handler *tmp = handler;
1790ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1791ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              handler = tmp->next;
1792ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              tmp->block_count = 1;
1793ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              /* cruel unlink, this works because _all_ handlers vanish */
1794ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              tmp->next = NULL;
1795ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              tmp->prev = tmp;
1796abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik              if (tmp->sequential_number)
1797ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		{
1798abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik		  tmp->sequential_number = 0;
1799ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  handler_unref_R (0, NULL, tmp);
1800ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		}
1801ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            }
1802ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
18036d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik      g_bsearch_array_free (hlbsa, &g_signal_hlbsa_bconfig);
1804ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
18059369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1806ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1807ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1808abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janikgulong
1809cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_find (gpointer         instance,
1810cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       GSignalMatchType mask,
1811cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       guint            signal_id,
1812cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik		       GQuark		detail,
1813cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       GClosure        *closure,
1814cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       gpointer         func,
1815cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       gpointer         data)
1816ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1817abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  gulong handler_seq_no = 0;
1818ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1819cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1820cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
182183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1822cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & G_SIGNAL_MATCH_MASK)
1823ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
182483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      HandlerMatch *mlist;
182583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
18269369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_LOCK ();
182783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
182883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      if (mlist)
182983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	{
1830abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik	  handler_seq_no = mlist->handler->sequential_number;
183183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	  handler_match_free1_R (mlist, instance);
183283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	}
18339369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
1834ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
183583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1836abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  return handler_seq_no;
1837ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1838ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1839cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikstatic guint
184083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiksignal_handlers_foreach_matched_R (gpointer         instance,
184183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   GSignalMatchType mask,
184283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   guint            signal_id,
184383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   GQuark           detail,
184483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   GClosure        *closure,
184583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   gpointer         func,
184683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   gpointer         data,
184783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   void		  (*callback) (gpointer instance,
1848abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik							       gulong   handler_seq_no))
1849ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
185083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *mlist;
1851cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
185283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
185383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
185483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  while (mlist)
1855ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1856cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      n_handlers++;
1857abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik      if (mlist->handler->sequential_number)
1858abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik	{
18599369e1e022978100c521634a968968a901dd934cTim Janik	  SIGNAL_UNLOCK ();
1860abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik	  callback (instance, mlist->handler->sequential_number);
18619369e1e022978100c521634a968968a901dd934cTim Janik	  SIGNAL_LOCK ();
1862abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik	}
186383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      mlist = handler_match_free1_R (mlist, instance);
1864ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
186583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1866cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1867ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1868ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1869ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint
1870cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_block_matched (gpointer         instance,
1871cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 GSignalMatchType mask,
1872cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 guint            signal_id,
1873cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 GQuark           detail,
1874cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 GClosure        *closure,
1875cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 gpointer         func,
1876cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 gpointer         data)
1877ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1878cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
187983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
188010c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
188110c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
188283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1883cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1884cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
18859369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_LOCK ();
188683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
188783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      closure, func, data,
188883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      g_signal_handler_block);
18899369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
1890cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
189183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1892cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1893cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1894cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1895cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint
1896cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_unblock_matched (gpointer         instance,
1897cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   GSignalMatchType mask,
1898cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   guint            signal_id,
1899cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   GQuark           detail,
1900cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   GClosure        *closure,
1901cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   gpointer         func,
1902cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   gpointer         data)
1903cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1904cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
1905ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
190610c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
190710c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
1908ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1909cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1910cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
19119369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_LOCK ();
191283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
191383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      closure, func, data,
191483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      g_signal_handler_unblock);
19159369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
1916cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
191783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1918cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1919cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1920cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1921cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint
1922cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_disconnect_matched (gpointer         instance,
1923cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      GSignalMatchType mask,
1924cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      guint            signal_id,
1925cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      GQuark           detail,
1926cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      GClosure        *closure,
1927cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      gpointer         func,
1928cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      gpointer         data)
1929cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1930cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
193183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
193210c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
193310c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
193483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1935cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1936cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
19379369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_LOCK ();
193883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
193983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      closure, func, data,
194083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      g_signal_handler_disconnect);
19419369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
1942cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
194383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1944cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1945ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1946ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1947ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikgboolean
1948cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_has_handler_pending (gpointer instance,
1949cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik			      guint    signal_id,
1950cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik			      GQuark   detail,
1951cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik			      gboolean may_be_blocked)
1952ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
195383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *mlist;
195483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  gboolean has_pending;
1955ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1956ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1957ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (signal_id > 0, FALSE);
1958ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
19599369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
1960830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (detail)
1961830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
1962830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1963830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1964830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      if (!(node->flags & G_SIGNAL_DETAILED))
1965830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	{
1966830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
19679369e1e022978100c521634a968968a901dd934cTim Janik	  SIGNAL_UNLOCK ();
1968830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  return FALSE;
1969830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	}
1970830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    }
197183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  mlist = handlers_find (instance,
197283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik			 (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
197383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik			 signal_id, detail, NULL, NULL, NULL, TRUE);
197483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  if (mlist)
197583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    {
197683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      has_pending = TRUE;
197783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      handler_match_free1_R (mlist, instance);
197883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    }
197983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  else
198083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    has_pending = FALSE;
19819369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
1982ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
198383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return has_pending;
1984ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1985ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1986779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janikstatic inline gboolean
1987779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janiksignal_check_skip_emission (SignalNode *node,
1988779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik			    gpointer    instance,
1989779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik			    GQuark      detail)
1990779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik{
1991779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  HandlerList *hlist;
1992779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
1993779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  /* are we able to check for NULL class handlers? */
1994779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  if (!node->test_class_offset)
1995779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    return FALSE;
1996779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
1997779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  /* are there emission hooks pending? */
1998779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  if (node->emission_hooks && node->emission_hooks->hooks)
1999779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    return FALSE;
2000779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
2001779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  /* is there a non-NULL class handler? */
2002779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  if (node->test_class_offset != TEST_CLASS_MAGIC)
2003779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    {
2004779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      GTypeClass *class = G_TYPE_INSTANCE_GET_CLASS (instance, G_TYPE_FROM_INSTANCE (instance), GTypeClass);
2005779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
2006779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      if (G_STRUCT_MEMBER (gpointer, class, node->test_class_offset))
2007779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik	return FALSE;
2008779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    }
2009779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
2010779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  /* are signals being debugged? */
2011779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik#ifdef  G_ENABLE_DEBUG
2012779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  IF_DEBUG (SIGNALS, g_trace_instance_signals || g_trap_instance_signals)
2013779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    return FALSE;
2014779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik#endif /* G_ENABLE_DEBUG */
2015779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
2016779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  /* is this a no-recurse signal already in emission? */
2017779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  if (node->flags & G_SIGNAL_NO_RECURSE &&
2018779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      emission_find (g_restart_emissions, node->signal_id, detail, instance))
2019779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    return FALSE;
2020779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
2021779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  /* do we have pending handlers? */
2022779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  hlist = handler_list_lookup (node->signal_id, instance);
2023779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  if (hlist && hlist->handlers)
2024779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    return FALSE;
2025779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
2026779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  /* none of the above, no emission required */
2027779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  return TRUE;
2028779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik}
2029779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
2030ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
2031ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_emitv (const GValue *instance_and_params,
2032ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		guint         signal_id,
2033830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		GQuark	      detail,
2034ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		GValue       *return_value)
2035ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
2036ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  const GValue *param_values;
2037e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  gpointer instance;
2038e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  SignalNode *node;
2039624a3c9689a9538af7df04aab389423edc82b51aDarin Adler#ifdef G_ENABLE_DEBUG
2040ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint i;
2041624a3c9689a9538af7df04aab389423edc82b51aDarin Adler#endif
2042ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2043ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (instance_and_params != NULL);
204437e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik  instance = g_value_peek_pointer (instance_and_params);
2045ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2046ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (signal_id > 0);
2047e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2048ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  param_values = instance_and_params + 1;
2049ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
20509369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
2051ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
2052e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
2053cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
2054cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
20559369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
2056cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      return;
2057cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
2058782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifdef G_ENABLE_DEBUG
2059830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (detail && !(node->flags & G_SIGNAL_DETAILED))
2060830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
2061830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
20629369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
2063830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      return;
2064830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    }
2065ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  for (i = 0; i < node->n_params; i++)
206637e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik    if (!G_TYPE_CHECK_VALUE_TYPE (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
2067ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      {
2068e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'",
2069e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		    G_STRLOC,
2070116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor		    type_debug_name (node->param_types[i]),
2071ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    i,
2072ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    node->name,
2073ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    G_VALUE_TYPE_NAME (param_values + i));
20749369e1e022978100c521634a968968a901dd934cTim Janik	SIGNAL_UNLOCK ();
2075ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	return;
2076ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      }
2077ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node->return_type != G_TYPE_NONE)
2078ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
2079ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (!return_value)
2080ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
2081e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)",
2082e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      G_STRLOC,
2083116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor		      type_debug_name (node->return_type),
2084ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      node->name);
20859369e1e022978100c521634a968968a901dd934cTim Janik	  SIGNAL_UNLOCK ();
2086ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  return;
2087ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
208837e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik      else if (!node->accumulator && !G_TYPE_CHECK_VALUE_TYPE (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
2089ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
2090e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'",
2091e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      G_STRLOC,
2092116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor		      type_debug_name (node->return_type),
2093ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      node->name,
2094ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      G_VALUE_TYPE_NAME (return_value));
20959369e1e022978100c521634a968968a901dd934cTim Janik	  SIGNAL_UNLOCK ();
2096ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  return;
2097ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
2098ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
2099ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
2100ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return_value = NULL;
2101782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#endif	/* G_ENABLE_DEBUG */
2102e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2103779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  /* optimize NOP emissions */
2104779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  if (signal_check_skip_emission (node, instance, detail))
2105779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    {
2106779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      /* nothing to do to emit this signal */
2107779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      SIGNAL_UNLOCK ();
2108779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
2109779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      return;
2110779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    }
2111779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
21129369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
2113e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  signal_emit_unlocked_R (node, detail, instance, return_value, instance_and_params);
2114ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
2115ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2116e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid
2117e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit_valist (gpointer instance,
2118e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      guint    signal_id,
2119e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      GQuark   detail,
2120e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      va_list  var_args)
2121e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
2122e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL;
2123e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  GType signal_return_type;
2124e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GValue *param_values;
2125e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  SignalNode *node;
2126e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  guint i, n_params;
2127e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik
2128e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2129e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (signal_id > 0);
2130e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
21319369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
2132e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
2133e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
2134e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
2135e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
21369369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
2137e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return;
2138e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
2139e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#ifndef G_DISABLE_CHECKS
2140e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (detail && !(node->flags & G_SIGNAL_DETAILED))
2141e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
2142e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
21439369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
2144e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return;
2145e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
2146e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#endif  /* !G_DISABLE_CHECKS */
2147e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2148779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  /* optimize NOP emissions */
2149779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik  if (signal_check_skip_emission (node, instance, detail))
2150779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    {
2151779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      /* nothing to do to emit this signal */
2152779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      SIGNAL_UNLOCK ();
2153779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
2154779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik      return;
2155779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik    }
2156779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik
2157e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  n_params = node->n_params;
2158e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  signal_return_type = node->return_type;
2159e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (node->n_params < MAX_STACK_VALUES)
2160e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    instance_and_params = stack_values;
2161e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
2162e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
2163e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      free_me = g_new (GValue, node->n_params + 1);
2164e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      instance_and_params = free_me;
2165e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
2166e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  param_values = instance_and_params + 1;
2167e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  for (i = 0; i < node->n_params; i++)
2168e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
2169e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      gchar *error;
2170e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik      GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
2171e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik      gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
2172e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik
2173e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      param_values[i].g_type = 0;
21749369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
2175e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik      g_value_init (param_values + i, ptype);
2176bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik      G_VALUE_COLLECT (param_values + i,
2177bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik		       var_args,
2178e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik		       static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
2179bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik		       &error);
2180e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (error)
2181e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
2182e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_warning ("%s: %s", G_STRLOC, error);
2183e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (error);
2184e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2185e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  /* we purposely leak the value here, it might not be
2186e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	   * in a sane state if an error condition occoured
2187e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	   */
2188e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  while (i--)
2189e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_value_unset (param_values + i);
2190e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2191e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (free_me);
2192e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  return;
2193e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
21949369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_LOCK ();
2195e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
21969369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
2197e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  instance_and_params->g_type = 0;
2198f3ec41e8d22b5fa99b93ea753acb0de873732e94Jonathan Blandford  g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (instance));
2199e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_value_set_instance (instance_and_params, instance);
2200e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  if (signal_return_type == G_TYPE_NONE)
2201e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik    signal_emit_unlocked_R (node, detail, instance, NULL, instance_and_params);
2202e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
2203e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
2204e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      GValue return_value = { 0, };
2205e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      gchar *error = NULL;
2206e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik      GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
2207e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik      gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
2208e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik
2209e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik      g_value_init (&return_value, rtype);
2210e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik
2211e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik      signal_emit_unlocked_R (node, detail, instance, &return_value, instance_and_params);
2212e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2213743f49cec9f4696c9eba32966d6ac78cd96c586dTim Janik      G_VALUE_LCOPY (&return_value,
2214743f49cec9f4696c9eba32966d6ac78cd96c586dTim Janik		     var_args,
2215e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik		     static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
2216743f49cec9f4696c9eba32966d6ac78cd96c586dTim Janik		     &error);
2217e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (!error)
2218e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_value_unset (&return_value);
2219e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
2220e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
2221e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_warning ("%s: %s", G_STRLOC, error);
2222e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (error);
2223e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik
2224e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  /* we purposely leak the value here, it might not be
2225160cd96ae26a571e76af717c27ae29b8125a54a5Matthias Clasen	   * in a sane state if an error condition occured
2226e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	   */
2227e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
2228e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
2229e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  for (i = 0; i < n_params; i++)
2230e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_value_unset (param_values + i);
2231e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_value_unset (instance_and_params);
2232e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (free_me)
2233e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_free (free_me);
2234e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
2235e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2236e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid
2237e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit (gpointer instance,
2238e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	       guint    signal_id,
2239e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	       GQuark   detail,
2240e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	       ...)
2241e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
2242e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  va_list var_args;
2243e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2244e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  va_start (var_args, detail);
2245e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_signal_emit_valist (instance, signal_id, detail, var_args);
2246e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  va_end (var_args);
2247e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
2248e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2249e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid
2250e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit_by_name (gpointer     instance,
2251e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       const gchar *detailed_signal,
2252e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       ...)
2253e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
2254e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GQuark detail = 0;
2255e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint signal_id;
2256e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2257e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
2258e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (detailed_signal != NULL);
2259e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
22609369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
2261e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE);
22629369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
2263e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2264e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (signal_id)
2265e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
2266e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      va_list var_args;
2267e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2268e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      va_start (var_args, detailed_signal);
2269e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_signal_emit_valist (instance, signal_id, detail, var_args);
2270e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      va_end (var_args);
2271e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
2272e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
2273e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
2274e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
2275e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2276617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikstatic inline gboolean
2277617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikaccumulate (GSignalInvocationHint *ihint,
2278617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	    GValue                *return_accu,
2279617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	    GValue	          *handler_return,
2280617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	    SignalAccumulator     *accumulator)
2281617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{
2282617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  gboolean continue_emission;
2283617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
2284617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  if (!accumulator)
2285617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    return TRUE;
2286617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
2287617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data);
2288617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  g_value_reset (handler_return);
2289617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
2290617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  return continue_emission;
2291617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik}
2292617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
2293e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikstatic gboolean
2294e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janiksignal_emit_unlocked_R (SignalNode   *node,
2295e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik			GQuark	      detail,
2296e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik			gpointer      instance,
2297e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik			GValue	     *emission_return,
2298e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik			const GValue *instance_and_params)
2299ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
2300617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  SignalAccumulator *accumulator;
2301a05a4b766073561baea10ba697fc7042c308719cTim Janik  Emission emission;
2302ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GClosure *class_closure;
2303ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList *hlist;
2304830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  Handler *handler_list = NULL;
2305617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  GValue *return_accu, accu = { 0, };
2306e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  guint signal_id;
2307abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  gulong max_sequential_handler_number;
2308e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  gboolean return_value_altered = FALSE;
2309ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
231022357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#ifdef	G_ENABLE_DEBUG
231122357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik  IF_DEBUG (SIGNALS, g_trace_instance_signals == instance || g_trap_instance_signals == instance)
231222357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik    {
231343b692c8eb49a82657d9cb09a222dc66f2cc0199Tim Janik      g_message ("%s::%s(%u) emitted (instance=%p, signal-node=%p)",
231422357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik		 g_type_name (G_TYPE_FROM_INSTANCE (instance)),
231522357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik		 node->name, detail,
231622357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik		 instance, node);
231722357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik      if (g_trap_instance_signals == instance)
231822357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik	G_BREAKPOINT ();
231922357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik    }
232022357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#endif	/* G_ENABLE_DEBUG */
232122357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik
23229369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_LOCK ();
2323e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik  signal_id = node->signal_id;
2324ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node->flags & G_SIGNAL_NO_RECURSE)
2325ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
2326a05a4b766073561baea10ba697fc7042c308719cTim Janik      Emission *node = emission_find (g_restart_emissions, signal_id, detail, instance);
2327ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2328a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (node)
2329ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
2330a05a4b766073561baea10ba697fc7042c308719cTim Janik	  node->state = EMISSION_RESTART;
23319369e1e022978100c521634a968968a901dd934cTim Janik	  SIGNAL_UNLOCK ();
2332e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  return return_value_altered;
2333ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
2334ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
2335ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  accumulator = node->accumulator;
2336ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (accumulator)
2337617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    {
23389369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
2339617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
2340617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      return_accu = &accu;
23419369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_LOCK ();
2342617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    }
2343617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik  else
2344617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik    return_accu = emission_return;
2345a05a4b766073561baea10ba697fc7042c308719cTim Janik  emission.instance = instance;
2346a05a4b766073561baea10ba697fc7042c308719cTim Janik  emission.ihint.signal_id = node->signal_id;
2347a05a4b766073561baea10ba697fc7042c308719cTim Janik  emission.ihint.detail = detail;
2348a05a4b766073561baea10ba697fc7042c308719cTim Janik  emission.ihint.run_type = 0;
2349a05a4b766073561baea10ba697fc7042c308719cTim Janik  emission.state = 0;
2350a05a4b766073561baea10ba697fc7042c308719cTim Janik  emission.chain_type = G_TYPE_NONE;
2351a05a4b766073561baea10ba697fc7042c308719cTim Janik  emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission);
2352a05a4b766073561baea10ba697fc7042c308719cTim Janik  class_closure = signal_lookup_closure (node, instance);
2353ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2354ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMIT_RESTART:
2355ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2356830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
2357830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    handler_unref_R (signal_id, instance, handler_list);
2358abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik  max_sequential_handler_number = g_handler_sequential_number;
2359830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  hlist = handler_list_lookup (signal_id, instance);
2360830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  handler_list = hlist ? hlist->handlers : NULL;
2361830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
2362830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    handler_ref (handler_list);
2363830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
2364a05a4b766073561baea10ba697fc7042c308719cTim Janik  emission.ihint.run_type = G_SIGNAL_RUN_FIRST;
2365830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
2366ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
2367ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
2368a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.state = EMISSION_RUN;
2369a05a4b766073561baea10ba697fc7042c308719cTim Janik
2370a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
23719369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
2372617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      g_closure_invoke (class_closure,
2373617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik			return_accu,
2374617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik			node->n_params + 1,
2375617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik			instance_and_params,
2376a05a4b766073561baea10ba697fc7042c308719cTim Janik			&emission.ihint);
2377a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2378a05a4b766073561baea10ba697fc7042c308719cTim Janik	  emission.state == EMISSION_RUN)
2379a05a4b766073561baea10ba697fc7042c308719cTim Janik	emission.state = EMISSION_STOP;
23809369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_LOCK ();
2381a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.chain_type = G_TYPE_NONE;
2382e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return_value_altered = TRUE;
2383ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2384a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (emission.state == EMISSION_STOP)
2385ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
2386a05a4b766073561baea10ba697fc7042c308719cTim Janik      else if (emission.state == EMISSION_RESTART)
2387ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
2388ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
2389ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2390ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node->emission_hooks)
2391ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
2392617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      gboolean need_destroy, was_in_call, may_recurse = TRUE;
2393617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      GHook *hook;
23949490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik
2395a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.state = EMISSION_HOOK;
2396617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      hook = g_hook_first_valid (node->emission_hooks, may_recurse);
2397617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      while (hook)
2398617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	{
23999490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik	  SignalHook *signal_hook = SIGNAL_HOOK (hook);
2400617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
24019490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik	  if (!signal_hook->detail || signal_hook->detail == detail)
2402617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	    {
2403738c1cfd6bc87a410324209e8e96f76f90ada720Erwann Chenede	      GSignalEmissionHook hook_func = (GSignalEmissionHook) hook->func;
2404617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
2405617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	      was_in_call = G_HOOK_IN_CALL (hook);
2406617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	      hook->flags |= G_HOOK_FLAG_IN_CALL;
24079369e1e022978100c521634a968968a901dd934cTim Janik              SIGNAL_UNLOCK ();
2408a05a4b766073561baea10ba697fc7042c308719cTim Janik	      need_destroy = !hook_func (&emission.ihint, node->n_params + 1, instance_and_params, hook->data);
24099369e1e022978100c521634a968968a901dd934cTim Janik	      SIGNAL_LOCK ();
2410617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	      if (!was_in_call)
2411617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik		hook->flags &= ~G_HOOK_FLAG_IN_CALL;
2412617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	      if (need_destroy)
2413617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik		g_hook_destroy_link (node->emission_hooks, hook);
2414617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	    }
2415617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	  hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse);
2416617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	}
2417ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2418a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (emission.state == EMISSION_RESTART)
2419ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
2420ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
2421ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2422830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
2423ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
2424830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      Handler *handler = handler_list;
2425ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2426a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.state = EMISSION_RUN;
2427ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler_ref (handler);
2428ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      do
2429ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
2430ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  Handler *tmp;
2431ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2432830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  if (handler->after)
2433830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    {
2434830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      handler_unref_R (signal_id, instance, handler_list);
2435830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      handler_list = handler;
2436830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      break;
2437830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    }
2438abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik	  else if (!handler->block_count && (!handler->detail || handler->detail == detail) &&
2439abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik		   handler->sequential_number < max_sequential_handler_number)
2440ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    {
24419369e1e022978100c521634a968968a901dd934cTim Janik	      SIGNAL_UNLOCK ();
2442617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	      g_closure_invoke (handler->closure,
2443617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik				return_accu,
2444617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik				node->n_params + 1,
2445617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik				instance_and_params,
2446a05a4b766073561baea10ba697fc7042c308719cTim Janik				&emission.ihint);
2447a05a4b766073561baea10ba697fc7042c308719cTim Janik	      if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2448a05a4b766073561baea10ba697fc7042c308719cTim Janik		  emission.state == EMISSION_RUN)
2449a05a4b766073561baea10ba697fc7042c308719cTim Janik		emission.state = EMISSION_STOP;
24509369e1e022978100c521634a968968a901dd934cTim Janik	      SIGNAL_LOCK ();
2451e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	      return_value_altered = TRUE;
2452ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2453a05a4b766073561baea10ba697fc7042c308719cTim Janik	      tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
2454ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    }
2455ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  else
2456ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    tmp = handler->next;
2457ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2458ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (tmp)
2459ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    handler_ref (tmp);
2460830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  handler_unref_R (signal_id, instance, handler_list);
2461830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  handler_list = handler;
2462ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  handler = tmp;
2463ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
2464ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      while (handler);
2465ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2466a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (emission.state == EMISSION_STOP)
2467ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
2468a05a4b766073561baea10ba697fc7042c308719cTim Janik      else if (emission.state == EMISSION_RESTART)
2469ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
2470ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
2471ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2472a05a4b766073561baea10ba697fc7042c308719cTim Janik  emission.ihint.run_type = G_SIGNAL_RUN_LAST;
2473830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
2474ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
2475ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
2476a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.state = EMISSION_RUN;
2477ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2478a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
24799369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
2480617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      g_closure_invoke (class_closure,
2481617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik			return_accu,
2482617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik			node->n_params + 1,
2483617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik			instance_and_params,
2484a05a4b766073561baea10ba697fc7042c308719cTim Janik			&emission.ihint);
2485a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2486a05a4b766073561baea10ba697fc7042c308719cTim Janik	  emission.state == EMISSION_RUN)
2487a05a4b766073561baea10ba697fc7042c308719cTim Janik	emission.state = EMISSION_STOP;
24889369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_LOCK ();
2489a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.chain_type = G_TYPE_NONE;
2490e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return_value_altered = TRUE;
2491ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2492a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (emission.state == EMISSION_STOP)
2493ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
2494a05a4b766073561baea10ba697fc7042c308719cTim Janik      else if (emission.state == EMISSION_RESTART)
2495ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
2496ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
2497ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2498830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
2499ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
2500830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      Handler *handler = handler_list;
2501ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2502a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.state = EMISSION_RUN;
2503ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler_ref (handler);
2504ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      do
2505ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
2506ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  Handler *tmp;
2507ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2508abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik	  if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail) &&
2509abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik	      handler->sequential_number < max_sequential_handler_number)
2510ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    {
25119369e1e022978100c521634a968968a901dd934cTim Janik	      SIGNAL_UNLOCK ();
2512617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	      g_closure_invoke (handler->closure,
2513617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik				return_accu,
2514617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik				node->n_params + 1,
2515617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik				instance_and_params,
2516a05a4b766073561baea10ba697fc7042c308719cTim Janik				&emission.ihint);
2517a05a4b766073561baea10ba697fc7042c308719cTim Janik	      if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
2518a05a4b766073561baea10ba697fc7042c308719cTim Janik		  emission.state == EMISSION_RUN)
2519a05a4b766073561baea10ba697fc7042c308719cTim Janik		emission.state = EMISSION_STOP;
25209369e1e022978100c521634a968968a901dd934cTim Janik	      SIGNAL_LOCK ();
2521e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	      return_value_altered = TRUE;
2522ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2523a05a4b766073561baea10ba697fc7042c308719cTim Janik	      tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
2524ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    }
2525ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  else
2526ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    tmp = handler->next;
2527ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2528ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (tmp)
2529ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    handler_ref (tmp);
2530ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  handler_unref_R (signal_id, instance, handler);
2531ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  handler = tmp;
2532ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
2533ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      while (handler);
2534ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2535a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (emission.state == EMISSION_STOP)
2536ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
2537a05a4b766073561baea10ba697fc7042c308719cTim Janik      else if (emission.state == EMISSION_RESTART)
2538ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
2539ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
2540ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2541ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMIT_CLEANUP:
2542ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2543a05a4b766073561baea10ba697fc7042c308719cTim Janik  emission.ihint.run_type = G_SIGNAL_RUN_CLEANUP;
2544830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
2545ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
2546ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
2547830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      gboolean need_unset = FALSE;
2548830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
2549a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.state = EMISSION_STOP;
2550ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2551a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
25529369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_UNLOCK ();
2553617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik      if (node->return_type != G_TYPE_NONE && !accumulator)
2554ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
2555617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	  g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
2556617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik	  need_unset = TRUE;
2557ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
2558ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_closure_invoke (class_closure,
2559ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			node->return_type != G_TYPE_NONE ? &accu : NULL,
2560ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			node->n_params + 1,
2561830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			instance_and_params,
2562a05a4b766073561baea10ba697fc7042c308719cTim Janik			&emission.ihint);
2563830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      if (need_unset)
2564ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_value_unset (&accu);
25659369e1e022978100c521634a968968a901dd934cTim Janik      SIGNAL_LOCK ();
2566a05a4b766073561baea10ba697fc7042c308719cTim Janik      emission.chain_type = G_TYPE_NONE;
2567830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
2568a05a4b766073561baea10ba697fc7042c308719cTim Janik      if (emission.state == EMISSION_RESTART)
2569ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
2570ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
2571ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2572830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
2573830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    handler_unref_R (signal_id, instance, handler_list);
2574ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2575a05a4b766073561baea10ba697fc7042c308719cTim Janik  emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission);
25769369e1e022978100c521634a968968a901dd934cTim Janik  SIGNAL_UNLOCK ();
2577ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (accumulator)
2578e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_value_unset (&accu);
2579617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik
2580e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  return return_value_altered;
2581ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
2582e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2583116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylorstatic const gchar*
2584116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylortype_debug_name (GType type)
2585116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor{
2586116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor  if (type)
2587116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor    {
2588116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor      const char *name = g_type_name (type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
2589116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor      return name ? name : "<unknown>";
2590116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor    }
2591116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor  else
2592116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor    return "<invalid>";
2593116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor}
2594e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
259532bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylorgboolean
259632bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylorg_signal_accumulator_true_handled (GSignalInvocationHint *ihint,
259732bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor				   GValue                *return_accu,
259832bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor				   const GValue          *handler_return,
259932bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor				   gpointer               dummy)
260032bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor{
260132bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor  gboolean continue_emission;
260232bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor  gboolean signal_handled;
260332bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor
260432bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor  signal_handled = g_value_get_boolean (handler_return);
260532bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor  g_value_set_boolean (return_accu, signal_handled);
260632bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor  continue_emission = !signal_handled;
260732bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor
260832bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor  return continue_emission;
260932bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor}
261032bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor
2611f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik/* --- compile standard marshallers --- */
261237e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik#include	"gobject.h"
261337e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik#include	"genums.h"
2614e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#include        "gmarshal.c"
2615