gsignal.c revision f0b9abe801c2e0cccb7930421a81bb77031e3251
1ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* GObject - GLib Type, Object, Parameter and Signal Library
2ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Copyright (C) 2000 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
27ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#include        "gsignal.h"
28ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#include        "gbsearcharray.h"
29e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#include        "gvaluecollector.h"
30f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#include	<string.h>
31ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
32ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
33ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* pre allocation configurations
34ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */
35e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#define	MAX_STACK_VALUES	(16)
36ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define BSA_PRE_ALLOC           (20)
37ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_PRE_ALLOC       (48)
38ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define EMISSION_PRE_ALLOC      (16)
39ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
40ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define REPORT_BUG      "please report occourance circumstances to gtk-devel-list@gnome.org"
41ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
42ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
43ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- generic allocation --- */
44782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik/* we special case allocations generically by replacing
45ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * these functions with more speed/memory aware variants
46ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */
47782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifndef	DISABLE_MEM_POOLS
48ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline gpointer
49ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_generic_node_alloc (GTrashStack **trash_stack_p,
50ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                      guint         sizeof_node,
51ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                      guint         nodes_pre_alloc)
52ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
53ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gpointer node = g_trash_stack_pop (trash_stack_p);
54ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
55ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!node)
56ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
57ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      guint8 *block;
58ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
59ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
60ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      block = g_malloc (sizeof_node * nodes_pre_alloc);
61ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      while (--nodes_pre_alloc)
62ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
63ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          g_trash_stack_push (trash_stack_p, block);
64ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          block += sizeof_node;
65ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
66ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node = block;
67ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
68ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
69ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return node;
70ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
71f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#define	g_generic_node_free(trash_stack_p, node) g_trash_stack_push (trash_stack_p, node)
72782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#else	/* !DISABLE_MEM_POOLS */
73f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#define	g_generic_node_alloc(t,sizeof_node,p)	 g_malloc (sizeof_node)
74f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#define	g_generic_node_free(t,node)		 g_free (node)
75782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#endif	/* !DISABLE_MEM_POOLS */
76ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
77ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
78ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- typedefs --- */
7983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _SignalNode   SignalNode;
8083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _SignalKey    SignalKey;
8183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _Emission     Emission;
8283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _Handler      Handler;
8383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _HandlerList  HandlerList;
8483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _HandlerMatch HandlerMatch;
85ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiktypedef enum
86ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
87ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_STOP,
88ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_RUN,
89ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_HOOK,
90ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_RESTART
91ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} EmissionState;
92ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
93ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
94ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- prototypes --- */
9583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline guint		signal_id_lookup	(GQuark		  quark,
9683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GType		  itype);
9783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      void		signal_destroy_R	(SignalNode	 *signal_node);
9883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerList*	handler_list_ensure	(guint		  signal_id,
9983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
10083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerList*	handler_list_lookup	(guint		  signal_id,
10183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
10283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline Handler*		handler_new		(gboolean	  after);
10383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      void		handler_insert		(guint		  signal_id,
10483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance,
10583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 Handler	 *handler);
10683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      Handler*		handler_lookup		(gpointer	  instance,
10783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  handler_id,
10883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		 *signal_id_p);
10983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*	handler_match_prepend	(HandlerMatch	 *list,
11083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 Handler	 *handler,
11183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  signal_id);
11283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*	handler_match_free1_R	(HandlerMatch	 *node,
11383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
11483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      HandlerMatch*	handlers_find		(gpointer	  instance,
11583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GSignalMatchType mask,
11683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  signal_id,
11783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GQuark		  detail,
11883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GClosure	 *closure,
11983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  func,
12083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  data,
12183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gboolean	  one_and_only);
12283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		handler_ref		(Handler	 *handler);
12383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		handler_unref_R		(guint		  signal_id,
12483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance,
12583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 Handler	 *handler);
12683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		emission_push		(Emission	**emission_list_p,
12783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  signal_id,
12883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GQuark		  detail,
12983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance,
13083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 EmissionState	 *state_p);
13183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		emission_pop		(Emission	**emission_list_p,
13283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 EmissionState	 *state_p);
13383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline Emission*		emission_find		(Emission	 *emission_list,
13483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  signal_id,
13583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GQuark		  detail,
13683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
137e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikstatic	      gboolean		signal_emit_R		(SignalNode	 *node,
13883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GQuark		  detail,
13983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance,
14083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GValue		 *return_value,
14183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 const GValue	 *instance_and_params);
142ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
143ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
144ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- structures --- */
145ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _SignalNode
146ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
147ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* permanent portion */
148ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              signal_id;
149ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GType              itype;
150ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gchar             *name;
151ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              destroyed : 1;
152ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
153ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* reinitializable portion */
154ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              flags : 8;
155ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              n_params : 8;
156ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GType		    *param_types;
157ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GType		     return_type;
158ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GClosure          *class_closure;
159ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GSignalAccumulator accumulator;
160ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GSignalCMarshaller c_marshaller;
161ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GHookList         *emission_hooks;
162ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
163ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
164ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _SignalKey
165ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
166ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GType  itype;
167ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GQuark quark;
168ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint  signal_id;
169ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
170ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
171ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _Emission
172ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
173ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Emission      *next;
174ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint          signal_id;
175830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  GQuark	 detail;
176ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gpointer       instance;
177ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EmissionState *state_p;
178ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
179ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
180ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _HandlerList
181ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
182ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint    signal_id;
183ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler *handlers;
184ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
185ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _Handler
186ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
187ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint         id;
188ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler      *next;
189ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler      *prev;
190830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  GQuark	detail;
191ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint         ref_count : 16;
192ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_MAX_REF_COUNT   (1 << 16)
193ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint         block_count : 12;
194ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_MAX_BLOCK_COUNT (1 << 12)
195ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint         after : 1;
196ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GClosure     *closure;
197ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
19883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstruct _HandlerMatch
19983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{
20083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  Handler      *handler;
20183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *next;
20283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  union {
20383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    guint       signal_id;
20483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    gpointer	dummy;
20583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  } d;
20683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik};
207ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
208ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
209ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- variables --- */
210ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GBSearchArray  g_signal_key_bsa = { NULL, 0, 0, 0, NULL };
211ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GHashTable    *g_handler_list_bsa_ht = NULL;
212ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Emission      *g_recursive_emissions = NULL;
213ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Emission      *g_restart_emissions = NULL;
214ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GTrashStack   *g_bsa_ts = NULL;
215ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GTrashStack   *g_handler_ts = NULL;
216ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GTrashStack   *g_emission_ts = NULL;
217ee23c09e83d06a0d131ebd234c132f1c3602c019Tim JanikG_LOCK_DEFINE_STATIC (g_signal_mutex);
218ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
219ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
220ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- signal nodes --- */
221ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic guint          g_n_signal_nodes = 0;
222ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic SignalNode   **g_signal_nodes = NULL;
223ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
224ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline SignalNode*
225ee23c09e83d06a0d131ebd234c132f1c3602c019Tim JanikLOOKUP_SIGNAL_NODE (register guint signal_id)
226ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
227ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (signal_id < g_n_signal_nodes)
228ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return g_signal_nodes[signal_id];
229ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
230ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return NULL;
231ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
232ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
233ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
234ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- functions --- */
235ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline guint
236ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_id_lookup (GQuark quark,
237ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  GType  itype)
238ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
239e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GType *ifaces, type = itype;
240e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  SignalKey key;
241e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint n_ifaces;
242e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
243e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  key.quark = quark;
244e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
245e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  /* try looking up signals for this type and its anchestors */
2468a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  do
2478a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik    {
248e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalKey *signal_key;
2498a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik
250e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      key.itype = type;
2518a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik      signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
2528a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik
2538a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik      if (signal_key)
2548a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik	return signal_key->signal_id;
2558a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik
256e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      type = g_type_parent (type);
2578a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik    }
258e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  while (type);
259e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
260e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  /* no luck, try interfaces it exports */
261e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  ifaces = g_type_interfaces (itype, &n_ifaces);
262e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  while (n_ifaces--)
263e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
264e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalKey *signal_key;
265e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
266e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      key.itype = ifaces[n_ifaces];
267e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
268e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
269e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (signal_key)
270e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
271e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (ifaces);
272e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  return signal_key->signal_id;
273e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
274e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
275e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_free (ifaces);
276ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2778a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  return 0;
278ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
279ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
280ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic gint
281ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_lists_cmp (gconstpointer node1,
282ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                   gconstpointer node2)
283ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
284ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  const HandlerList *hlist1 = node1, *hlist2 = node2;
285ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
286ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
287ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
288ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
289ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline HandlerList*
290ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_list_ensure (guint    signal_id,
291ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		     gpointer instance)
292ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
293ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
294ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList key;
295ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
296ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!hlbsa)
297ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
298ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa = g_generic_node_alloc (&g_bsa_ts,
299ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                    sizeof (GBSearchArray),
300ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                    BSA_PRE_ALLOC);
301ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa->cmp_func = handler_lists_cmp;
302ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa->sizeof_node = sizeof (HandlerList);
303ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa->flags = G_BSEARCH_DEFER_SHRINK;
304ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa->n_nodes = 0;
305ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa->nodes = NULL;
306ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
307ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
308ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  key.signal_id = signal_id;
309ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  key.handlers = NULL;
310ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
311ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return g_bsearch_array_insert (hlbsa, &key, FALSE);
312ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
313ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
314ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline HandlerList*
315ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_list_lookup (guint    signal_id,
316ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		     gpointer instance)
317ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
318ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
319ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList key;
320ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
321ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  key.signal_id = signal_id;
322ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
323ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL;
324ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
325ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
326ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Handler*
327ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_lookup (gpointer instance,
328ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		guint    handler_id,
329ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		guint   *signal_id_p)
330ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
331ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
332ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
333ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (hlbsa)
334ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
335ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      guint i;
336ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
337ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      for (i = 0; i < hlbsa->n_nodes; i++)
338ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
339ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
340ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          Handler *handler;
341ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
342ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          for (handler = hlist->handlers; handler; handler = handler->next)
343ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            if (handler->id == handler_id)
344ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              {
345ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                if (signal_id_p)
346ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                  *signal_id_p = hlist->signal_id;
347ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
348ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                return handler;
349ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              }
350ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
351ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
352ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
353ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return NULL;
354ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
355ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
35683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*
35783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandler_match_prepend (HandlerMatch *list,
35883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		       Handler      *handler,
35983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		       guint	     signal_id)
36083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{
36183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *node;
36283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
36383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  /* yeah, we could use our own memchunk here, introducing yet more
36483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   * rarely used cached nodes and extra allocation overhead.
36583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   * instead, we use GList* nodes, since they are exactly the size
36683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   * we need and are already cached. g_signal_init() asserts this.
36783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   */
36883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node = (HandlerMatch*) g_list_alloc ();
36983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node->handler = handler;
37083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node->next = list;
37183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node->d.signal_id = signal_id;
37283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  handler_ref (handler);
37383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
37483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return node;
37583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik}
37683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*
37783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandler_match_free1_R (HandlerMatch *node,
37883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		       gpointer      instance)
37983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{
38083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *next = node->next;
38183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
38283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  handler_unref_R (node->d.signal_id, instance, node->handler);
38383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  g_list_free_1 ((GList*) node);
38483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
38583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return next;
38683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik}
38783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
38883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic HandlerMatch*
38983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandlers_find (gpointer         instance,
39083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       GSignalMatchType mask,
39183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       guint            signal_id,
39283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       GQuark           detail,
39383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       GClosure        *closure,
39483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       gpointer         func,
39583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       gpointer         data,
39683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       gboolean         one_and_only)
397ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
39883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *mlist = NULL;
39983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
400ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (mask & G_SIGNAL_MATCH_ID)
401ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
402ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      HandlerList *hlist = handler_list_lookup (signal_id, instance);
403ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      Handler *handler;
404790a7bd3be608d9b12a18711d4400490d96b2a46Elliot Lee      SignalNode *node = NULL;
405ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
40655ec7f32a6852dba73abb29e650615b66b065ef9Tim Janik      if (mask & G_SIGNAL_MATCH_FUNC)
407ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
408ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  node = LOOKUP_SIGNAL_NODE (signal_id);
409ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (!node || !node->c_marshaller)
410ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    return NULL;
411ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
41283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
413ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      mask = ~mask;
414ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
41583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik        if (handler->id &&
41683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	    ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
417830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
418ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
419830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
420ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
421ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik					      handler->closure->meta_marshal == 0 &&
422ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik					      ((GCClosure*) handler->closure)->callback == func)))
42383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	  {
42483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	    mlist = handler_match_prepend (mlist, handler, signal_id);
42583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	    if (one_and_only)
42683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	      return mlist;
42783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	  }
428ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
429ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
430ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
431ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
432ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
433ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      mask = ~mask;
434ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (hlbsa)
435ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
436ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          guint i;
437ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
438ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          for (i = 0; i < hlbsa->n_nodes; i++)
439ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            {
440ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
441790a7bd3be608d9b12a18711d4400490d96b2a46Elliot Lee	      SignalNode *node = NULL;
442ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              Handler *handler;
443ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
444ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      if (!(mask & G_SIGNAL_MATCH_FUNC))
445ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		{
446ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
447ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  if (!node->c_marshaller)
448ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    continue;
449ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		}
45083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
451ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              for (handler = hlist->handlers; handler; handler = handler->next)
45283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		if (handler->id &&
45383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		    ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
454830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik                    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
455ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                    ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
456830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
457ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
458ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik						      handler->closure->meta_marshal == 0 &&
459ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik						      ((GCClosure*) handler->closure)->callback == func)))
46083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		  {
461a453526f350a3956a26f71db481bd8b436c65f97Owen Taylor		    mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
46283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		    if (one_and_only)
46383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		      return mlist;
46483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		  }
465ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            }
466ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
467ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
468ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
46983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return mlist;
470ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
471ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
472ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline Handler*
473ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_new (gboolean after)
474ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
475ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  static guint handler_id = 1;
476ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler *handler = g_generic_node_alloc (&g_handler_ts,
477ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                           sizeof (Handler),
478ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                           HANDLER_PRE_ALLOC);
479ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#ifndef G_DISABLE_CHECKS
480ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (handler_id == 0)
481ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
482ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif
483ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
484ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->id = handler_id++;
485ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->prev = NULL;
486ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->next = NULL;
487830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  handler->detail = 0;
488ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->ref_count = 1;
489ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->block_count = 0;
490ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->after = after != FALSE;
491ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->closure = NULL;
492ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
493ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return handler;
494ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
495ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
496ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
497ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_ref (Handler *handler)
498ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
499ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (handler->ref_count > 0);
500ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
501ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#ifndef G_DISABLE_CHECKS
502ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
503ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
504ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif
505ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
506ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->ref_count += 1;
507ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
508ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
509ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
510ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_unref_R (guint    signal_id,
511ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		 gpointer instance,
512ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		 Handler *handler)
513ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
514ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (handler->ref_count > 0);
515ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
516ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->ref_count -= 1;
517ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!handler->ref_count)
518ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
519ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (handler->next)
520ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        handler->next->prev = handler->prev;
52183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      if (handler->prev)	/* watch out for g_signal_handlers_destroy()! */
522ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        handler->prev->next = handler->next;
523ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
524ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
525ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          HandlerList *hlist = handler_list_lookup (signal_id, instance);
526ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
527ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          hlist->handlers = handler->next;
528ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
529ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
530ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_closure_unref (handler->closure);
531ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_LOCK (g_signal_mutex);
532ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_generic_node_free (&g_handler_ts, handler);
533ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
534ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
535ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
536ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic void
537ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_insert (guint    signal_id,
538ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		gpointer instance,
539ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		Handler  *handler)
540ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
541ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList *hlist;
542ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
543e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
544ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
545ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  hlist = handler_list_ensure (signal_id, instance);
546ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!hlist->handlers)
547ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    hlist->handlers = handler;
548ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else if (hlist->handlers->after && !handler->after)
549ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
550ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->next = hlist->handlers;
551ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlist->handlers->prev = handler;
552ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlist->handlers = handler;
553ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
554ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
555ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
556ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      Handler *tmp = hlist->handlers;
557ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
558ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (handler->after)
559ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        while (tmp->next)
560ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          tmp = tmp->next;
561ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
562ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        while (tmp->next && !tmp->next->after)
563ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          tmp = tmp->next;
564ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (tmp->next)
565ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        tmp->next->prev = handler;
566ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->next = tmp->next;
567ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->prev = tmp;
568ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      tmp->next = handler;
569ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
570ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
571ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
572ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
573ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikemission_push (Emission     **emission_list_p,
574ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       guint          signal_id,
575830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	       GQuark	      detail,
576ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       gpointer       instance,
577ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       EmissionState *state_p)
578ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
579ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Emission *emission = g_generic_node_alloc (&g_emission_ts,
580ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                             sizeof (Emission),
581ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                             EMISSION_PRE_ALLOC);
582ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  emission->next = *emission_list_p;
583ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  emission->signal_id = signal_id;
584830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  emission->detail = detail;
585ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  emission->instance = instance;
586ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  emission->state_p = state_p;
587ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  *emission_list_p = emission;
588ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
589ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
590ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
591830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janikemission_pop (Emission     **emission_list_p,
592830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      EmissionState *state_p)
593ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
594830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  Emission **loc = emission_list_p, *emission = *loc;
59583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
596830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  while (emission->state_p != state_p)
597830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
598830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      loc = &emission->next;
599830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      emission = *loc;
600830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    }
601830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  *loc = emission->next;
602ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_generic_node_free (&g_emission_ts, emission);
603ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
604ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
605ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline Emission*
606ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikemission_find (Emission *emission_list,
607ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       guint     signal_id,
608830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	       GQuark    detail,
609ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       gpointer  instance)
610ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
611ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Emission *emission;
612ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
613ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  for (emission = emission_list; emission; emission = emission->next)
614830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    if (emission->instance == instance &&
615830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	emission->signal_id == signal_id &&
616830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	emission->detail == detail)
617ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      return emission;
618ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return NULL;
619ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
620ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
621ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic gint
622ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_key_cmp (gconstpointer node1,
623ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                gconstpointer node2)
624ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
625ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  const SignalKey *key1 = node1, *key2 = node2;
626ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
627ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (key1->itype == key2->itype)
628ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
629ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
630ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
631ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
632ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
633ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
634ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_init (void) /* sync with gtype.c */
635ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
636ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
637ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!g_n_signal_nodes)
638ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
63983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      /* handler_id_node_prepend() requires this */
64083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      g_assert (sizeof (GList) == sizeof (HandlerMatch));
64183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
642ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      /* setup signal key array */
643ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_key_bsa.cmp_func = signal_key_cmp;
644ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
645782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik      g_signal_key_bsa.flags = G_BSEARCH_ALIGN_POWER2; /* alloc-only */
646ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
647ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
648ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
649ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
650ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      /* invalid (0) signal_id */
651ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_n_signal_nodes = 1;
652ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
653ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes[0] = NULL;
654ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
655ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
656ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
657ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
658ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
6593cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik_g_signals_destroy (GType itype)
660ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
661ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint i;
662ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
663ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
66483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  for (i = 1; i < g_n_signal_nodes; i++)
665ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
666ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      SignalNode *node = g_signal_nodes[i];
667ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
668ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (node->itype == itype)
669ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
670ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          if (node->destroyed)
671ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
672ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                       node->name,
673ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                       g_type_name (node->itype));
674ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          else
675cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik	    signal_destroy_R (node);
676ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
677ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
678ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
679ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
680ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
681ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
682ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_stop_emission (gpointer instance,
683830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik                        guint    signal_id,
684830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			GQuark   detail)
685ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
686ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
687ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
688ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
689ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (signal_id > 0);
690ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
691ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
692ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
693830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
694830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
695830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
696830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      G_UNLOCK (g_signal_mutex);
697830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      return;
698830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    }
699e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
700ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
701ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
702830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      Emission *emission = emission_find (emission_list, signal_id, detail, instance);
703ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
704ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission)
705ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
706ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          if (*emission->state_p == EMISSION_HOOK)
707ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
708ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                       node->name, instance);
709ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          else if (*emission->state_p == EMISSION_RUN)
710ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            *emission->state_p = EMISSION_STOP;
711ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
712ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
713ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
714ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                   node->name, instance);
715ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
716ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
717ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
718ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
719ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
720ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
7213cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikstatic inline guint
7223cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janiksignal_parse_name (const gchar *name,
7233cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		   GType        itype,
7243cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		   GQuark      *detail_p,
7253cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		   gboolean     force_quark)
7263cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik{
7273cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  const gchar *colon = strchr (name, ':');
7283cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  guint signal_id;
7293cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
7303cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  if (!colon)
7313cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    {
7323cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      signal_id = signal_id_lookup (g_quark_try_string (name), itype);
7333cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (signal_id && detail_p)
7343cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	*detail_p = 0;
7353cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    }
7363cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  else if (colon[1] == ':')
7373cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    {
7383cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      gchar buffer[32];
7393cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      guint l = colon - name;
7403cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
7413cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (l < 32)
7423cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	{
7433cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  memcpy (buffer, name, l);
7443cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  buffer[l] = 0;
7453cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  signal_id = signal_id_lookup (g_quark_try_string (buffer), itype);
7463cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	}
7473cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      else
7483cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	{
7493cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  gchar *signal = g_new (gchar, l + 1);
7503cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
7513cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  memcpy (signal, name, l);
7523cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  signal[l] = 0;
7533cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  signal_id = signal_id_lookup (g_quark_try_string (signal), itype);
7543cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  g_free (signal);
7553cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	}
7563cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
7573cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (signal_id && detail_p)
7583cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	*detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0;
7593cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    }
7603cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  else
7613cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    signal_id = 0;
7623cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  return signal_id;
7633cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik}
7643cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
7653cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikgboolean
7663cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikg_signal_parse_name (const gchar *detailed_signal,
7673cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     GType        itype,
7683cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     guint       *signal_id_p,
7693cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     GQuark      *detail_p,
7703cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     gboolean	  force_detail_quark)
7713cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik{
7723cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  GQuark detail = 0;
7733cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  guint signal_id;
77483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
7753cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  g_return_val_if_fail (detailed_signal != NULL, FALSE);
7763cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
77783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
7783cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  G_LOCK (g_signal_mutex);
7793cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
7803cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  G_UNLOCK (g_signal_mutex);
78183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
7823cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  if (signal_id)
7833cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    {
7843cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (signal_id_p)
7853cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	*signal_id_p = signal_id;
7863cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (detail_p)
7873cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	*detail_p = detail;
78883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
7893cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      return TRUE;
7903cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    }
7913cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  else
7923cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    return FALSE;
7933cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik}
7943cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
795ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint
796ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_lookup (const gchar *name,
797ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 GType        itype)
798ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
7998a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  guint signal_id;
8008a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik
801ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (name != NULL, 0);
802ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
803ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
804ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
8058a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
806ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
807ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
8088a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  return signal_id;
809ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
810ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
811ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikgchar*
812ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_name (guint signal_id)
813ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
814ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
815ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gchar *name;
81683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
817ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
818ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
819ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  name = node ? node->name : NULL;
820ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
821ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
822ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return name;
823ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
824ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
825ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
826ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_query (guint         signal_id,
827ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		GSignalQuery *query)
828ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
829ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
83083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
831ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (query != NULL);
83283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
833ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
834ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
835ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!node || node->destroyed)
836ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    query->signal_id = 0;
837ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
838ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
839ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->signal_id = node->signal_id;
840ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->signal_name = node->name;
841ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->itype = node->itype;
842ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->signal_flags = node->flags;
843ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->return_type = node->return_type;
844ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->n_params = node->n_params;
845ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->param_types = node->param_types;
846ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
847ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
848ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
849ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
85065c423b458d9fd1338cab0de7951092c09ab1686Tim Janikguint*
85165c423b458d9fd1338cab0de7951092c09ab1686Tim Janikg_signal_list_ids (GType  itype,
85265c423b458d9fd1338cab0de7951092c09ab1686Tim Janik		   guint *n_ids)
853300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor{
854300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  SignalKey *keys;
855300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  GArray *result;
85665c423b458d9fd1338cab0de7951092c09ab1686Tim Janik  guint n_nodes;
85765c423b458d9fd1338cab0de7951092c09ab1686Tim Janik  guint i;
85883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
859300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
86065c423b458d9fd1338cab0de7951092c09ab1686Tim Janik  g_return_val_if_fail (n_ids != NULL, NULL);
86183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
86265c423b458d9fd1338cab0de7951092c09ab1686Tim Janik  G_LOCK (g_signal_mutex);
86383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
864300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  keys = g_signal_key_bsa.nodes;
865300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  n_nodes  = g_signal_key_bsa.n_nodes;
866300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  result = g_array_new (FALSE, FALSE, sizeof (guint));
867300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor
868300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  for (i = 0; i < n_nodes; i++)
86965c423b458d9fd1338cab0de7951092c09ab1686Tim Janik    if (keys[i].itype == itype)
87065c423b458d9fd1338cab0de7951092c09ab1686Tim Janik      {
87165c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	gchar *name = g_quark_to_string (keys[i].quark);
87283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
87365c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	/* Signal names with "_" in them are aliases to the same
87465c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	 * name with "-" instead of "_".
87565c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	 */
87665c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	if (!strchr (name, '_'))
87765c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	  g_array_append_val (result, keys[i].signal_id);
87865c423b458d9fd1338cab0de7951092c09ab1686Tim Janik      }
87983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
880300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  *n_ids = result->len;
88183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
88265c423b458d9fd1338cab0de7951092c09ab1686Tim Janik  G_UNLOCK (g_signal_mutex);
88365c423b458d9fd1338cab0de7951092c09ab1686Tim Janik
884300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  return (guint *) g_array_free (result, FALSE);
885300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor}
886300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor
887ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint
888b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Penningtong_signal_new_valist (const gchar       *signal_name,
889b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GType              itype,
890b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GSignalFlags       signal_flags,
891b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GClosure          *class_closure,
892b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GSignalAccumulator accumulator,
893b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GSignalCMarshaller c_marshaller,
894b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GType              return_type,
895b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     guint              n_params,
896b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     va_list            args)
897e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
898e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GType *param_types;
899e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint i;
900e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint signal_id;
901e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
902e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (n_params > 0)
903e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
904e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      param_types = g_new (GType, n_params);
905e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
906e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      for (i = 0; i < n_params; i++)
907e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	param_types[i] = va_arg (args, GType);
908e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
909e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
910e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    param_types = NULL;
911e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
912e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  signal_id = g_signal_newv (signal_name, itype, signal_flags,
913e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			     class_closure, accumulator, c_marshaller,
914e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			     return_type, n_params, param_types);
915e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_free (param_types);
916e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
917e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  return signal_id;
918e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
919e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
920e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikguint
921b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Penningtong_signal_newc (const gchar	 *signal_name,
922b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               GType		  itype,
923b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               GSignalFlags	  signal_flags,
924b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               guint              class_offset,
925b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               GSignalAccumulator accumulator,
926b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               GSignalCMarshaller c_marshaller,
927b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               GType		  return_type,
928b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               guint		  n_params,
929b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               ...)
930b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington{
931b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  va_list args;
932b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  guint signal_id;
933b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
934b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  g_return_val_if_fail (signal_name != NULL, 0);
935b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
936b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  va_start (args, n_params);
937b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
938b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
939b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                                   g_signal_type_cclosure_new (itype,
940b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                                                               class_offset),
941b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                                   accumulator, c_marshaller,
942b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                                   return_type, n_params, args);
943b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
944b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  va_end (args);
945b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
946b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  return signal_id;
947b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington}
948b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
949b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Penningtonguint
950ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_newv (const gchar       *signal_name,
951ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GType              itype,
952830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik               GSignalFlags       signal_flags,
953ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GClosure          *class_closure,
954ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GSignalAccumulator accumulator,
955ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GSignalCMarshaller c_marshaller,
956ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GType		  return_type,
957ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               guint              n_params,
958ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GType		 *param_types)
959ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
960ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gchar *name;
961ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint signal_id, i;
962ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
963ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
964ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (signal_name != NULL, 0);
965ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
966ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (n_params)
967ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_return_val_if_fail (param_types != NULL, 0);
968ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (return_type != G_TYPE_NONE)
969ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_return_val_if_fail (accumulator == NULL, 0);
970ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
971ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  name = g_strdup (signal_name);
972ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_strdelimit (name, G_STR_DELIMITERS ":^", '_');  // FIXME do character checks like for types
973ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
974ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
975ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
9768a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
977ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
978ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node && !node->destroyed)
979ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
980ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
981ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 name,
982ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 g_type_name (node->itype),
983ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
984ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (name);
985ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
986ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      return 0;
987ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
988ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node && node->itype != itype)
989ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
990ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
991ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 name,
992ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 g_type_name (itype),
993ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 g_type_name (node->itype));
994ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (name);
995ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
996ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      return 0;
997ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
998ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  for (i = 0; i < n_params; i++)
999ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    if (!G_TYPE_IS_VALUE (param_types[i]) ||
1000ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */
1001ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      {
1002ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
1003ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		   i + 1, g_type_name (param_types[i]), g_type_name (itype), name);
1004ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_free (name);
1005ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	G_UNLOCK (g_signal_mutex);
1006ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	return 0;
1007ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      }
1008ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type))
1009ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1010ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
1011ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		 g_type_name (param_types[i]), g_type_name (itype), name);
1012ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (name);
1013ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
1014ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      return 0;
1015ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1016ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1017ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* setup permanent portion of signal node */
1018ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!node)
1019ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1020ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      SignalKey key;
1021ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1022ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      signal_id = g_n_signal_nodes++;
1023ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node = g_new (SignalNode, 1);
1024ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node->signal_id = signal_id;
1025ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
1026ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes[signal_id] = node;
1027ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node->itype = itype;
1028ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node->name = name;
1029ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.itype = itype;
1030ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.quark = g_quark_from_string (node->name);
1031ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.signal_id = signal_id;
1032ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
1033ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_strdelimit (node->name, "_", '-');
1034ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.quark = g_quark_from_static_string (node->name);
1035ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
1036ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1037ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->destroyed = FALSE;
1038ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1039ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* setup reinitializable portion */
1040830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
1041ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->n_params = n_params;
1042ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
1043ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->return_type = return_type;
1044ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL;
1045ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->accumulator = accumulator;
1046ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->c_marshaller = c_marshaller;
1047ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->emission_hooks = NULL;
1048ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure))
1049ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_closure_set_marshal (class_closure, node->c_marshaller);
1050ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1051ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1052ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return signal_id;
1053ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1054ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1055ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic void
1056ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_destroy_R (SignalNode *signal_node)
1057ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1058ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode node = *signal_node;
1059ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1060ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->destroyed = TRUE;
1061ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1062ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* reentrancy caution, zero out real contents first */
1063ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->n_params = 0;
1064ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->param_types = NULL;
1065ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->return_type = 0;
1066ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->class_closure = NULL;
1067ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->accumulator = NULL;
1068ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->c_marshaller = NULL;
1069ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->emission_hooks = NULL;
1070ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1071782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifdef	G_ENABLE_DEBUG
1072ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* check current emissions */
1073ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  {
1074ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    Emission *emission;
1075ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1076ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
1077ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik         emission; emission = emission->next)
1078ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission->signal_id == node.signal_id)
1079ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
1080ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                    node.name, emission->instance);
1081ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  }
1082ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif
1083ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1084ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* free contents that need to
1085ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik   */
1086ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1087ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_free (node.param_types);
1088ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_closure_unref (node.class_closure);
1089ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node.emission_hooks)
1090ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1091ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_hook_list_clear (node.emission_hooks);
1092ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (node.emission_hooks);
1093ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1094ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1095ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1096ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1097ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint
10983cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikg_signal_connect_closure_by_id (gpointer  instance,
10993cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				guint     signal_id,
11003cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				GQuark    detail,
11013cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				GClosure *closure,
11023cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				gboolean  after)
1103ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1104ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
1105ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint handler_id = 0;
1106ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1107ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1108ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (signal_id > 0, 0);
1109ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (closure != NULL, 0);
1110ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1111ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1112ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
1113e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (node)
1114830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
1115e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1116e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1117e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1118e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1119e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
1120e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1121e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  Handler *handler = handler_new (after);
1122e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1123e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_id = handler->id;
1124e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->detail = detail;
1125e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->closure = g_closure_ref (closure);
1126e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_insert (signal_id, instance, handler);
1127e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
1128e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_closure_set_marshal (closure, node->c_marshaller);
1129e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1130ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1131ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
1132ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1133ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1134ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1135ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return handler_id;
1136ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1137ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1138e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikguint
1139e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_connect_closure (gpointer     instance,
1140e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			  const gchar *detailed_signal,
1141e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			  GClosure    *closure,
1142e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			  gboolean     after)
1143e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1144e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint signal_id, handler_id = 0;
1145e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GQuark detail = 0;
1146e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GType itype;
1147e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1148e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1149e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (detailed_signal != NULL, 0);
1150e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (closure != NULL, 0);
1151e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1152e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_LOCK (g_signal_mutex);
1153e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  itype = G_TYPE_FROM_INSTANCE (instance);
1154e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1155e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (signal_id)
1156e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1157e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1158e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1159e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1160e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1161e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else if (!g_type_is_a (itype, node->itype))
1162e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1163e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
1164e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1165e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  Handler *handler = handler_new (after);
1166e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1167e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_id = handler->id;
1168e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->detail = detail;
1169e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->closure = g_closure_ref (closure);
1170e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_insert (signal_id, instance, handler);
1171e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1172e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_closure_set_marshal (handler->closure, node->c_marshaller);
1173e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1174e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1175e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1176e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1177e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_UNLOCK (g_signal_mutex);
1178e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1179e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  return handler_id;
1180e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1181e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1182e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikguint
1183e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_connect_data (gpointer       instance,
1184e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       const gchar   *detailed_signal,
1185e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       GCallback      c_handler,
1186e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       gpointer       data,
1187e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       GClosureNotify destroy_data,
1188e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       gboolean       swapped,
1189e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       gboolean       after)
1190e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1191e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint signal_id, handler_id = 0;
1192e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GQuark detail = 0;
1193e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GType itype;
1194e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1195e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1196e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (detailed_signal != NULL, 0);
1197e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (c_handler != NULL, 0);
1198e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1199e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_LOCK (g_signal_mutex);
1200e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  itype = G_TYPE_FROM_INSTANCE (instance);
1201e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1202e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (signal_id)
1203e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1204e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1205e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1206e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1207e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1208e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else if (!g_type_is_a (itype, node->itype))
1209e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1210e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
1211e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1212e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  Handler *handler = handler_new (after);
1213e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1214e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_id = handler->id;
1215e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->detail = detail;
1216e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
1217e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_insert (signal_id, instance, handler);
1218e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1219e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_closure_set_marshal (handler->closure, node->c_marshaller);
1220e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1221e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1222e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1223e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1224e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_UNLOCK (g_signal_mutex);
1225e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1226e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  return handler_id;
1227e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1228e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1229ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
1230cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_block (gpointer instance,
1231cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                        guint    handler_id)
1232cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1233cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  Handler *handler;
1234cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1235cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1236cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (handler_id > 0);
1237cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1238cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  G_LOCK (g_signal_mutex);
1239cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  handler = handler_lookup (instance, handler_id, NULL);
1240cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (handler)
1241cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1242cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik#ifndef G_DISABLE_CHECKS
1243cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
1244cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik        g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
1245cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik#endif
1246cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1247cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      handler->block_count += 1;
1248cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
1249cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  else
1250cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1251cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  G_UNLOCK (g_signal_mutex);
1252cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1253cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1254cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikvoid
1255cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_unblock (gpointer instance,
1256cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                          guint    handler_id)
1257cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1258cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  Handler *handler;
1259cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1260cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1261cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (handler_id > 0);
1262cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1263cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  G_LOCK (g_signal_mutex);
1264cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  handler = handler_lookup (instance, handler_id, NULL);
1265cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (handler)
1266cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1267cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      if (handler->block_count)
1268cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik        handler->block_count -= 1;
1269cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      else
1270cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik        g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance);
1271cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
1272cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  else
1273cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1274cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  G_UNLOCK (g_signal_mutex);
1275cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1276cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1277cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikvoid
1278ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_handler_disconnect (gpointer instance,
1279ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                             guint    handler_id)
1280ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1281ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler *handler;
1282ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint signal_id;
1283ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1284ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1285ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (handler_id > 0);
1286ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1287ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1288ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler = handler_lookup (instance, handler_id, &signal_id);
1289ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (handler)
1290ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1291ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->id = 0;
1292ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->block_count = 1;
1293ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler_unref_R (signal_id, instance, handler);
1294ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1295ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
1296ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1297ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1298ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1299ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1300ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
130183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikg_signal_handlers_destroy (gpointer instance)
1302ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1303ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa;
1304ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1305ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1306ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1307ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1308ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
1309ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (hlbsa)
1310ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1311ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      guint i;
1312ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1313ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      /* reentrancy caution, delete instance trace first */
1314ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_hash_table_remove (g_handler_list_bsa_ht, instance);
131583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1316ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      for (i = 0; i < hlbsa->n_nodes; i++)
1317ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
1318ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
1319ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          Handler *handler = hlist->handlers;
1320ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1321ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          while (handler)
1322ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            {
1323ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              Handler *tmp = handler;
1324ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1325ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              handler = tmp->next;
1326ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              tmp->block_count = 1;
1327ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              /* cruel unlink, this works because _all_ handlers vanish */
1328ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              tmp->next = NULL;
1329ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              tmp->prev = tmp;
1330ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              if (tmp->id)
1331ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		{
1332ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  tmp->id = 0;
1333ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  handler_unref_R (0, NULL, tmp);
1334ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		}
1335ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            }
1336ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
1337ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (hlbsa->nodes);
1338ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_generic_node_free (&g_bsa_ts, hlbsa);
1339ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1340ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1341ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1342ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1343cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint
1344cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_find (gpointer         instance,
1345cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       GSignalMatchType mask,
1346cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       guint            signal_id,
1347cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik		       GQuark		detail,
1348cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       GClosure        *closure,
1349cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       gpointer         func,
1350cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       gpointer         data)
1351ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1352cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint handler_id = 0;
1353ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1354cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1355cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
135683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1357cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & G_SIGNAL_MATCH_MASK)
1358ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
135983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      HandlerMatch *mlist;
136083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1361cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_LOCK (g_signal_mutex);
136283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
136383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      if (mlist)
136483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	{
136583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	  handler_id = mlist->handler->id;
136683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	  handler_match_free1_R (mlist, instance);
136783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	}
1368cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
1369ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
137083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1371cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return handler_id;
1372ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1373ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1374cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikstatic guint
137583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiksignal_handlers_foreach_matched_R (gpointer         instance,
137683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   GSignalMatchType mask,
137783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   guint            signal_id,
137883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   GQuark           detail,
137983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   GClosure        *closure,
138083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   gpointer         func,
138183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   gpointer         data,
138283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   void		  (*callback) (gpointer instance,
138383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							       guint    handler_id))
1384ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
138583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *mlist;
1386cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
138783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
138883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
138983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  while (mlist)
1390ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1391cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      n_handlers++;
1392cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
139383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      callback (instance, mlist->handler->id);
1394cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_LOCK (g_signal_mutex);
139583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      mlist = handler_match_free1_R (mlist, instance);
1396ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
139783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1398cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1399ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1400ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1401ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint
1402cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_block_matched (gpointer         instance,
1403cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 GSignalMatchType mask,
1404cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 guint            signal_id,
1405cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 GQuark           detail,
1406cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 GClosure        *closure,
1407cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 gpointer         func,
1408cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 gpointer         data)
1409ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1410cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
141183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1412cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1413cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
141483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1415cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1416cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1417cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_LOCK (g_signal_mutex);
141883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
141983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      closure, func, data,
142083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      g_signal_handler_block);
1421cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
1422cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
142383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1424cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1425cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1426cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1427cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint
1428cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_unblock_matched (gpointer         instance,
1429cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   GSignalMatchType mask,
1430cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   guint            signal_id,
1431cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   GQuark           detail,
1432cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   GClosure        *closure,
1433cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   gpointer         func,
1434cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   gpointer         data)
1435cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1436cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
1437ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1438cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1439cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1440ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1441cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1442cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1443cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_LOCK (g_signal_mutex);
144483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
144583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      closure, func, data,
144683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      g_signal_handler_unblock);
1447cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
1448cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
144983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1450cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1451cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1452cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1453cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint
1454cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_disconnect_matched (gpointer         instance,
1455cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      GSignalMatchType mask,
1456cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      guint            signal_id,
1457cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      GQuark           detail,
1458cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      GClosure        *closure,
1459cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      gpointer         func,
1460cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      gpointer         data)
1461cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1462cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
146383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1464cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1465cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
146683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1467cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1468cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1469cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_LOCK (g_signal_mutex);
147083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
147183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      closure, func, data,
147283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      g_signal_handler_disconnect);
1473cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
1474cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
147583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1476cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1477ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1478ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1479ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikgboolean
1480cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_has_handler_pending (gpointer instance,
1481cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik			      guint    signal_id,
1482cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik			      GQuark   detail,
1483cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik			      gboolean may_be_blocked)
1484ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
148583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *mlist;
148683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  gboolean has_pending;
1487ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1488ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1489ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (signal_id > 0, FALSE);
1490ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1491ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1492830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (detail)
1493830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
1494830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1495830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1496830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      if (!(node->flags & G_SIGNAL_DETAILED))
1497830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	{
1498830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1499830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  G_UNLOCK (g_signal_mutex);
1500830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  return FALSE;
1501830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	}
1502830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    }
150383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  mlist = handlers_find (instance,
150483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik			 (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
150583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik			 signal_id, detail, NULL, NULL, NULL, TRUE);
150683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  if (mlist)
150783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    {
150883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      has_pending = TRUE;
150983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      handler_match_free1_R (mlist, instance);
151083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    }
151183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  else
151283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    has_pending = FALSE;
1513ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1514ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
151583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return has_pending;
1516ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1517ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1518ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
1519ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_emitv (const GValue *instance_and_params,
1520ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		guint         signal_id,
1521830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		GQuark	      detail,
1522ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		GValue       *return_value)
1523ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1524ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  const GValue *param_values;
1525e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  gpointer instance;
1526e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  SignalNode *node;
1527ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint i;
1528ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1529ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (instance_and_params != NULL);
1530ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  instance = g_value_get_as_pointer (instance_and_params);
1531ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1532ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (signal_id > 0);
1533e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1534ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  param_values = instance_and_params + 1;
1535ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1536ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1537ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
1538e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1539cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1540cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1541cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
1542cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      return;
1543cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
1544782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifdef G_ENABLE_DEBUG
1545830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (detail && !(node->flags & G_SIGNAL_DETAILED))
1546830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
1547830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1548830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      G_UNLOCK (g_signal_mutex);
1549830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      return;
1550830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    }
1551ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  for (i = 0; i < node->n_params; i++)
1552ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
1553ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      {
1554e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'",
1555e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		    G_STRLOC,
1556ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    g_type_name (node->param_types[i]),
1557ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    i,
1558ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    node->name,
1559ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    G_VALUE_TYPE_NAME (param_values + i));
1560ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	G_UNLOCK (g_signal_mutex);
1561ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	return;
1562ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      }
1563ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node->return_type != G_TYPE_NONE)
1564ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1565ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (!return_value)
1566ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1567e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)",
1568e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      G_STRLOC,
1569ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      g_type_name (node->return_type),
1570ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      node->name);
1571ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  G_UNLOCK (g_signal_mutex);
1572ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  return;
1573ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1574ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
1575ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1576e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'",
1577e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      G_STRLOC,
1578ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      g_type_name (node->return_type),
1579ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      node->name,
1580ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      G_VALUE_TYPE_NAME (return_value));
1581ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  G_UNLOCK (g_signal_mutex);
1582ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  return;
1583ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1584ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1585ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
1586ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return_value = NULL;
1587782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#endif	/* G_ENABLE_DEBUG */
1588e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1589830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  signal_emit_R (node, detail, instance, return_value, instance_and_params);
1590ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1591ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1592ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1593e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid
1594e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit_valist (gpointer instance,
1595e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      guint    signal_id,
1596e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      GQuark   detail,
1597e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      va_list  var_args)
1598e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1599e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL;
1600e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GValue *param_values;
1601e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  SignalNode *node;
1602e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint i;
1603e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1604e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1605e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (signal_id > 0);
1606e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1607e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_LOCK (g_signal_mutex);
1608e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
1609e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1610e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1611e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1612e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      G_UNLOCK (g_signal_mutex);
1613e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return;
1614e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1615e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#ifndef G_DISABLE_CHECKS
1616e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (detail && !(node->flags & G_SIGNAL_DETAILED))
1617e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1618e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1619e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      G_UNLOCK (g_signal_mutex);
1620e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return;
1621e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1622e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#endif  /* !G_DISABLE_CHECKS */
1623e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1624e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (node->n_params < MAX_STACK_VALUES)
1625e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    instance_and_params = stack_values;
1626e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1627e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1628e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      free_me = g_new (GValue, node->n_params + 1);
1629e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      instance_and_params = free_me;
1630e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1631e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  param_values = instance_and_params + 1;
1632e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  for (i = 0; i < node->n_params; i++)
1633e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1634e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      gchar *error;
1635e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1636e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      param_values[i].g_type = 0;
1637e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_value_init (param_values + i, node->param_types[i]);
1638e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      G_VALUE_COLLECT (param_values + i, var_args, &error);
1639e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (error)
1640e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1641e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_warning ("%s: %s", G_STRLOC, error);
1642e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (error);
1643e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1644e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  /* we purposely leak the value here, it might not be
1645e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	   * in a sane state if an error condition occoured
1646e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	   */
1647e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  while (i--)
1648e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_value_unset (param_values + i);
1649e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1650e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  G_UNLOCK (g_signal_mutex);
1651e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (free_me);
1652e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  return;
1653e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1654e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1655e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  instance_and_params->g_type = 0;
1656e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_value_init (instance_and_params, node->itype);
1657e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_value_set_instance (instance_and_params, instance);
1658e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (node->return_type == G_TYPE_NONE)
1659e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    signal_emit_R (node, detail, instance, NULL, instance_and_params);
1660e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1661e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1662e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      GValue return_value = { 0, };
1663e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      gchar *error = NULL;
1664e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1665e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_value_init (&return_value, node->return_type);
1666e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (signal_emit_R (node, detail, instance, &return_value, instance_and_params))
1667e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	G_VALUE_LCOPY (&return_value, var_args, &error);
1668e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (!error)
1669e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_value_unset (&return_value);
1670e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
1671e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1672e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_warning ("%s: %s", G_STRLOC, error);
1673e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (error);
1674e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1675e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  /* we purposely leak the value here, it might not be
1676e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	   * in a sane state if an error condition occoured
1677e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	   */
1678e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1679e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1680e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  for (i = 0; i < node->n_params; i++)
1681e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_value_unset (param_values + i);
1682e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_value_unset (instance_and_params);
1683e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (free_me)
1684e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_free (free_me);
1685e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_UNLOCK (g_signal_mutex);
1686e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1687e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1688e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid
1689e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit (gpointer instance,
1690e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	       guint    signal_id,
1691e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	       GQuark   detail,
1692e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	       ...)
1693e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1694e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  va_list var_args;
1695e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1696e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  va_start (var_args, detail);
1697e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_signal_emit_valist (instance, signal_id, detail, var_args);
1698e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  va_end (var_args);
1699e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1700e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1701e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid
1702e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit_by_name (gpointer     instance,
1703e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       const gchar *detailed_signal,
1704e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       ...)
1705e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1706e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GQuark detail = 0;
1707e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint signal_id;
1708e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1709e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1710e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (detailed_signal != NULL);
1711e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1712e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_LOCK (g_signal_mutex);
1713e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE);
1714e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_UNLOCK (g_signal_mutex);
1715e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1716e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (signal_id)
1717e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1718e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      va_list var_args;
1719e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1720e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      va_start (var_args, detailed_signal);
1721e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_signal_emit_valist (instance, signal_id, detail, var_args);
1722e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      va_end (var_args);
1723e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1724e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1725e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1726e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1727e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1728e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikstatic gboolean
1729ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_emit_R (SignalNode   *node,
1730830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	       GQuark	     detail,
1731ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       gpointer      instance,
1732ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       GValue	    *return_value,
1733ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       const GValue *instance_and_params)
1734ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1735ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EmissionState emission_state = 0;
1736ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GSignalAccumulator accumulator;
1737830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  GSignalInvocationHint ihint;
1738ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GClosure *class_closure;
1739ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList *hlist;
1740830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  Handler *handler_list = NULL;
1741e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GValue accu = { 0, };
1742ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gboolean accu_used = FALSE;
1743ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint signal_id = node->signal_id;
1744e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  gboolean return_value_altered = FALSE;
1745ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1746ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node->flags & G_SIGNAL_NO_RECURSE)
1747ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1748830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance);
1749ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1750ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission)
1751ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1752ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  *emission->state_p = EMISSION_RESTART;
1753e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  return return_value_altered;
1754ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1755ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1756830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  ihint.signal_id = node->signal_id;
1757830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  ihint.detail = detail;
1758ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  accumulator = node->accumulator;
1759ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (accumulator)
1760e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_value_init (&accu, node->return_type);
1761ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
1762830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		 signal_id, detail, instance, &emission_state);
1763ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  class_closure = node->class_closure;
1764ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1765ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMIT_RESTART:
1766ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1767830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
1768830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    handler_unref_R (signal_id, instance, handler_list);
1769830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  hlist = handler_list_lookup (signal_id, instance);
1770830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  handler_list = hlist ? hlist->handlers : NULL;
1771830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
1772830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    handler_ref (handler_list);
1773830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1774830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  ihint.run_type = G_SIGNAL_RUN_FIRST;
1775830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1776ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
1777ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1778ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_RUN;
1779ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1780ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
1781ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (accumulator)
1782ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1783ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (accu_used)
1784ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    g_value_reset (&accu);
1785ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  g_closure_invoke (class_closure,
1786ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			    &accu,
1787ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			    node->n_params + 1,
1788830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			    instance_and_params,
1789830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			    &ihint);
1790830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  if (!accumulator (&ihint, return_value, &accu) &&
1791ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      emission_state == EMISSION_RUN)
1792ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    emission_state = EMISSION_STOP;
1793ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  accu_used = TRUE;
1794ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1795ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
1796ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_closure_invoke (class_closure,
1797ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			  return_value,
1798ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			  node->n_params + 1,
1799830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			  instance_and_params,
1800830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			  &ihint);
1801ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_LOCK (g_signal_mutex);
1802e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return_value_altered = TRUE;
1803ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1804ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_STOP)
1805ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
1806ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else if (emission_state == EMISSION_RESTART)
1807ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
1808ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1809ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1810ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node->emission_hooks)
1811ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1812ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_HOOK;
1813ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1814ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
1815ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_print ("emission_hooks()\n");
1816ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_LOCK (g_signal_mutex);
1817ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1818ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_RESTART)
1819ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
1820ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1821ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1822830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
1823ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1824830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      Handler *handler = handler_list;
1825ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1826ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_RUN;
1827ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler_ref (handler);
1828ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      do
1829ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1830ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  Handler *tmp;
1831ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1832830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  if (handler->after)
1833830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    {
1834830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      handler_unref_R (signal_id, instance, handler_list);
1835830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      handler_list = handler;
1836830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      break;
1837830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    }
1838830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  else if (!handler->block_count && (!handler->detail || handler->detail == detail))
1839ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    {
1840ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      G_UNLOCK (g_signal_mutex);
1841ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      if (accumulator)
1842ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		{
1843ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  if (accu_used)
1844ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    g_value_reset (&accu);
1845ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  g_closure_invoke (handler->closure,
1846ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				    &accu,
1847ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				    node->n_params + 1,
1848830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				    instance_and_params,
1849830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				    &ihint);
1850830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		  if (!accumulator (&ihint, return_value, &accu) &&
1851ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      emission_state == EMISSION_RUN)
1852ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    emission_state = EMISSION_STOP;
1853ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  accu_used = TRUE;
1854ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		}
1855ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      else
1856ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		g_closure_invoke (handler->closure,
1857ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				  return_value,
1858ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				  node->n_params + 1,
1859830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				  instance_and_params,
1860830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				  &ihint);
1861ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      G_LOCK (g_signal_mutex);
1862e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	      return_value_altered = TRUE;
1863ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1864ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1865ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    }
1866ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  else
1867ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    tmp = handler->next;
1868ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1869ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (tmp)
1870ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    handler_ref (tmp);
1871830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  handler_unref_R (signal_id, instance, handler_list);
1872830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  handler_list = handler;
1873ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  handler = tmp;
1874ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1875ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      while (handler);
1876ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1877ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_STOP)
1878ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
1879ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else if (emission_state == EMISSION_RESTART)
1880ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
1881ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1882ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1883830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  ihint.run_type = G_SIGNAL_RUN_LAST;
1884830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1885ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
1886ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1887ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_RUN;
1888ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1889ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
1890ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (accumulator)
1891ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1892ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (accu_used)
1893ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    g_value_reset (&accu);
1894ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  g_closure_invoke (class_closure,
1895ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			    &accu,
1896ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			    node->n_params + 1,
1897830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			    instance_and_params,
1898830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			    &ihint);
1899830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik          if (!accumulator (&ihint, return_value, &accu) &&
1900ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      emission_state == EMISSION_RUN)
1901ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    emission_state = EMISSION_STOP;
1902ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  accu_used = TRUE;
1903ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1904ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
1905ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_closure_invoke (class_closure,
1906ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			  return_value,
1907ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			  node->n_params + 1,
1908830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			  instance_and_params,
1909830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			  &ihint);
1910ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_LOCK (g_signal_mutex);
1911e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return_value_altered = TRUE;
1912ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1913ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_STOP)
1914ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
1915ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else if (emission_state == EMISSION_RESTART)
1916ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
1917ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1918ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1919830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
1920ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1921830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      Handler *handler = handler_list;
1922ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1923ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_RUN;
1924ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler_ref (handler);
1925ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      do
1926ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1927ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  Handler *tmp;
1928ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1929830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail))
1930ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    {
1931ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      G_UNLOCK (g_signal_mutex);
1932ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              if (accumulator)
1933ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		{
1934ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  if (accu_used)
1935ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    g_value_reset (&accu);
1936ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  g_closure_invoke (handler->closure,
1937ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				    &accu,
1938ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				    node->n_params + 1,
1939830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				    instance_and_params,
1940830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				    &ihint);
1941830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		  if (!accumulator (&ihint, return_value, &accu) &&
1942ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      emission_state == EMISSION_RUN)
1943ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    emission_state = EMISSION_STOP;
1944ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  accu_used = TRUE;
1945ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		}
1946ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      else
1947ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		g_closure_invoke (handler->closure,
1948ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				  return_value,
1949ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				  node->n_params + 1,
1950830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				  instance_and_params,
1951830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				  &ihint);
1952ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      G_LOCK (g_signal_mutex);
1953e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	      return_value_altered = TRUE;
1954ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1955ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1956ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    }
1957ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  else
1958ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    tmp = handler->next;
1959ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1960ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (tmp)
1961ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    handler_ref (tmp);
1962ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  handler_unref_R (signal_id, instance, handler);
1963ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  handler = tmp;
1964ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1965ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      while (handler);
1966ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1967ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_STOP)
1968ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
1969ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else if (emission_state == EMISSION_RESTART)
1970ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
1971ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1972ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1973ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMIT_CLEANUP:
1974ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1975830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  ihint.run_type = G_SIGNAL_RUN_CLEANUP;
1976830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1977ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
1978ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1979830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      gboolean need_unset = FALSE;
1980830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1981ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_STOP;
1982ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1983ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
1984ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (node->return_type != G_TYPE_NONE)
1985ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1986ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (!accumulator)
1987830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    {
1988830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      g_value_init (&accu, node->return_type);
1989830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      need_unset = TRUE;
1990830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    }
1991ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  else if (accu_used)
1992ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    g_value_reset (&accu);
1993ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1994ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_closure_invoke (class_closure,
1995ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			node->return_type != G_TYPE_NONE ? &accu : NULL,
1996ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			node->n_params + 1,
1997830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			instance_and_params,
1998830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			&ihint);
1999830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      if (need_unset)
2000ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_value_unset (&accu);
2001ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_LOCK (g_signal_mutex);
2002830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
2003ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_RESTART)
2004ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
2005ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
2006ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2007830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
2008830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    handler_unref_R (signal_id, instance, handler_list);
2009ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2010830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
2011ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (accumulator)
2012e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_value_unset (&accu);
2013e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2014e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  return return_value_altered;
2015ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
2016e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2017e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2018f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik/* --- compile standard marshallers --- */
2019e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#include	"gvaluetypes.h"
2020e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#include        "gmarshal.c"
2021