gsignal.c revision 782a8e2e7c69c3d98bd69bcfdbb65ded520576f4
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 */
22fbe5df779cd39c9587f665118074ac828a805c26Owen Taylor#include <string.h>
23fbe5df779cd39c9587f665118074ac828a805c26Owen Taylor
24ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#include        "gsignal.h"
25ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#include        "gbsearcharray.h"
26e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#include        "gvaluecollector.h"
27ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
28ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
29ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* pre allocation configurations
30ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */
31e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#define	MAX_STACK_VALUES	(16)
32ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define BSA_PRE_ALLOC           (20)
33ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_PRE_ALLOC       (48)
34ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define EMISSION_PRE_ALLOC      (16)
35ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
36ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define REPORT_BUG      "please report occourance circumstances to gtk-devel-list@gnome.org"
37ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
38ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
39ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- generic allocation --- */
40782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik/* we special case allocations generically by replacing
41ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * these functions with more speed/memory aware variants
42ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */
43782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifndef	DISABLE_MEM_POOLS
44ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline gpointer
45ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_generic_node_alloc (GTrashStack **trash_stack_p,
46ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                      guint         sizeof_node,
47ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                      guint         nodes_pre_alloc)
48ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
49ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gpointer node = g_trash_stack_pop (trash_stack_p);
50ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
51ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!node)
52ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
53ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      guint8 *block;
54ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
55ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      nodes_pre_alloc = MAX (nodes_pre_alloc, 1);
56ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      block = g_malloc (sizeof_node * nodes_pre_alloc);
57ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      while (--nodes_pre_alloc)
58ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
59ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          g_trash_stack_push (trash_stack_p, block);
60ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          block += sizeof_node;
61ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
62ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node = block;
63ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
64ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
65ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return node;
66ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
67ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
68ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_generic_node_free (GTrashStack **trash_stack_p,
69ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                     gpointer      node)
70ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
71ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_trash_stack_push (trash_stack_p, node);
72ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
73782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#else	/* !DISABLE_MEM_POOLS */
74782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janikstatic inline gpointer
75782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janikg_generic_node_alloc (GTrashStack **trash_stack_p,
76782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik                      guint         sizeof_node,
77782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik                      guint         nodes_pre_alloc)
78782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik{
79782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik  return g_malloc (sizeof_node);
80782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik}
81782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janikstatic inline void
82782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janikg_generic_node_free (GTrashStack **trash_stack_p,
83782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik                     gpointer      node)
84782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik{
85782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik  g_free (node);
86782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik}
87782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#endif	/* !DISABLE_MEM_POOLS */
88ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
89ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
90ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- typedefs --- */
9183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _SignalNode   SignalNode;
9283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _SignalKey    SignalKey;
9383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _Emission     Emission;
9483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _Handler      Handler;
9583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _HandlerList  HandlerList;
9683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _HandlerMatch HandlerMatch;
97ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiktypedef enum
98ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
99ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_STOP,
100ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_RUN,
101ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_HOOK,
102ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EMISSION_RESTART
103ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} EmissionState;
104ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
105ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
106ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- prototypes --- */
10783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline guint		signal_id_lookup	(GQuark		  quark,
10883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GType		  itype);
10983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      void		signal_destroy_R	(SignalNode	 *signal_node);
11083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerList*	handler_list_ensure	(guint		  signal_id,
11183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
11283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerList*	handler_list_lookup	(guint		  signal_id,
11383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
11483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline Handler*		handler_new		(gboolean	  after);
11583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      void		handler_insert		(guint		  signal_id,
11683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance,
11783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 Handler	 *handler);
11883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      Handler*		handler_lookup		(gpointer	  instance,
11983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  handler_id,
12083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		 *signal_id_p);
12183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*	handler_match_prepend	(HandlerMatch	 *list,
12283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 Handler	 *handler,
12383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  signal_id);
12483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*	handler_match_free1_R	(HandlerMatch	 *node,
12583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
12683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic	      HandlerMatch*	handlers_find		(gpointer	  instance,
12783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GSignalMatchType mask,
12883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  signal_id,
12983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GQuark		  detail,
13083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GClosure	 *closure,
13183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  func,
13283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  data,
13383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gboolean	  one_and_only);
13483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		handler_ref		(Handler	 *handler);
13583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		handler_unref_R		(guint		  signal_id,
13683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance,
13783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 Handler	 *handler);
13883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		emission_push		(Emission	**emission_list_p,
13983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  signal_id,
14083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GQuark		  detail,
14183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance,
14283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 EmissionState	 *state_p);
14383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void		emission_pop		(Emission	**emission_list_p,
14483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 EmissionState	 *state_p);
14583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline Emission*		emission_find		(Emission	 *emission_list,
14683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 guint		  signal_id,
14783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GQuark		  detail,
14883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance);
149e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikstatic	      gboolean		signal_emit_R		(SignalNode	 *node,
15083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GQuark		  detail,
15183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 gpointer	  instance,
15283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 GValue		 *return_value,
15383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							 const GValue	 *instance_and_params);
154ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
155ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
156ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- structures --- */
157ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _SignalNode
158ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
159ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* permanent portion */
160ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              signal_id;
161ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GType              itype;
162ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gchar             *name;
163ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              destroyed : 1;
164ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
165ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* reinitializable portion */
166ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              flags : 8;
167ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint              n_params : 8;
168ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GType		    *param_types;
169ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GType		     return_type;
170ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GClosure          *class_closure;
171ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GSignalAccumulator accumulator;
172ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GSignalCMarshaller c_marshaller;
173ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GHookList         *emission_hooks;
174ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
175ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
176ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _SignalKey
177ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
178ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GType  itype;
179ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GQuark quark;
180ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint  signal_id;
181ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
182ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
183ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _Emission
184ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
185ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Emission      *next;
186ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint          signal_id;
187830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  GQuark	 detail;
188ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gpointer       instance;
189ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EmissionState *state_p;
190ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
191ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
192ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _HandlerList
193ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
194ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint    signal_id;
195ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler *handlers;
196ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
197ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _Handler
198ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
199ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint         id;
200ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler      *next;
201ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler      *prev;
202830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  GQuark	detail;
203ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint         ref_count : 16;
204ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_MAX_REF_COUNT   (1 << 16)
205ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint         block_count : 12;
206ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_MAX_BLOCK_COUNT (1 << 12)
207ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint         after : 1;
208ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GClosure     *closure;
209ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik};
21083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstruct _HandlerMatch
21183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{
21283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  Handler      *handler;
21383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *next;
21483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  union {
21583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    guint       signal_id;
21683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    gpointer	dummy;
21783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  } d;
21883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik};
219ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
220ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
221ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- variables --- */
222ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GBSearchArray  g_signal_key_bsa = { NULL, 0, 0, 0, NULL };
223ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GHashTable    *g_handler_list_bsa_ht = NULL;
224ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Emission      *g_recursive_emissions = NULL;
225ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Emission      *g_restart_emissions = NULL;
226ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GTrashStack   *g_bsa_ts = NULL;
227ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GTrashStack   *g_handler_ts = NULL;
228ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GTrashStack   *g_emission_ts = NULL;
229ee23c09e83d06a0d131ebd234c132f1c3602c019Tim JanikG_LOCK_DEFINE_STATIC (g_signal_mutex);
230ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
231ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
232ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- signal nodes --- */
233ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic guint          g_n_signal_nodes = 0;
234ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic SignalNode   **g_signal_nodes = NULL;
235ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
236ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline SignalNode*
237ee23c09e83d06a0d131ebd234c132f1c3602c019Tim JanikLOOKUP_SIGNAL_NODE (register guint signal_id)
238ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
239ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (signal_id < g_n_signal_nodes)
240ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return g_signal_nodes[signal_id];
241ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
242ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return NULL;
243ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
244ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
245ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
246ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- functions --- */
247ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline guint
248ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_id_lookup (GQuark quark,
249ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  GType  itype)
250ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
251e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GType *ifaces, type = itype;
252e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  SignalKey key;
253e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint n_ifaces;
254e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
255e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  key.quark = quark;
256e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
257e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  /* try looking up signals for this type and its anchestors */
2588a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  do
2598a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik    {
260e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalKey *signal_key;
2618a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik
262e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      key.itype = type;
2638a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik      signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
2648a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik
2658a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik      if (signal_key)
2668a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik	return signal_key->signal_id;
2678a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik
268e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      type = g_type_parent (type);
2698a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik    }
270e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  while (type);
271e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
272e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  /* no luck, try interfaces it exports */
273e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  ifaces = g_type_interfaces (itype, &n_ifaces);
274e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  while (n_ifaces--)
275e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
276e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalKey *signal_key;
277e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
278e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      key.itype = ifaces[n_ifaces];
279e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key);
280e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
281e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (signal_key)
282e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
283e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (ifaces);
284e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  return signal_key->signal_id;
285e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
286e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
287e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_free (ifaces);
288ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2898a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  return 0;
290ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
291ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
292ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic gint
293ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_lists_cmp (gconstpointer node1,
294ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                   gconstpointer node2)
295ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
296ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  const HandlerList *hlist1 = node1, *hlist2 = node2;
297ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
298ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
299ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
300ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
301ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline HandlerList*
302ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_list_ensure (guint    signal_id,
303ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		     gpointer instance)
304ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
305ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
306ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList key;
307ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
308ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!hlbsa)
309ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
310ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa = g_generic_node_alloc (&g_bsa_ts,
311ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                    sizeof (GBSearchArray),
312ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                    BSA_PRE_ALLOC);
313ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa->cmp_func = handler_lists_cmp;
314ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa->sizeof_node = sizeof (HandlerList);
315ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa->flags = G_BSEARCH_DEFER_SHRINK;
316ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa->n_nodes = 0;
317ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlbsa->nodes = NULL;
318ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
319ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
320ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  key.signal_id = signal_id;
321ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  key.handlers = NULL;
322ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
323ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return g_bsearch_array_insert (hlbsa, &key, FALSE);
324ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
325ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
326ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline HandlerList*
327ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_list_lookup (guint    signal_id,
328ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		     gpointer instance)
329ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
330ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
331ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList key;
332ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
333ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  key.signal_id = signal_id;
334ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
335ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL;
336ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
337ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
338ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Handler*
339ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_lookup (gpointer instance,
340ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		guint    handler_id,
341ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		guint   *signal_id_p)
342ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
343ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
344ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
345ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (hlbsa)
346ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
347ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      guint i;
348ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
349ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      for (i = 0; i < hlbsa->n_nodes; i++)
350ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
351ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
352ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          Handler *handler;
353ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
354ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          for (handler = hlist->handlers; handler; handler = handler->next)
355ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            if (handler->id == handler_id)
356ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              {
357ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                if (signal_id_p)
358ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                  *signal_id_p = hlist->signal_id;
359ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
360ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                return handler;
361ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              }
362ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
363ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
364ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
365ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return NULL;
366ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
367ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
36883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*
36983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandler_match_prepend (HandlerMatch *list,
37083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		       Handler      *handler,
37183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		       guint	     signal_id)
37283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{
37383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *node;
37483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
37583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  /* yeah, we could use our own memchunk here, introducing yet more
37683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   * rarely used cached nodes and extra allocation overhead.
37783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   * instead, we use GList* nodes, since they are exactly the size
37883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   * we need and are already cached. g_signal_init() asserts this.
37983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik   */
38083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node = (HandlerMatch*) g_list_alloc ();
38183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node->handler = handler;
38283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node->next = list;
38383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  node->d.signal_id = signal_id;
38483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  handler_ref (handler);
38583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
38683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return node;
38783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik}
38883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch*
38983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandler_match_free1_R (HandlerMatch *node,
39083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		       gpointer      instance)
39183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{
39283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *next = node->next;
39383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
39483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  handler_unref_R (node->d.signal_id, instance, node->handler);
39583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  g_list_free_1 ((GList*) node);
39683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
39783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return next;
39883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik}
39983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
40083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic HandlerMatch*
40183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandlers_find (gpointer         instance,
40283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       GSignalMatchType mask,
40383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       guint            signal_id,
40483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       GQuark           detail,
40583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       GClosure        *closure,
40683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       gpointer         func,
40783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       gpointer         data,
40883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	       gboolean         one_and_only)
409ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
41083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *mlist = NULL;
41183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
412ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (mask & G_SIGNAL_MATCH_ID)
413ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
414ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      HandlerList *hlist = handler_list_lookup (signal_id, instance);
415ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      Handler *handler;
416790a7bd3be608d9b12a18711d4400490d96b2a46Elliot Lee      SignalNode *node = NULL;
417ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
41855ec7f32a6852dba73abb29e650615b66b065ef9Tim Janik      if (mask & G_SIGNAL_MATCH_FUNC)
419ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
420ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  node = LOOKUP_SIGNAL_NODE (signal_id);
421ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (!node || !node->c_marshaller)
422ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    return NULL;
423ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
42483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
425ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      mask = ~mask;
426ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
42783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik        if (handler->id &&
42883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	    ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
429830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
430ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
431830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
432ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
433ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik					      handler->closure->meta_marshal == 0 &&
434ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik					      ((GCClosure*) handler->closure)->callback == func)))
43583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	  {
43683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	    mlist = handler_match_prepend (mlist, handler, signal_id);
43783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	    if (one_and_only)
43883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	      return mlist;
43983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	  }
440ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
441ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
442ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
443ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
444ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
445ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      mask = ~mask;
446ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (hlbsa)
447ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
448ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          guint i;
449ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
450ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          for (i = 0; i < hlbsa->n_nodes; i++)
451ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            {
452ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
453790a7bd3be608d9b12a18711d4400490d96b2a46Elliot Lee	      SignalNode *node = NULL;
454ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              Handler *handler;
455ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
456ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      if (!(mask & G_SIGNAL_MATCH_FUNC))
457ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		{
458ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
459ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  if (!node->c_marshaller)
460ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    continue;
461ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		}
46283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
463ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              for (handler = hlist->handlers; handler; handler = handler->next)
46483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		if (handler->id &&
46583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		    ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
466830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik                    ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
467ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                    ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
468830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		    ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
469ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
470ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik						      handler->closure->meta_marshal == 0 &&
471ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik						      ((GCClosure*) handler->closure)->callback == func)))
47283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		  {
473a453526f350a3956a26f71db481bd8b436c65f97Owen Taylor		    mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
47483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		    if (one_and_only)
47583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		      return mlist;
47683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik		  }
477ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            }
478ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
479ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
480ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
48183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return mlist;
482ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
483ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
484ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline Handler*
485ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_new (gboolean after)
486ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
487ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  static guint handler_id = 1;
488ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler *handler = g_generic_node_alloc (&g_handler_ts,
489ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                           sizeof (Handler),
490ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                           HANDLER_PRE_ALLOC);
491ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#ifndef G_DISABLE_CHECKS
492ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (handler_id == 0)
493ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
494ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif
495ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
496ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->id = handler_id++;
497ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->prev = NULL;
498ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->next = NULL;
499830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  handler->detail = 0;
500ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->ref_count = 1;
501ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->block_count = 0;
502ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->after = after != FALSE;
503ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->closure = NULL;
504ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
505ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return handler;
506ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
507ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
508ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
509ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_ref (Handler *handler)
510ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
511ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (handler->ref_count > 0);
512ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
513ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#ifndef G_DISABLE_CHECKS
514ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1)
515ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG);
516ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif
517ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
518ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->ref_count += 1;
519ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
520ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
521ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
522ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_unref_R (guint    signal_id,
523ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		 gpointer instance,
524ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		 Handler *handler)
525ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
526ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (handler->ref_count > 0);
527ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
528ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler->ref_count -= 1;
529ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!handler->ref_count)
530ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
531ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (handler->next)
532ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        handler->next->prev = handler->prev;
53383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      if (handler->prev)	/* watch out for g_signal_handlers_destroy()! */
534ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        handler->prev->next = handler->next;
535ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
536ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
537ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          HandlerList *hlist = handler_list_lookup (signal_id, instance);
538ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
539ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          hlist->handlers = handler->next;
540ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
541ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
542ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_closure_unref (handler->closure);
543ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_LOCK (g_signal_mutex);
544ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_generic_node_free (&g_handler_ts, handler);
545ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
546ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
547ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
548ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic void
549ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_insert (guint    signal_id,
550ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		gpointer instance,
551ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		Handler  *handler)
552ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
553ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList *hlist;
554ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
555e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
556ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
557ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  hlist = handler_list_ensure (signal_id, instance);
558ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!hlist->handlers)
559ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    hlist->handlers = handler;
560ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else if (hlist->handlers->after && !handler->after)
561ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
562ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->next = hlist->handlers;
563ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlist->handlers->prev = handler;
564ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      hlist->handlers = handler;
565ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
566ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
567ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
568ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      Handler *tmp = hlist->handlers;
569ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
570ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (handler->after)
571ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        while (tmp->next)
572ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          tmp = tmp->next;
573ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
574ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        while (tmp->next && !tmp->next->after)
575ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          tmp = tmp->next;
576ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (tmp->next)
577ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        tmp->next->prev = handler;
578ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->next = tmp->next;
579ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->prev = tmp;
580ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      tmp->next = handler;
581ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
582ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
583ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
584ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
585ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikemission_push (Emission     **emission_list_p,
586ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       guint          signal_id,
587830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	       GQuark	      detail,
588ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       gpointer       instance,
589ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       EmissionState *state_p)
590ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
591ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Emission *emission = g_generic_node_alloc (&g_emission_ts,
592ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                             sizeof (Emission),
593ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                                             EMISSION_PRE_ALLOC);
594ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  emission->next = *emission_list_p;
595ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  emission->signal_id = signal_id;
596830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  emission->detail = detail;
597ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  emission->instance = instance;
598ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  emission->state_p = state_p;
599ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  *emission_list_p = emission;
600ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
601ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
602ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void
603830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janikemission_pop (Emission     **emission_list_p,
604830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      EmissionState *state_p)
605ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
606830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  Emission **loc = emission_list_p, *emission = *loc;
60783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
608830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  while (emission->state_p != state_p)
609830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
610830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      loc = &emission->next;
611830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      emission = *loc;
612830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    }
613830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  *loc = emission->next;
614ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_generic_node_free (&g_emission_ts, emission);
615ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
616ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
617ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline Emission*
618ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikemission_find (Emission *emission_list,
619ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       guint     signal_id,
620830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	       GQuark    detail,
621ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       gpointer  instance)
622ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
623ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Emission *emission;
624ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
625ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  for (emission = emission_list; emission; emission = emission->next)
626830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    if (emission->instance == instance &&
627830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	emission->signal_id == signal_id &&
628830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	emission->detail == detail)
629ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      return emission;
630ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return NULL;
631ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
632ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
633ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic gint
634ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_key_cmp (gconstpointer node1,
635ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                gconstpointer node2)
636ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
637ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  const SignalKey *key1 = node1, *key2 = node2;
638ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
639ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (key1->itype == key2->itype)
640ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
641ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
642ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
643ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
644ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
645ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
646ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_init (void) /* sync with gtype.c */
647ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
648ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
649ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!g_n_signal_nodes)
650ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
65183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      /* handler_id_node_prepend() requires this */
65283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      g_assert (sizeof (GList) == sizeof (HandlerMatch));
65383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
654ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      /* setup signal key array */
655ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_key_bsa.cmp_func = signal_key_cmp;
656ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
657782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik      g_signal_key_bsa.flags = G_BSEARCH_ALIGN_POWER2; /* alloc-only */
658ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
659ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
660ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
661ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
662ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      /* invalid (0) signal_id */
663ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_n_signal_nodes = 1;
664ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
665ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes[0] = NULL;
666ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
667ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
668ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
669ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
670ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
6713cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik_g_signals_destroy (GType itype)
672ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
673ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint i;
674ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
675ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
67683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  for (i = 1; i < g_n_signal_nodes; i++)
677ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
678ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      SignalNode *node = g_signal_nodes[i];
679ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
680ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (node->itype == itype)
681ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
682ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          if (node->destroyed)
683ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed",
684ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                       node->name,
685ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                       g_type_name (node->itype));
686ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          else
687cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik	    signal_destroy_R (node);
688ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
689ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
690ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
691ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
692ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
693ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
694ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_stop_emission (gpointer instance,
695830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik                        guint    signal_id,
696830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			GQuark   detail)
697ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
698ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
699ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
700ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
701ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (signal_id > 0);
702ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
703ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
704ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
705830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
706830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
707830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
708830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      G_UNLOCK (g_signal_mutex);
709830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      return;
710830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    }
711e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
712ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
713ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions;
714830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      Emission *emission = emission_find (emission_list, signal_id, detail, instance);
715ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
716ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission)
717ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
718ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          if (*emission->state_p == EMISSION_HOOK)
719ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook",
720ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                       node->name, instance);
721ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          else if (*emission->state_p == EMISSION_RUN)
722ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            *emission->state_p = EMISSION_STOP;
723ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
724ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
725ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'",
726ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                   node->name, instance);
727ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
728ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
729ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
730ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
731ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
732ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
7333cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikstatic inline guint
7343cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janiksignal_parse_name (const gchar *name,
7353cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		   GType        itype,
7363cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		   GQuark      *detail_p,
7373cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		   gboolean     force_quark)
7383cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik{
7393cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  const gchar *colon = strchr (name, ':');
7403cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  guint signal_id;
7413cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
7423cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  if (!colon)
7433cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    {
7443cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      signal_id = signal_id_lookup (g_quark_try_string (name), itype);
7453cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (signal_id && detail_p)
7463cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	*detail_p = 0;
7473cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    }
7483cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  else if (colon[1] == ':')
7493cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    {
7503cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      gchar buffer[32];
7513cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      guint l = colon - name;
7523cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
7533cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (l < 32)
7543cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	{
7553cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  memcpy (buffer, name, l);
7563cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  buffer[l] = 0;
7573cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  signal_id = signal_id_lookup (g_quark_try_string (buffer), itype);
7583cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	}
7593cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      else
7603cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	{
7613cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  gchar *signal = g_new (gchar, l + 1);
7623cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
7633cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  memcpy (signal, name, l);
7643cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  signal[l] = 0;
7653cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  signal_id = signal_id_lookup (g_quark_try_string (signal), itype);
7663cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	  g_free (signal);
7673cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	}
7683cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
7693cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (signal_id && detail_p)
7703cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	*detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0;
7713cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    }
7723cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  else
7733cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    signal_id = 0;
7743cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  return signal_id;
7753cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik}
7763cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
7773cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikgboolean
7783cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikg_signal_parse_name (const gchar *detailed_signal,
7793cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     GType        itype,
7803cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     guint       *signal_id_p,
7813cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     GQuark      *detail_p,
7823cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik		     gboolean	  force_detail_quark)
7833cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik{
7843cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  GQuark detail = 0;
7853cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  guint signal_id;
78683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
7873cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  g_return_val_if_fail (detailed_signal != NULL, FALSE);
7883cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
78983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
7903cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  G_LOCK (g_signal_mutex);
7913cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
7923cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  G_UNLOCK (g_signal_mutex);
79383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
7943cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  if (signal_id)
7953cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    {
7963cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (signal_id_p)
7973cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	*signal_id_p = signal_id;
7983cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      if (detail_p)
7993cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik	*detail_p = detail;
80083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
8013cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik      return TRUE;
8023cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    }
8033cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik  else
8043cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik    return FALSE;
8053cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik}
8063cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik
807ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint
808ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_lookup (const gchar *name,
809ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 GType        itype)
810ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
8118a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  guint signal_id;
8128a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik
813ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (name != NULL, 0);
814ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
815ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
816ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
8178a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
818ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
819ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
8208a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  return signal_id;
821ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
822ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
823ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikgchar*
824ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_name (guint signal_id)
825ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
826ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
827ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gchar *name;
82883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
829ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
830ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
831ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  name = node ? node->name : NULL;
832ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
833ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
834ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return name;
835ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
836ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
837ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
838ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_query (guint         signal_id,
839ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		GSignalQuery *query)
840ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
841ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
84283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
843ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (query != NULL);
84483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
845ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
846ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
847ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!node || node->destroyed)
848ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    query->signal_id = 0;
849ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
850ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
851ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->signal_id = node->signal_id;
852ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->signal_name = node->name;
853ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->itype = node->itype;
854ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->signal_flags = node->flags;
855ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->return_type = node->return_type;
856ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->n_params = node->n_params;
857ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      query->param_types = node->param_types;
858ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
859ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
860ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
861ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
86265c423b458d9fd1338cab0de7951092c09ab1686Tim Janikguint*
86365c423b458d9fd1338cab0de7951092c09ab1686Tim Janikg_signal_list_ids (GType  itype,
86465c423b458d9fd1338cab0de7951092c09ab1686Tim Janik		   guint *n_ids)
865300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor{
866300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  SignalKey *keys;
867300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  GArray *result;
86865c423b458d9fd1338cab0de7951092c09ab1686Tim Janik  guint n_nodes;
86965c423b458d9fd1338cab0de7951092c09ab1686Tim Janik  guint i;
87083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
871300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
87265c423b458d9fd1338cab0de7951092c09ab1686Tim Janik  g_return_val_if_fail (n_ids != NULL, NULL);
87383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
87465c423b458d9fd1338cab0de7951092c09ab1686Tim Janik  G_LOCK (g_signal_mutex);
87583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
876300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  keys = g_signal_key_bsa.nodes;
877300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  n_nodes  = g_signal_key_bsa.n_nodes;
878300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  result = g_array_new (FALSE, FALSE, sizeof (guint));
879300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor
880300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  for (i = 0; i < n_nodes; i++)
88165c423b458d9fd1338cab0de7951092c09ab1686Tim Janik    if (keys[i].itype == itype)
88265c423b458d9fd1338cab0de7951092c09ab1686Tim Janik      {
88365c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	gchar *name = g_quark_to_string (keys[i].quark);
88483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
88565c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	/* Signal names with "_" in them are aliases to the same
88665c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	 * name with "-" instead of "_".
88765c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	 */
88865c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	if (!strchr (name, '_'))
88965c423b458d9fd1338cab0de7951092c09ab1686Tim Janik	  g_array_append_val (result, keys[i].signal_id);
89065c423b458d9fd1338cab0de7951092c09ab1686Tim Janik      }
89183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
892300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  *n_ids = result->len;
89383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
89465c423b458d9fd1338cab0de7951092c09ab1686Tim Janik  G_UNLOCK (g_signal_mutex);
89565c423b458d9fd1338cab0de7951092c09ab1686Tim Janik
896300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor  return (guint *) g_array_free (result, FALSE);
897300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor}
898300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor
899ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint
900b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Penningtong_signal_new_valist (const gchar       *signal_name,
901b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GType              itype,
902b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GSignalFlags       signal_flags,
903b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GClosure          *class_closure,
904b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GSignalAccumulator accumulator,
905b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GSignalCMarshaller c_marshaller,
906b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     GType              return_type,
907b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     guint              n_params,
908b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                     va_list            args)
909e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
910e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GType *param_types;
911e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint i;
912e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint signal_id;
913e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
914e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (n_params > 0)
915e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
916e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      param_types = g_new (GType, n_params);
917e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
918e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      for (i = 0; i < n_params; i++)
919e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	param_types[i] = va_arg (args, GType);
920e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
921e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
922e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    param_types = NULL;
923e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
924e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  signal_id = g_signal_newv (signal_name, itype, signal_flags,
925e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			     class_closure, accumulator, c_marshaller,
926e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			     return_type, n_params, param_types);
927e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_free (param_types);
928e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
929e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  return signal_id;
930e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
931e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
932e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikguint
933b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Penningtong_signal_newc (const gchar	 *signal_name,
934b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               GType		  itype,
935b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               GSignalFlags	  signal_flags,
936b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               guint              class_offset,
937b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               GSignalAccumulator accumulator,
938b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               GSignalCMarshaller c_marshaller,
939b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               GType		  return_type,
940b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               guint		  n_params,
941b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington               ...)
942b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington{
943b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  va_list args;
944b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  guint signal_id;
945b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
946b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  g_return_val_if_fail (signal_name != NULL, 0);
947b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
948b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  va_start (args, n_params);
949b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
950b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
951b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                                   g_signal_type_cclosure_new (itype,
952b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                                                               class_offset),
953b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                                   accumulator, c_marshaller,
954b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington                                   return_type, n_params, args);
955b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
956b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  va_end (args);
957b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
958b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington  return signal_id;
959b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington}
960b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington
961b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Penningtonguint
962ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_newv (const gchar       *signal_name,
963ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GType              itype,
964830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik               GSignalFlags       signal_flags,
965ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GClosure          *class_closure,
966ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GSignalAccumulator accumulator,
967ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GSignalCMarshaller c_marshaller,
968ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GType		  return_type,
969ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               guint              n_params,
970ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik               GType		 *param_types)
971ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
972ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gchar *name;
973ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint signal_id, i;
974ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
975ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
976ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (signal_name != NULL, 0);
977ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
978ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (n_params)
979ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_return_val_if_fail (param_types != NULL, 0);
980ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (return_type != G_TYPE_NONE)
981ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_return_val_if_fail (accumulator == NULL, 0);
982ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
983ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  name = g_strdup (signal_name);
984ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_strdelimit (name, G_STR_DELIMITERS ":^", '_');  // FIXME do character checks like for types
985ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
986ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
987ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
9888a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik  signal_id = signal_id_lookup (g_quark_try_string (name), itype);
989ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
990ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node && !node->destroyed)
991ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
992ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s",
993ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 name,
994ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 g_type_name (node->itype),
995ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
996ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (name);
997ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
998ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      return 0;
999ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1000ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node && node->itype != itype)
1001ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1002ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'",
1003ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 name,
1004ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 g_type_name (itype),
1005ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                 g_type_name (node->itype));
1006ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (name);
1007ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
1008ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      return 0;
1009ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1010ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  for (i = 0; i < n_params; i++)
1011ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    if (!G_TYPE_IS_VALUE (param_types[i]) ||
1012ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	param_types[i] == G_TYPE_ENUM || param_types[i] == G_TYPE_FLAGS) /* FIXME: kludge */
1013ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      {
1014ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type",
1015ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		   i + 1, g_type_name (param_types[i]), g_type_name (itype), name);
1016ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_free (name);
1017ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	G_UNLOCK (g_signal_mutex);
1018ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	return 0;
1019ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      }
1020ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type))
1021ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1022ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type",
1023ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		 g_type_name (param_types[i]), g_type_name (itype), name);
1024ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (name);
1025ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
1026ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      return 0;
1027ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1028ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1029ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* setup permanent portion of signal node */
1030ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (!node)
1031ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1032ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      SignalKey key;
1033ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1034ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      signal_id = g_n_signal_nodes++;
1035ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node = g_new (SignalNode, 1);
1036ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node->signal_id = signal_id;
1037ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
1038ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_signal_nodes[signal_id] = node;
1039ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node->itype = itype;
1040ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      node->name = name;
1041ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.itype = itype;
1042ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.quark = g_quark_from_string (node->name);
1043ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.signal_id = signal_id;
1044ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
1045ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_strdelimit (node->name, "_", '-');
1046ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      key.quark = g_quark_from_static_string (node->name);
1047ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE);
1048ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1049ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->destroyed = FALSE;
1050ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1051ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* setup reinitializable portion */
1052830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
1053ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->n_params = n_params;
1054ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
1055ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->return_type = return_type;
1056ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL;
1057ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->accumulator = accumulator;
1058ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->c_marshaller = c_marshaller;
1059ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node->emission_hooks = NULL;
1060ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure))
1061ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_closure_set_marshal (class_closure, node->c_marshaller);
1062ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1063ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1064ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return signal_id;
1065ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1066ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1067ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic void
1068ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_destroy_R (SignalNode *signal_node)
1069ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1070ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode node = *signal_node;
1071ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1072ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->destroyed = TRUE;
1073ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1074ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* reentrancy caution, zero out real contents first */
1075ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->n_params = 0;
1076ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->param_types = NULL;
1077ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->return_type = 0;
1078ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->class_closure = NULL;
1079ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->accumulator = NULL;
1080ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->c_marshaller = NULL;
1081ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  signal_node->emission_hooks = NULL;
1082ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1083782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifdef	G_ENABLE_DEBUG
1084ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* check current emissions */
1085ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  {
1086ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    Emission *emission;
1087ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1088ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions;
1089ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik         emission; emission = emission->next)
1090ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission->signal_id == node.signal_id)
1091ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')",
1092ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                    node.name, emission->instance);
1093ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  }
1094ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif
1095ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1096ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  /* free contents that need to
1097ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik   */
1098ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1099ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_free (node.param_types);
1100ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_closure_unref (node.class_closure);
1101ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node.emission_hooks)
1102ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1103ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_hook_list_clear (node.emission_hooks);
1104ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (node.emission_hooks);
1105ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1106ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1107ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1108ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1109ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint
11103cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikg_signal_connect_closure_by_id (gpointer  instance,
11113cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				guint     signal_id,
11123cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				GQuark    detail,
11133cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				GClosure *closure,
11143cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik				gboolean  after)
1115ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1116ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  SignalNode *node;
1117ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint handler_id = 0;
1118ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1119ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1120ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (signal_id > 0, 0);
1121ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (closure != NULL, 0);
1122ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1123ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1124ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
1125e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (node)
1126830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
1127e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1128e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1129e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1130e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1131e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
1132e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1133e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  Handler *handler = handler_new (after);
1134e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1135e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_id = handler->id;
1136e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->detail = detail;
1137e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->closure = g_closure_ref (closure);
1138e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_insert (signal_id, instance, handler);
1139e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
1140e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_closure_set_marshal (closure, node->c_marshaller);
1141e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1142ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1143ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
1144ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1145ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1146ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1147ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  return handler_id;
1148ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1149ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1150e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikguint
1151e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_connect_closure (gpointer     instance,
1152e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			  const gchar *detailed_signal,
1153e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			  GClosure    *closure,
1154e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik			  gboolean     after)
1155e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1156e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint signal_id, handler_id = 0;
1157e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GQuark detail = 0;
1158e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GType itype;
1159e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1160e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1161e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (detailed_signal != NULL, 0);
1162e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (closure != NULL, 0);
1163e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1164e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_LOCK (g_signal_mutex);
1165e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  itype = G_TYPE_FROM_INSTANCE (instance);
1166e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1167e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (signal_id)
1168e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1169e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1170e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1171e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1172e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1173e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else if (!g_type_is_a (itype, node->itype))
1174e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1175e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
1176e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1177e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  Handler *handler = handler_new (after);
1178e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1179e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_id = handler->id;
1180e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->detail = detail;
1181e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->closure = g_closure_ref (closure);
1182e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_insert (signal_id, instance, handler);
1183e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1184e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_closure_set_marshal (handler->closure, node->c_marshaller);
1185e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1186e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1187e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1188e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1189e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_UNLOCK (g_signal_mutex);
1190e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1191e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  return handler_id;
1192e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1193e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1194e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikguint
1195e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_connect_data (gpointer       instance,
1196e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       const gchar   *detailed_signal,
1197e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       GCallback      c_handler,
1198e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       gpointer       data,
1199e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       GClosureNotify destroy_data,
1200e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       gboolean       swapped,
1201e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       gboolean       after)
1202e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1203e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint signal_id, handler_id = 0;
1204e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GQuark detail = 0;
1205e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GType itype;
1206e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1207e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1208e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (detailed_signal != NULL, 0);
1209e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_val_if_fail (c_handler != NULL, 0);
1210e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1211e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_LOCK (g_signal_mutex);
1212e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  itype = G_TYPE_FROM_INSTANCE (instance);
1213e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
1214e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (signal_id)
1215e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1216e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1217e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1218e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (detail && !(node->flags & G_SIGNAL_DETAILED))
1219e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal);
1220e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else if (!g_type_is_a (itype, node->itype))
1221e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1222e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
1223e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1224e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  Handler *handler = handler_new (after);
1225e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1226e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_id = handler->id;
1227e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->detail = detail;
1228e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
1229e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  handler_insert (signal_id, instance, handler);
1230e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
1231e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_closure_set_marshal (handler->closure, node->c_marshaller);
1232e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1233e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1234e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1235e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1236e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_UNLOCK (g_signal_mutex);
1237e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1238e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  return handler_id;
1239e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1240e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1241ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
1242cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_block (gpointer instance,
1243cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                        guint    handler_id)
1244cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1245cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  Handler *handler;
1246cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1247cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1248cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (handler_id > 0);
1249cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1250cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  G_LOCK (g_signal_mutex);
1251cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  handler = handler_lookup (instance, handler_id, NULL);
1252cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (handler)
1253cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1254cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik#ifndef G_DISABLE_CHECKS
1255cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
1256cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik        g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
1257cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik#endif
1258cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1259cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      handler->block_count += 1;
1260cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
1261cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  else
1262cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1263cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  G_UNLOCK (g_signal_mutex);
1264cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1265cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1266cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikvoid
1267cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_unblock (gpointer instance,
1268cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                          guint    handler_id)
1269cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1270cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  Handler *handler;
1271cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1272cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1273cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_if_fail (handler_id > 0);
1274cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1275cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  G_LOCK (g_signal_mutex);
1276cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  handler = handler_lookup (instance, handler_id, NULL);
1277cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (handler)
1278cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1279cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      if (handler->block_count)
1280cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik        handler->block_count -= 1;
1281cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      else
1282cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik        g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance);
1283cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
1284cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  else
1285cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1286cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  G_UNLOCK (g_signal_mutex);
1287cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1288cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1289cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikvoid
1290ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_handler_disconnect (gpointer instance,
1291ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik                             guint    handler_id)
1292ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1293ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  Handler *handler;
1294ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint signal_id;
1295ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1296ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1297ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (handler_id > 0);
1298ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1299ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1300ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  handler = handler_lookup (instance, handler_id, &signal_id);
1301ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (handler)
1302ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1303ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->id = 0;
1304ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler->block_count = 1;
1305ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler_unref_R (signal_id, instance, handler);
1306ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1307ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
1308ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id);
1309ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1310ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1311ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1312ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
131383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikg_signal_handlers_destroy (gpointer instance)
1314ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1315ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GBSearchArray *hlbsa;
1316ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1317ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1318ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1319ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1320ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
1321ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (hlbsa)
1322ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1323ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      guint i;
1324ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1325ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      /* reentrancy caution, delete instance trace first */
1326ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_hash_table_remove (g_handler_list_bsa_ht, instance);
132783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1328ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      for (i = 0; i < hlbsa->n_nodes; i++)
1329ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        {
1330ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i);
1331ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          Handler *handler = hlist->handlers;
1332ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1333ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik          while (handler)
1334ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            {
1335ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              Handler *tmp = handler;
1336ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1337ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              handler = tmp->next;
1338ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              tmp->block_count = 1;
1339ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              /* cruel unlink, this works because _all_ handlers vanish */
1340ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              tmp->next = NULL;
1341ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              tmp->prev = tmp;
1342ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              if (tmp->id)
1343ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		{
1344ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  tmp->id = 0;
1345ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  handler_unref_R (0, NULL, tmp);
1346ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		}
1347ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik            }
1348ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik        }
1349ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_free (hlbsa->nodes);
1350ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_generic_node_free (&g_bsa_ts, hlbsa);
1351ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1352ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1353ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1354ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1355cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint
1356cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_find (gpointer         instance,
1357cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       GSignalMatchType mask,
1358cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       guint            signal_id,
1359cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik		       GQuark		detail,
1360cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       GClosure        *closure,
1361cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       gpointer         func,
1362cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik                       gpointer         data)
1363ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1364cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint handler_id = 0;
1365ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1366cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
1367cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
136883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1369cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & G_SIGNAL_MATCH_MASK)
1370ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
137183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      HandlerMatch *mlist;
137283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1373cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_LOCK (g_signal_mutex);
137483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
137583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      if (mlist)
137683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	{
137783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	  handler_id = mlist->handler->id;
137883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	  handler_match_free1_R (mlist, instance);
137983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik	}
1380cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
1381ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
138283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1383cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return handler_id;
1384ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1385ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1386cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikstatic guint
138783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiksignal_handlers_foreach_matched_R (gpointer         instance,
138883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   GSignalMatchType mask,
138983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   guint            signal_id,
139083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   GQuark           detail,
139183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   GClosure        *closure,
139283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   gpointer         func,
139383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   gpointer         data,
139483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik				   void		  (*callback) (gpointer instance,
139583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik							       guint    handler_id))
1396ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
139783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *mlist;
1398cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
139983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
140083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
140183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  while (mlist)
1402ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1403cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      n_handlers++;
1404cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
140583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      callback (instance, mlist->handler->id);
1406cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_LOCK (g_signal_mutex);
140783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      mlist = handler_match_free1_R (mlist, instance);
1408ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
140983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1410cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1411ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1412ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1413ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint
1414cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_block_matched (gpointer         instance,
1415cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 GSignalMatchType mask,
1416cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 guint            signal_id,
1417cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 GQuark           detail,
1418cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 GClosure        *closure,
1419cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 gpointer         func,
1420cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				 gpointer         data)
1421ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1422cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
142383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1424cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1425cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
142683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1427cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1428cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1429cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_LOCK (g_signal_mutex);
143083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
143183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      closure, func, data,
143283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      g_signal_handler_block);
1433cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
1434cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
143583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1436cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1437cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1438cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1439cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint
1440cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_unblock_matched (gpointer         instance,
1441cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   GSignalMatchType mask,
1442cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   guint            signal_id,
1443cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   GQuark           detail,
1444cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   GClosure        *closure,
1445cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   gpointer         func,
1446cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				   gpointer         data)
1447cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1448cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
1449ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1450cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1451cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
1452ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1453cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1454cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1455cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_LOCK (g_signal_mutex);
145683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
145783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      closure, func, data,
145883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      g_signal_handler_unblock);
1459cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
1460cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
146183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1462cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1463cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik}
1464cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik
1465cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint
1466cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_disconnect_matched (gpointer         instance,
1467cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      GSignalMatchType mask,
1468cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      guint            signal_id,
1469cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      GQuark           detail,
1470cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      GClosure        *closure,
1471cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      gpointer         func,
1472cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik				      gpointer         data)
1473cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{
1474cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  guint n_handlers = 0;
147583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1476cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1477cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE);
147883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1479cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
1480cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1481cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_LOCK (g_signal_mutex);
148283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
148383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      closure, func, data,
148483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik						      g_signal_handler_disconnect);
1485cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
1486cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
148783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik
1488cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik  return n_handlers;
1489ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1490ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1491ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikgboolean
1492cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_has_handler_pending (gpointer instance,
1493cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik			      guint    signal_id,
1494cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik			      GQuark   detail,
1495cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik			      gboolean may_be_blocked)
1496ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
149783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  HandlerMatch *mlist;
149883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  gboolean has_pending;
1499ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1500ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
1501ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_val_if_fail (signal_id > 0, FALSE);
1502ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1503ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1504830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (detail)
1505830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
1506830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
1507830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1508830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      if (!(node->flags & G_SIGNAL_DETAILED))
1509830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	{
1510830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1511830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  G_UNLOCK (g_signal_mutex);
1512830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  return FALSE;
1513830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	}
1514830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    }
151583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  mlist = handlers_find (instance,
151683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik			 (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
151783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik			 signal_id, detail, NULL, NULL, NULL, TRUE);
151883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  if (mlist)
151983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    {
152083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      has_pending = TRUE;
152183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik      handler_match_free1_R (mlist, instance);
152283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    }
152383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  else
152483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik    has_pending = FALSE;
1525ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1526ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
152783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik  return has_pending;
1528ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1529ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1530ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid
1531ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_emitv (const GValue *instance_and_params,
1532ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		guint         signal_id,
1533830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		GQuark	      detail,
1534ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		GValue       *return_value)
1535ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1536ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  const GValue *param_values;
1537e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  gpointer instance;
1538e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  SignalNode *node;
1539ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint i;
1540ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1541ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (instance_and_params != NULL);
1542ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  instance = g_value_get_as_pointer (instance_and_params);
1543ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1544ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  g_return_if_fail (signal_id > 0);
1545e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1546ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  param_values = instance_and_params + 1;
1547ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1548ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_LOCK (g_signal_mutex);
1549ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
1550e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1551cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    {
1552cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1553cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      G_UNLOCK (g_signal_mutex);
1554cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik      return;
1555cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik    }
1556782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifdef G_ENABLE_DEBUG
1557830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (detail && !(node->flags & G_SIGNAL_DETAILED))
1558830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    {
1559830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1560830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      G_UNLOCK (g_signal_mutex);
1561830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      return;
1562830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    }
1563ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  for (i = 0; i < node->n_params; i++)
1564ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    if (!G_VALUE_HOLDS (param_values + i, node->param_types[i]))
1565ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      {
1566e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'",
1567e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		    G_STRLOC,
1568ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    g_type_name (node->param_types[i]),
1569ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    i,
1570ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    node->name,
1571ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    G_VALUE_TYPE_NAME (param_values + i));
1572ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	G_UNLOCK (g_signal_mutex);
1573ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	return;
1574ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      }
1575ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node->return_type != G_TYPE_NONE)
1576ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1577ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (!return_value)
1578ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1579e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)",
1580e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      G_STRLOC,
1581ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      g_type_name (node->return_type),
1582ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      node->name);
1583ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  G_UNLOCK (g_signal_mutex);
1584ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  return;
1585ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1586ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else if (!node->accumulator && !G_VALUE_HOLDS (return_value, node->return_type))
1587ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1588e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'",
1589e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      G_STRLOC,
1590ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      g_type_name (node->return_type),
1591ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      node->name,
1592ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      G_VALUE_TYPE_NAME (return_value));
1593ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  G_UNLOCK (g_signal_mutex);
1594ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  return;
1595ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1596ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1597ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  else
1598ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    return_value = NULL;
1599782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#endif	/* G_ENABLE_DEBUG */
1600e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1601830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  signal_emit_R (node, detail, instance, return_value, instance_and_params);
1602ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  G_UNLOCK (g_signal_mutex);
1603ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
1604ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1605e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid
1606e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit_valist (gpointer instance,
1607e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      guint    signal_id,
1608e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      GQuark   detail,
1609e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		      va_list  var_args)
1610e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1611e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL;
1612e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GValue *param_values;
1613e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  SignalNode *node;
1614e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint i;
1615e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1616e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1617e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (signal_id > 0);
1618e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1619e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_LOCK (g_signal_mutex);
1620e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  node = LOOKUP_SIGNAL_NODE (signal_id);
1621e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
1622e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1623e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance);
1624e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      G_UNLOCK (g_signal_mutex);
1625e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return;
1626e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1627e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#ifndef G_DISABLE_CHECKS
1628e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (detail && !(node->flags & G_SIGNAL_DETAILED))
1629e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1630e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
1631e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      G_UNLOCK (g_signal_mutex);
1632e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return;
1633e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1634e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#endif  /* !G_DISABLE_CHECKS */
1635e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1636e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (node->n_params < MAX_STACK_VALUES)
1637e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    instance_and_params = stack_values;
1638e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1639e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1640e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      free_me = g_new (GValue, node->n_params + 1);
1641e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      instance_and_params = free_me;
1642e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1643e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  param_values = instance_and_params + 1;
1644e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  for (i = 0; i < node->n_params; i++)
1645e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1646e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      gchar *error;
1647e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1648e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      param_values[i].g_type = 0;
1649e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_value_init (param_values + i, node->param_types[i]);
1650e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      G_VALUE_COLLECT (param_values + i, var_args, &error);
1651e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (error)
1652e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1653e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_warning ("%s: %s", G_STRLOC, error);
1654e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (error);
1655e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1656e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  /* we purposely leak the value here, it might not be
1657e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	   * in a sane state if an error condition occoured
1658e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	   */
1659e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  while (i--)
1660e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	    g_value_unset (param_values + i);
1661e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1662e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  G_UNLOCK (g_signal_mutex);
1663e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (free_me);
1664e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  return;
1665e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1666e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1667e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  instance_and_params->g_type = 0;
1668e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_value_init (instance_and_params, node->itype);
1669e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_value_set_instance (instance_and_params, instance);
1670e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (node->return_type == G_TYPE_NONE)
1671e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    signal_emit_R (node, detail, instance, NULL, instance_and_params);
1672e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1673e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1674e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      GValue return_value = { 0, };
1675e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      gchar *error = NULL;
1676e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1677e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_value_init (&return_value, node->return_type);
1678e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (signal_emit_R (node, detail, instance, &return_value, instance_and_params))
1679e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	G_VALUE_LCOPY (&return_value, var_args, &error);
1680e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      if (!error)
1681e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	g_value_unset (&return_value);
1682e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      else
1683e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	{
1684e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_warning ("%s: %s", G_STRLOC, error);
1685e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  g_free (error);
1686e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1687e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  /* we purposely leak the value here, it might not be
1688e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	   * in a sane state if an error condition occoured
1689e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	   */
1690e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	}
1691e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1692e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  for (i = 0; i < node->n_params; i++)
1693e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_value_unset (param_values + i);
1694e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_value_unset (instance_and_params);
1695e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (free_me)
1696e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_free (free_me);
1697e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_UNLOCK (g_signal_mutex);
1698e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1699e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1700e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid
1701e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit (gpointer instance,
1702e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	       guint    signal_id,
1703e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	       GQuark   detail,
1704e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	       ...)
1705e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1706e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  va_list var_args;
1707e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1708e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  va_start (var_args, detail);
1709e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_signal_emit_valist (instance, signal_id, detail, var_args);
1710e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  va_end (var_args);
1711e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1712e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1713e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid
1714e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit_by_name (gpointer     instance,
1715e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       const gchar *detailed_signal,
1716e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik		       ...)
1717e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{
1718e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GQuark detail = 0;
1719e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  guint signal_id;
1720e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1721e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
1722e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  g_return_if_fail (detailed_signal != NULL);
1723e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1724e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_LOCK (g_signal_mutex);
1725e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE);
1726e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  G_UNLOCK (g_signal_mutex);
1727e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1728e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  if (signal_id)
1729e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    {
1730e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      va_list var_args;
1731e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1732e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      va_start (var_args, detailed_signal);
1733e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      g_signal_emit_valist (instance, signal_id, detail, var_args);
1734e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      va_end (var_args);
1735e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    }
1736e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  else
1737e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
1738e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik}
1739e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
1740e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikstatic gboolean
1741ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_emit_R (SignalNode   *node,
1742830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	       GQuark	     detail,
1743ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       gpointer      instance,
1744ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       GValue	    *return_value,
1745ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	       const GValue *instance_and_params)
1746ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{
1747ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  EmissionState emission_state = 0;
1748ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GSignalAccumulator accumulator;
1749830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  GSignalInvocationHint ihint;
1750ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  GClosure *class_closure;
1751ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  HandlerList *hlist;
1752830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  Handler *handler_list = NULL;
1753e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  GValue accu = { 0, };
1754ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  gboolean accu_used = FALSE;
1755ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  guint signal_id = node->signal_id;
1756e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  gboolean return_value_altered = FALSE;
1757ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1758ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node->flags & G_SIGNAL_NO_RECURSE)
1759ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1760830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance);
1761ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1762ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission)
1763ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1764ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  *emission->state_p = EMISSION_RESTART;
1765e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	  return return_value_altered;
1766ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1767ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1768830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  ihint.signal_id = node->signal_id;
1769830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  ihint.detail = detail;
1770ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  accumulator = node->accumulator;
1771ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (accumulator)
1772e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_value_init (&accu, node->return_type);
1773ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions,
1774830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		 signal_id, detail, instance, &emission_state);
1775ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  class_closure = node->class_closure;
1776ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1777ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMIT_RESTART:
1778ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1779830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
1780830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    handler_unref_R (signal_id, instance, handler_list);
1781830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  hlist = handler_list_lookup (signal_id, instance);
1782830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  handler_list = hlist ? hlist->handlers : NULL;
1783830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
1784830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    handler_ref (handler_list);
1785830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1786830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  ihint.run_type = G_SIGNAL_RUN_FIRST;
1787830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1788ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
1789ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1790ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_RUN;
1791ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1792ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
1793ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (accumulator)
1794ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1795ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (accu_used)
1796ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    g_value_reset (&accu);
1797ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  g_closure_invoke (class_closure,
1798ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			    &accu,
1799ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			    node->n_params + 1,
1800830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			    instance_and_params,
1801830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			    &ihint);
1802830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  if (!accumulator (&ihint, return_value, &accu) &&
1803ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      emission_state == EMISSION_RUN)
1804ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    emission_state = EMISSION_STOP;
1805ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  accu_used = TRUE;
1806ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1807ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
1808ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_closure_invoke (class_closure,
1809ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			  return_value,
1810ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			  node->n_params + 1,
1811830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			  instance_and_params,
1812830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			  &ihint);
1813ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_LOCK (g_signal_mutex);
1814e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return_value_altered = TRUE;
1815ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1816ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_STOP)
1817ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
1818ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else if (emission_state == EMISSION_RESTART)
1819ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
1820ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1821ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1822ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (node->emission_hooks)
1823ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1824ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_HOOK;
1825ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1826ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
1827ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_print ("emission_hooks()\n");
1828ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_LOCK (g_signal_mutex);
1829ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1830ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_RESTART)
1831ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
1832ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1833ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1834830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
1835ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1836830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      Handler *handler = handler_list;
1837ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1838ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_RUN;
1839ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler_ref (handler);
1840ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      do
1841ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1842ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  Handler *tmp;
1843ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1844830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  if (handler->after)
1845830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    {
1846830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      handler_unref_R (signal_id, instance, handler_list);
1847830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      handler_list = handler;
1848830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      break;
1849830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    }
1850830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  else if (!handler->block_count && (!handler->detail || handler->detail == detail))
1851ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    {
1852ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      G_UNLOCK (g_signal_mutex);
1853ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      if (accumulator)
1854ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		{
1855ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  if (accu_used)
1856ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    g_value_reset (&accu);
1857ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  g_closure_invoke (handler->closure,
1858ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				    &accu,
1859ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				    node->n_params + 1,
1860830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				    instance_and_params,
1861830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				    &ihint);
1862830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		  if (!accumulator (&ihint, return_value, &accu) &&
1863ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      emission_state == EMISSION_RUN)
1864ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    emission_state = EMISSION_STOP;
1865ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  accu_used = TRUE;
1866ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		}
1867ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      else
1868ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		g_closure_invoke (handler->closure,
1869ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				  return_value,
1870ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				  node->n_params + 1,
1871830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				  instance_and_params,
1872830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				  &ihint);
1873ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      G_LOCK (g_signal_mutex);
1874e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	      return_value_altered = TRUE;
1875ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1876ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1877ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    }
1878ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  else
1879ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    tmp = handler->next;
1880ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1881ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (tmp)
1882ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    handler_ref (tmp);
1883830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  handler_unref_R (signal_id, instance, handler_list);
1884830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  handler_list = handler;
1885ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  handler = tmp;
1886ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1887ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      while (handler);
1888ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1889ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_STOP)
1890ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
1891ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else if (emission_state == EMISSION_RESTART)
1892ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
1893ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1894ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1895830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  ihint.run_type = G_SIGNAL_RUN_LAST;
1896830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1897ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
1898ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1899ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_RUN;
1900ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1901ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
1902ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (accumulator)
1903ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1904ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (accu_used)
1905ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    g_value_reset (&accu);
1906ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  g_closure_invoke (class_closure,
1907ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			    &accu,
1908ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			    node->n_params + 1,
1909830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			    instance_and_params,
1910830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			    &ihint);
1911830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik          if (!accumulator (&ihint, return_value, &accu) &&
1912ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      emission_state == EMISSION_RUN)
1913ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    emission_state = EMISSION_STOP;
1914ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  accu_used = TRUE;
1915ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1916ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else
1917ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_closure_invoke (class_closure,
1918ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			  return_value,
1919ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			  node->n_params + 1,
1920830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			  instance_and_params,
1921830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			  &ihint);
1922ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_LOCK (g_signal_mutex);
1923e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik      return_value_altered = TRUE;
1924ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1925ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_STOP)
1926ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
1927ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else if (emission_state == EMISSION_RESTART)
1928ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
1929ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1930ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1931830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
1932ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1933830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      Handler *handler = handler_list;
1934ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1935ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_RUN;
1936ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      handler_ref (handler);
1937ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      do
1938ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1939ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  Handler *tmp;
1940ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1941830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	  if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail))
1942ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    {
1943ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      G_UNLOCK (g_signal_mutex);
1944ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik              if (accumulator)
1945ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		{
1946ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  if (accu_used)
1947ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    g_value_reset (&accu);
1948ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  g_closure_invoke (handler->closure,
1949ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				    &accu,
1950ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				    node->n_params + 1,
1951830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				    instance_and_params,
1952830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				    &ihint);
1953830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik		  if (!accumulator (&ihint, return_value, &accu) &&
1954ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		      emission_state == EMISSION_RUN)
1955ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		    emission_state = EMISSION_STOP;
1956ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		  accu_used = TRUE;
1957ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		}
1958ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      else
1959ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik		g_closure_invoke (handler->closure,
1960ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				  return_value,
1961ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik				  node->n_params + 1,
1962830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				  instance_and_params,
1963830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik				  &ihint);
1964ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      G_LOCK (g_signal_mutex);
1965e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik	      return_value_altered = TRUE;
1966ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1967ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	      tmp = emission_state == EMISSION_RUN ? handler->next : NULL;
1968ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    }
1969ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  else
1970ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    tmp = handler->next;
1971ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1972ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (tmp)
1973ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    handler_ref (tmp);
1974ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  handler_unref_R (signal_id, instance, handler);
1975ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  handler = tmp;
1976ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
1977ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      while (handler);
1978ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1979ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_STOP)
1980ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_CLEANUP;
1981ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      else if (emission_state == EMISSION_RESTART)
1982ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
1983ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
1984ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1985ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMIT_CLEANUP:
1986ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1987830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  ihint.run_type = G_SIGNAL_RUN_CLEANUP;
1988830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1989ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
1990ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    {
1991830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      gboolean need_unset = FALSE;
1992830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
1993ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      emission_state = EMISSION_STOP;
1994ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
1995ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_UNLOCK (g_signal_mutex);
1996ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (node->return_type != G_TYPE_NONE)
1997ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	{
1998ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  if (!accumulator)
1999830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    {
2000830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      g_value_init (&accu, node->return_type);
2001830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	      need_unset = TRUE;
2002830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik	    }
2003ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	  else if (accu_used)
2004ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	    g_value_reset (&accu);
2005ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	}
2006ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      g_closure_invoke (class_closure,
2007ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			node->return_type != G_TYPE_NONE ? &accu : NULL,
2008ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik			node->n_params + 1,
2009830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			instance_and_params,
2010830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik			&ihint);
2011830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik      if (need_unset)
2012ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	g_value_unset (&accu);
2013ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      G_LOCK (g_signal_mutex);
2014830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik
2015ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik      if (emission_state == EMISSION_RESTART)
2016ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik	goto EMIT_RESTART;
2017ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik    }
2018ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2019830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  if (handler_list)
2020830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik    handler_unref_R (signal_id, instance, handler_list);
2021ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik
2022830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik  emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state);
2023ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik  if (accumulator)
2024e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik    g_value_unset (&accu);
2025e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2026e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik  return return_value_altered;
2027ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}
2028e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2029e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik
2030e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik/* compile standard marshallers */
2031e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#include	"gvaluetypes.h"
2032e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#include        "gmarshal.c"
2033