gsignal.c revision 9490f8d7e435d60b76d5fca12ba6332a5f058fa5
1ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* GObject - GLib Type, Object, Parameter and Signal Library 237e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik * Copyright (C) 2000-2001 Red Hat, Inc. 3ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 4ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * This library is free software; you can redistribute it and/or 5ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * modify it under the terms of the GNU Lesser General Public 6ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * License as published by the Free Software Foundation; either 7ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * version 2 of the License, or (at your option) any later version. 8ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 9ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * This library is distributed in the hope that it will be useful, 10ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * but WITHOUT ANY WARRANTY; without even the implied warranty of 11ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Lesser General Public License for more details. 13ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 14ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * You should have received a copy of the GNU Lesser General 15ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Public License along with this library; if not, write to the 16ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Boston, MA 02111-1307, USA. 18ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 19ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * this code is based on the original GtkSignal implementation 20ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * for the Gtk+ library by Peter Mattis <petm@xcf.berkeley.edu> 21ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 22f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik 23f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik/* 24f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik * MT safe 25f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik */ 26fbe5df779cd39c9587f665118074ac828a805c26Owen Taylor 27ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#include "gsignal.h" 28ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#include "gbsearcharray.h" 29e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#include "gvaluecollector.h" 30617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik#include "gvaluetypes.h" 31617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik#include "gboxed.h" 32f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#include <string.h> 33ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 34ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 35ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* pre allocation configurations 36ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 37e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#define MAX_STACK_VALUES (16) 38ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define BSA_PRE_ALLOC (20) 39ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_PRE_ALLOC (48) 40ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define EMISSION_PRE_ALLOC (16) 41ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 42ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define REPORT_BUG "please report occourance circumstances to gtk-devel-list@gnome.org" 4322357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#ifdef G_ENABLE_DEBUG 4422357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#define IF_DEBUG(debug_type, cond) if ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || cond) 4522357542e9cb017e2dfeee0004d6a22ed8897468Tim Janikstatic volatile gpointer *g_trace_instance_signals = NULL; 4622357542e9cb017e2dfeee0004d6a22ed8897468Tim Janikstatic volatile gpointer *g_trap_instance_signals = NULL; 4722357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#endif /* G_ENABLE_DEBUG */ 48ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 49ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 50ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- generic allocation --- */ 51782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik/* we special case allocations generically by replacing 52ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * these functions with more speed/memory aware variants 53ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 54782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifndef DISABLE_MEM_POOLS 55ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline gpointer 56ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_generic_node_alloc (GTrashStack **trash_stack_p, 57ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint sizeof_node, 58ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint nodes_pre_alloc) 59ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 60ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer node = g_trash_stack_pop (trash_stack_p); 61ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 62ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!node) 63ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 64ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint8 *block; 65ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 66ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik nodes_pre_alloc = MAX (nodes_pre_alloc, 1); 67ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik block = g_malloc (sizeof_node * nodes_pre_alloc); 68ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik while (--nodes_pre_alloc) 69ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 70ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_trash_stack_push (trash_stack_p, block); 71ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik block += sizeof_node; 72ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 73ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node = block; 74ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 75ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 76ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return node; 77ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 78f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#define g_generic_node_free(trash_stack_p, node) g_trash_stack_push (trash_stack_p, node) 79782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#else /* !DISABLE_MEM_POOLS */ 80f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#define g_generic_node_alloc(t,sizeof_node,p) g_malloc (sizeof_node) 81f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik#define g_generic_node_free(t,node) g_free (node) 82782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#endif /* !DISABLE_MEM_POOLS */ 83ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 84ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 85ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- typedefs --- */ 8683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _SignalNode SignalNode; 8783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _SignalKey SignalKey; 8883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _Emission Emission; 8983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _Handler Handler; 9083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _HandlerList HandlerList; 9183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _HandlerMatch HandlerMatch; 92ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiktypedef enum 93ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 94ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMISSION_STOP, 95ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMISSION_RUN, 96ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMISSION_HOOK, 97ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMISSION_RESTART 98ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} EmissionState; 99ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 100ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 101ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- prototypes --- */ 10283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline guint signal_id_lookup (GQuark quark, 10383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GType itype); 10483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic void signal_destroy_R (SignalNode *signal_node); 10583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerList* handler_list_ensure (guint signal_id, 10683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance); 10783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerList* handler_list_lookup (guint signal_id, 10883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance); 10983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline Handler* handler_new (gboolean after); 11083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic void handler_insert (guint signal_id, 11183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance, 11283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik Handler *handler); 11383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic Handler* handler_lookup (gpointer instance, 11483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint handler_id, 11583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint *signal_id_p); 11683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch* handler_match_prepend (HandlerMatch *list, 11783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik Handler *handler, 11883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id); 11983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch* handler_match_free1_R (HandlerMatch *node, 12083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance); 12183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic HandlerMatch* handlers_find (gpointer instance, 12283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GSignalMatchType mask, 12383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id, 12483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GQuark detail, 12583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GClosure *closure, 12683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer func, 12783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer data, 12883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gboolean one_and_only); 12983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void handler_ref (Handler *handler); 13083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void handler_unref_R (guint signal_id, 13183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance, 13283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik Handler *handler); 13383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void emission_push (Emission **emission_list_p, 13483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id, 13583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GQuark detail, 13683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance, 13783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik EmissionState *state_p); 13883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void emission_pop (Emission **emission_list_p, 13983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik EmissionState *state_p); 14083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline Emission* emission_find (Emission *emission_list, 14183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id, 14283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GQuark detail, 14383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance); 144e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikstatic gboolean signal_emit_R (SignalNode *node, 14583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GQuark detail, 14683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance, 14783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GValue *return_value, 14883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik const GValue *instance_and_params); 149ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 150ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 151ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- structures --- */ 152617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janiktypedef struct 153617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{ 154617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GSignalAccumulator func; 155617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik gpointer data; 156617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik} SignalAccumulator; 1579490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janiktypedef struct 1589490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik{ 1599490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik GHook hook; 1609490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik GQuark detail; 1619490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik} SignalHook; 1629490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik#define SIGNAL_HOOK(hook) ((SignalHook*) (hook)) 1639490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik 164ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _SignalNode 165ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 166ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* permanent portion */ 167ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id; 168ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType itype; 169ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gchar *name; 170ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint destroyed : 1; 171ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 172ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* reinitializable portion */ 173ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint flags : 8; 174ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint n_params : 8; 175bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik GType *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */ 176bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik GType return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */ 177ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GClosure *class_closure; 178617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SignalAccumulator *accumulator; 179ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GSignalCMarshaller c_marshaller; 180ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GHookList *emission_hooks; 181ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}; 182ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 183ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _SignalKey 184ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 185ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType itype; 186ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GQuark quark; 187ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id; 188ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}; 189ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 190ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _Emission 191ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 192ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Emission *next; 193ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id; 194830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik GQuark detail; 195ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance; 196ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EmissionState *state_p; 197ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}; 198ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 199ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _HandlerList 200ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 201ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id; 202ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handlers; 203ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}; 204ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _Handler 205ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 206ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint id; 207ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *next; 208ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *prev; 209830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik GQuark detail; 210ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint ref_count : 16; 211ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_MAX_REF_COUNT (1 << 16) 212ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint block_count : 12; 213ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_MAX_BLOCK_COUNT (1 << 12) 214ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint after : 1; 215ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GClosure *closure; 216ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}; 21783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstruct _HandlerMatch 21883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{ 21983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik Handler *handler; 22083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik HandlerMatch *next; 22183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik union { 22283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id; 22383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer dummy; 22483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } d; 22583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik}; 226ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 227ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 228ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- variables --- */ 229ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GBSearchArray g_signal_key_bsa = { NULL, 0, 0, 0, NULL }; 230ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GHashTable *g_handler_list_bsa_ht = NULL; 231ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Emission *g_recursive_emissions = NULL; 232ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Emission *g_restart_emissions = NULL; 233ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GTrashStack *g_bsa_ts = NULL; 234ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GTrashStack *g_handler_ts = NULL; 235ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic GTrashStack *g_emission_ts = NULL; 236ee23c09e83d06a0d131ebd234c132f1c3602c019Tim JanikG_LOCK_DEFINE_STATIC (g_signal_mutex); 237ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 238ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 239ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- signal nodes --- */ 240ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic guint g_n_signal_nodes = 0; 241ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic SignalNode **g_signal_nodes = NULL; 242ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 243ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline SignalNode* 244ee23c09e83d06a0d131ebd234c132f1c3602c019Tim JanikLOOKUP_SIGNAL_NODE (register guint signal_id) 245ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 246ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (signal_id < g_n_signal_nodes) 247ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return g_signal_nodes[signal_id]; 248ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 249ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return NULL; 250ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 251ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 252ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 253ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- functions --- */ 254ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline guint 255ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_id_lookup (GQuark quark, 256ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType itype) 257ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 258e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GType *ifaces, type = itype; 259e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SignalKey key; 260e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint n_ifaces; 261e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 262e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik key.quark = quark; 263e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 264e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik /* try looking up signals for this type and its anchestors */ 2658a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik do 2668a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik { 267e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SignalKey *signal_key; 2688a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik 269e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik key.itype = type; 2708a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key); 2718a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik 2728a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik if (signal_key) 2738a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik return signal_key->signal_id; 2748a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik 275e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik type = g_type_parent (type); 2768a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik } 277e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik while (type); 278e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 279e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik /* no luck, try interfaces it exports */ 280e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik ifaces = g_type_interfaces (itype, &n_ifaces); 281e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik while (n_ifaces--) 282e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 283e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SignalKey *signal_key; 284e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 285e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik key.itype = ifaces[n_ifaces]; 286e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik signal_key = g_bsearch_array_lookup (&g_signal_key_bsa, &key); 287e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 288e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (signal_key) 289e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 290e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_free (ifaces); 291e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return signal_key->signal_id; 292e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 293e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 294e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_free (ifaces); 295ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2968a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik return 0; 297ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 298ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 299ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic gint 300ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_lists_cmp (gconstpointer node1, 301ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gconstpointer node2) 302ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 303ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik const HandlerList *hlist1 = node1, *hlist2 = node2; 304ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 305ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id); 306ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 307ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 308ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline HandlerList* 309ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_list_ensure (guint signal_id, 310ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance) 311ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 312ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 313ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList key; 314ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 315ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!hlbsa) 316ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 317ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlbsa = g_generic_node_alloc (&g_bsa_ts, 318ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik sizeof (GBSearchArray), 319ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik BSA_PRE_ALLOC); 320ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlbsa->cmp_func = handler_lists_cmp; 321ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlbsa->sizeof_node = sizeof (HandlerList); 322ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlbsa->flags = G_BSEARCH_DEFER_SHRINK; 323ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlbsa->n_nodes = 0; 324ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlbsa->nodes = NULL; 325ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa); 326ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 327ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.signal_id = signal_id; 328ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.handlers = NULL; 329ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 330ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return g_bsearch_array_insert (hlbsa, &key, FALSE); 331ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 332ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 333ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline HandlerList* 334ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_list_lookup (guint signal_id, 335ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance) 336ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 337ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 338ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList key; 339ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 340ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.signal_id = signal_id; 341ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 342ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return hlbsa ? g_bsearch_array_lookup (hlbsa, &key) : NULL; 343ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 344ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 345ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Handler* 346ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_lookup (gpointer instance, 347ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint handler_id, 348ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint *signal_id_p) 349ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 350ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 351ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 352ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (hlbsa) 353ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 354ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint i; 355ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 356ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (i = 0; i < hlbsa->n_nodes; i++) 357ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 358ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i); 359ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler; 360ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 361ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (handler = hlist->handlers; handler; handler = handler->next) 362ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler->id == handler_id) 363ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 364ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (signal_id_p) 365ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik *signal_id_p = hlist->signal_id; 366ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 367ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return handler; 368ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 369ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 370ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 371ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 372ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return NULL; 373ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 374ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 37583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch* 37683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandler_match_prepend (HandlerMatch *list, 37783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik Handler *handler, 37883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id) 37983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{ 38083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik HandlerMatch *node; 38183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 38283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik /* yeah, we could use our own memchunk here, introducing yet more 38383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * rarely used cached nodes and extra allocation overhead. 38483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * instead, we use GList* nodes, since they are exactly the size 38583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * we need and are already cached. g_signal_init() asserts this. 38683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik */ 38783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik node = (HandlerMatch*) g_list_alloc (); 38883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik node->handler = handler; 38983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik node->next = list; 39083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik node->d.signal_id = signal_id; 39183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik handler_ref (handler); 39283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 39383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return node; 39483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik} 39583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch* 39683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandler_match_free1_R (HandlerMatch *node, 39783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance) 39883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{ 39983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik HandlerMatch *next = node->next; 40083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 40183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik handler_unref_R (node->d.signal_id, instance, node->handler); 40283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik g_list_free_1 ((GList*) node); 40383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 40483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return next; 40583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik} 40683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 40783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic HandlerMatch* 40883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandlers_find (gpointer instance, 40983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GSignalMatchType mask, 41083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id, 41183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GQuark detail, 41283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GClosure *closure, 41383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer func, 41483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer data, 41583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gboolean one_and_only) 416ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 41783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik HandlerMatch *mlist = NULL; 41883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 419ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (mask & G_SIGNAL_MATCH_ID) 420ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 421ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList *hlist = handler_list_lookup (signal_id, instance); 422ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler; 423790a7bd3be608d9b12a18711d4400490d96b2a46Elliot Lee SignalNode *node = NULL; 424ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 42555ec7f32a6852dba73abb29e650615b66b065ef9Tim Janik if (mask & G_SIGNAL_MATCH_FUNC) 426ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 427ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 428ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!node || !node->c_marshaller) 429ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return NULL; 430ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 43183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 432ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik mask = ~mask; 433ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next) 43483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik if (handler->id && 43583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && 436830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && 437ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && 438830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && 439ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && 440ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->closure->meta_marshal == 0 && 441ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik ((GCClosure*) handler->closure)->callback == func))) 44283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik { 44383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik mlist = handler_match_prepend (mlist, handler, signal_id); 44483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik if (one_and_only) 44583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return mlist; 44683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 447ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 448ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 449ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 450ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 451ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 452ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik mask = ~mask; 453ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (hlbsa) 454ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 455ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint i; 456ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 457ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (i = 0; i < hlbsa->n_nodes; i++) 458ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 459ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i); 460790a7bd3be608d9b12a18711d4400490d96b2a46Elliot Lee SignalNode *node = NULL; 461ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler; 462ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 463ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!(mask & G_SIGNAL_MATCH_FUNC)) 464ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 465ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node = LOOKUP_SIGNAL_NODE (hlist->signal_id); 466ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!node->c_marshaller) 467ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik continue; 468ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 46983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 470ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (handler = hlist->handlers; handler; handler = handler->next) 47183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik if (handler->id && 47283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && 473830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && 474ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && 475830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && 476ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && 477ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->closure->meta_marshal == 0 && 478ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik ((GCClosure*) handler->closure)->callback == func))) 47983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik { 480a453526f350a3956a26f71db481bd8b436c65f97Owen Taylor mlist = handler_match_prepend (mlist, handler, hlist->signal_id); 48183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik if (one_and_only) 48283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return mlist; 48383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 484ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 485ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 486ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 487ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 48883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return mlist; 489ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 490ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 491ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline Handler* 492ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_new (gboolean after) 493ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 494ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik static guint handler_id = 1; 495ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler = g_generic_node_alloc (&g_handler_ts, 496ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik sizeof (Handler), 497ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HANDLER_PRE_ALLOC); 498ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#ifndef G_DISABLE_CHECKS 499ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler_id == 0) 500ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG); 501ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif 502ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 503ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->id = handler_id++; 504ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->prev = NULL; 505ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->next = NULL; 506830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik handler->detail = 0; 507ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->ref_count = 1; 508ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->block_count = 0; 509ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->after = after != FALSE; 510ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->closure = NULL; 511ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 512ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return handler; 513ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 514ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 515ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void 516ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_ref (Handler *handler) 517ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 518ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (handler->ref_count > 0); 519ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 520ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#ifndef G_DISABLE_CHECKS 521ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler->ref_count >= HANDLER_MAX_REF_COUNT - 1) 522ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_error (G_STRLOC ": handler ref_count overflow, %s", REPORT_BUG); 523ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif 524ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 525ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->ref_count += 1; 526ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 527ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 528ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void 529ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_unref_R (guint signal_id, 530ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance, 531ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler) 532ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 533ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (handler->ref_count > 0); 534ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 535ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->ref_count -= 1; 536ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!handler->ref_count) 537ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 538ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler->next) 539ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->next->prev = handler->prev; 54083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik if (handler->prev) /* watch out for g_signal_handlers_destroy()! */ 541ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->prev->next = handler->next; 542ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 543ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 544ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList *hlist = handler_list_lookup (signal_id, instance); 545ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 546ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlist->handlers = handler->next; 547ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 548ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 549ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_closure_unref (handler->closure); 550ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 551ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_generic_node_free (&g_handler_ts, handler); 552ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 553ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 554ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 555ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic void 556ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_insert (guint signal_id, 557ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance, 558ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler) 559ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 560ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList *hlist; 561ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 562e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */ 563ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 564ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlist = handler_list_ensure (signal_id, instance); 565ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!hlist->handlers) 566ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlist->handlers = handler; 567ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else if (hlist->handlers->after && !handler->after) 568ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 569ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->next = hlist->handlers; 570ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlist->handlers->prev = handler; 571ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlist->handlers = handler; 572ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 573ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 574ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 575ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *tmp = hlist->handlers; 576ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 577ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler->after) 578ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik while (tmp->next) 579ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp = tmp->next; 580ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 581ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik while (tmp->next && !tmp->next->after) 582ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp = tmp->next; 583ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (tmp->next) 584ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp->next->prev = handler; 585ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->next = tmp->next; 586ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->prev = tmp; 587ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp->next = handler; 588ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 589ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 590ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 591ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void 592ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikemission_push (Emission **emission_list_p, 593ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id, 594830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik GQuark detail, 595ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance, 596ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EmissionState *state_p) 597ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 598ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Emission *emission = g_generic_node_alloc (&g_emission_ts, 599ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik sizeof (Emission), 600ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMISSION_PRE_ALLOC); 601ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission->next = *emission_list_p; 602ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission->signal_id = signal_id; 603830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik emission->detail = detail; 604ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission->instance = instance; 605ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission->state_p = state_p; 606ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik *emission_list_p = emission; 607ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 608ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 609ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void 610830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janikemission_pop (Emission **emission_list_p, 611830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik EmissionState *state_p) 612ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 613830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik Emission **loc = emission_list_p, *emission = *loc; 61483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 615830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik while (emission->state_p != state_p) 616830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 617830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik loc = &emission->next; 618830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik emission = *loc; 619830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik } 620830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik *loc = emission->next; 621ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_generic_node_free (&g_emission_ts, emission); 622ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 623ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 624ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline Emission* 625ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikemission_find (Emission *emission_list, 626ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id, 627830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik GQuark detail, 628ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance) 629ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 630ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Emission *emission; 631ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 632ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (emission = emission_list; emission; emission = emission->next) 633830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (emission->instance == instance && 634830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik emission->signal_id == signal_id && 635830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik emission->detail == detail) 636ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return emission; 637ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return NULL; 638ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 639ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 640ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic gint 641ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_key_cmp (gconstpointer node1, 642ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gconstpointer node2) 643ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 644ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik const SignalKey *key1 = node1, *key2 = node2; 645ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 646ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (key1->itype == key2->itype) 647ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark); 648ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 649ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype); 650ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 651ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 652ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid 653ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_init (void) /* sync with gtype.c */ 654ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 655ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 656ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!g_n_signal_nodes) 657ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 65883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik /* handler_id_node_prepend() requires this */ 65983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik g_assert (sizeof (GList) == sizeof (HandlerMatch)); 66083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 661ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* setup signal key array */ 662ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_signal_key_bsa.cmp_func = signal_key_cmp; 663ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_signal_key_bsa.sizeof_node = sizeof (SignalKey); 664782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik g_signal_key_bsa.flags = G_BSEARCH_ALIGN_POWER2; /* alloc-only */ 665ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 666ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */ 667ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL); 668ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 669ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* invalid (0) signal_id */ 670ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_n_signal_nodes = 1; 671ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); 672ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_signal_nodes[0] = NULL; 673ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 674ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 675ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 676ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 677ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid 6783cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik_g_signals_destroy (GType itype) 679ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 680ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint i; 681ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 682ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 68383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik for (i = 1; i < g_n_signal_nodes; i++) 684ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 685ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode *node = g_signal_nodes[i]; 686ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 687ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node->itype == itype) 688ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 689ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node->destroyed) 690ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed", 691ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->name, 692ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_type_name (node->itype)); 693ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 694cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik signal_destroy_R (node); 695ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 696ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 697ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 698ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 699ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 700ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid 701ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_stop_emission (gpointer instance, 702830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik guint signal_id, 703830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik GQuark detail) 704ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 705ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode *node; 706ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 707ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 708ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (signal_id > 0); 709ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 710ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 711ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 712830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (node && detail && !(node->flags & G_SIGNAL_DETAILED)) 713830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 714830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 715830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik G_UNLOCK (g_signal_mutex); 716830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik return; 717830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik } 718e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 719ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 720ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions; 721830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik Emission *emission = emission_find (emission_list, signal_id, detail, instance); 722ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 723ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission) 724ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 725ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (*emission->state_p == EMISSION_HOOK) 726ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook", 727ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->name, instance); 728ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else if (*emission->state_p == EMISSION_RUN) 729ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik *emission->state_p = EMISSION_STOP; 730ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 731ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 732ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'", 733ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->name, instance); 734ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 735ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 736ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 737ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 738ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 739ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 740617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikstatic void 741617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janiksignal_finalize_hook (GHookList *hook_list, 742617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GHook *hook) 743617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{ 744617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GDestroyNotify destroy = hook->destroy; 745617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 746617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (destroy) 747617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 748617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik hook->destroy = NULL; 749617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik G_UNLOCK (g_signal_mutex); 750617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik destroy (hook->data); 751617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik G_LOCK (g_signal_mutex); 752617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 753617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik} 754617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 755617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikguint 756617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikg_signal_add_emission_hook (guint signal_id, 757617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GQuark detail, 758617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GSignalEmissionHook hook_func, 759617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik gpointer hook_data, 760617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GDestroyNotify data_destroy) 761617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{ 762617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik static guint seq_hook_id = 1; 763617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SignalNode *node; 764617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GHook *hook; 7659490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik SignalHook *signal_hook; 766617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 767617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_return_val_if_fail (signal_id > 0, 0); 768617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_return_val_if_fail (hook_func != NULL, 0); 769617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 770617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik G_LOCK (g_signal_mutex); 771617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 772617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (!node || node->destroyed || (node->flags & G_SIGNAL_NO_HOOKS)) 773617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 774617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id); 775617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik G_UNLOCK (g_signal_mutex); 776617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return 0; 777617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 778617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 779617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 780617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 781617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik G_UNLOCK (g_signal_mutex); 782617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return 0; 783617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 784617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (!node->emission_hooks) 785617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 786617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->emission_hooks = g_new (GHookList, 1); 7879490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik g_hook_list_init (node->emission_hooks, sizeof (SignalHook)); 788617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->emission_hooks->finalize_hook = signal_finalize_hook; 789617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 790617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik hook = g_hook_alloc (node->emission_hooks); 791617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik hook->data = hook_data; 792617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik hook->func = hook_func; 793617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik hook->destroy = data_destroy; 7949490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik signal_hook = SIGNAL_HOOK (hook); 7959490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik signal_hook->detail = detail; 796617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->emission_hooks->seq_id = seq_hook_id; 797617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_hook_append (node->emission_hooks, hook); 798617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik seq_hook_id = node->emission_hooks->seq_id; 799617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik G_UNLOCK (g_signal_mutex); 800617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 801617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return hook->hook_id; 802617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik} 803617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 804617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikvoid 805617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikg_signal_remove_emission_hook (guint signal_id, 806617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik guint hook_id) 807617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{ 808617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SignalNode *node; 809617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 810617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_return_if_fail (signal_id > 0); 811617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_return_if_fail (hook_id > 0); 812617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 813617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik G_LOCK (g_signal_mutex); 814617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 815617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (!node || node->destroyed) 816617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id); 817617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id)) 818617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_warning ("%s: signal \"%s\" had no hook (%u) to remove", G_STRLOC, node->name, hook_id); 819617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik G_UNLOCK (g_signal_mutex); 820617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik} 821617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 8223cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikstatic inline guint 8233cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janiksignal_parse_name (const gchar *name, 8243cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik GType itype, 8253cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik GQuark *detail_p, 8263cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik gboolean force_quark) 8273cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik{ 8283cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik const gchar *colon = strchr (name, ':'); 8293cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik guint signal_id; 8303cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 8313cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik if (!colon) 8323cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik { 8333cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik signal_id = signal_id_lookup (g_quark_try_string (name), itype); 8343cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik if (signal_id && detail_p) 8353cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik *detail_p = 0; 8363cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik } 8373cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik else if (colon[1] == ':') 8383cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik { 8393cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik gchar buffer[32]; 8403cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik guint l = colon - name; 8413cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 8423cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik if (l < 32) 8433cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik { 8443cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik memcpy (buffer, name, l); 8453cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik buffer[l] = 0; 8463cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik signal_id = signal_id_lookup (g_quark_try_string (buffer), itype); 8473cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik } 8483cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik else 8493cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik { 8503cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik gchar *signal = g_new (gchar, l + 1); 8513cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 8523cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik memcpy (signal, name, l); 8533cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik signal[l] = 0; 8543cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik signal_id = signal_id_lookup (g_quark_try_string (signal), itype); 8553cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik g_free (signal); 8563cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik } 8573cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 8583cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik if (signal_id && detail_p) 8593cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik *detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0; 8603cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik } 8613cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik else 8623cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik signal_id = 0; 8633cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik return signal_id; 8643cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik} 8653cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 8663cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikgboolean 8673cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikg_signal_parse_name (const gchar *detailed_signal, 8683cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik GType itype, 8693cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik guint *signal_id_p, 8703cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik GQuark *detail_p, 8713cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik gboolean force_detail_quark) 8723cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik{ 87337e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik SignalNode *node; 8743cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik GQuark detail = 0; 8753cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik guint signal_id; 87683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 8773cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik g_return_val_if_fail (detailed_signal != NULL, FALSE); 8783cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE); 87983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 8803cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik G_LOCK (g_signal_mutex); 8813cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark); 8823cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik G_UNLOCK (g_signal_mutex); 88337e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik 88437e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik node = signal_id ? LOOKUP_SIGNAL_NODE (signal_id) : NULL; 88537e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik if (!node || node->destroyed || 88637e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik (detail && !(node->flags & G_SIGNAL_DETAILED))) 8873cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik return FALSE; 88837e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik 88937e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik if (signal_id_p) 89037e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik *signal_id_p = signal_id; 89137e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik if (detail_p) 89237e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik *detail_p = detail; 89337e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik 89437e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik return TRUE; 8953cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik} 8963cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 897ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint 898ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_lookup (const gchar *name, 899ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType itype) 900ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 9018a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik guint signal_id; 9028a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik 903ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (name != NULL, 0); 904ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); 905ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 906ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 9078a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik signal_id = signal_id_lookup (g_quark_try_string (name), itype); 908ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 909ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 9108a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik return signal_id; 911ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 912ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 9131c391cc69846713b0406545146ea232efc5f34e2Havoc PenningtonG_CONST_RETURN gchar* 914ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_name (guint signal_id) 915ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 916ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode *node; 917ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gchar *name; 91883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 919ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 920ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 921ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik name = node ? node->name : NULL; 922ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 923ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 924ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return name; 925ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 926ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 927ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid 928ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_query (guint signal_id, 929ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GSignalQuery *query) 930ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 931ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode *node; 93283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 933ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (query != NULL); 93483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 935ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 936ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 937ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!node || node->destroyed) 938ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik query->signal_id = 0; 939ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 940ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 941ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik query->signal_id = node->signal_id; 942ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik query->signal_name = node->name; 943ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik query->itype = node->itype; 944ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik query->signal_flags = node->flags; 945ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik query->return_type = node->return_type; 946ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik query->n_params = node->n_params; 947ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik query->param_types = node->param_types; 948ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 949ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 950ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 951ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 95265c423b458d9fd1338cab0de7951092c09ab1686Tim Janikguint* 95365c423b458d9fd1338cab0de7951092c09ab1686Tim Janikg_signal_list_ids (GType itype, 95465c423b458d9fd1338cab0de7951092c09ab1686Tim Janik guint *n_ids) 955300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor{ 956300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor SignalKey *keys; 957300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor GArray *result; 95865c423b458d9fd1338cab0de7951092c09ab1686Tim Janik guint n_nodes; 95965c423b458d9fd1338cab0de7951092c09ab1686Tim Janik guint i; 96083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 961300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL); 96265c423b458d9fd1338cab0de7951092c09ab1686Tim Janik g_return_val_if_fail (n_ids != NULL, NULL); 96383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 96465c423b458d9fd1338cab0de7951092c09ab1686Tim Janik G_LOCK (g_signal_mutex); 96583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 966300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor keys = g_signal_key_bsa.nodes; 967300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor n_nodes = g_signal_key_bsa.n_nodes; 968300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor result = g_array_new (FALSE, FALSE, sizeof (guint)); 969300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor 970300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor for (i = 0; i < n_nodes; i++) 97165c423b458d9fd1338cab0de7951092c09ab1686Tim Janik if (keys[i].itype == itype) 97265c423b458d9fd1338cab0de7951092c09ab1686Tim Janik { 9731c391cc69846713b0406545146ea232efc5f34e2Havoc Pennington const gchar *name = g_quark_to_string (keys[i].quark); 97483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 97565c423b458d9fd1338cab0de7951092c09ab1686Tim Janik /* Signal names with "_" in them are aliases to the same 97665c423b458d9fd1338cab0de7951092c09ab1686Tim Janik * name with "-" instead of "_". 97765c423b458d9fd1338cab0de7951092c09ab1686Tim Janik */ 97865c423b458d9fd1338cab0de7951092c09ab1686Tim Janik if (!strchr (name, '_')) 97965c423b458d9fd1338cab0de7951092c09ab1686Tim Janik g_array_append_val (result, keys[i].signal_id); 98065c423b458d9fd1338cab0de7951092c09ab1686Tim Janik } 98183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 982300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor *n_ids = result->len; 98383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 98465c423b458d9fd1338cab0de7951092c09ab1686Tim Janik G_UNLOCK (g_signal_mutex); 98565c423b458d9fd1338cab0de7951092c09ab1686Tim Janik 986300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor return (guint *) g_array_free (result, FALSE); 987300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor} 988300e3bb247216fee40254822c2fb60a78a8ef21cOwen Taylor 989ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint 990b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Penningtong_signal_new_valist (const gchar *signal_name, 991b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington GType itype, 992b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington GSignalFlags signal_flags, 993b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington GClosure *class_closure, 994b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington GSignalAccumulator accumulator, 995617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik gpointer accu_data, 996b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington GSignalCMarshaller c_marshaller, 997b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington GType return_type, 998b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington guint n_params, 999b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington va_list args) 1000e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{ 1001e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GType *param_types; 1002e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint i; 1003e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint signal_id; 1004e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1005e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (n_params > 0) 1006e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1007e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik param_types = g_new (GType, n_params); 1008e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1009e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik for (i = 0; i < n_params; i++) 1010e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik param_types[i] = va_arg (args, GType); 1011e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1012e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 1013e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik param_types = NULL; 1014e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1015e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik signal_id = g_signal_newv (signal_name, itype, signal_flags, 1016617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik class_closure, accumulator, accu_data, c_marshaller, 1017e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return_type, n_params, param_types); 1018e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_free (param_types); 1019e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1020e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return signal_id; 1021e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik} 1022e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1023e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikguint 1024b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Penningtong_signal_newc (const gchar *signal_name, 1025b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington GType itype, 1026b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington GSignalFlags signal_flags, 1027b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington guint class_offset, 1028617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GSignalAccumulator accumulator, 1029617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik gpointer accu_data, 1030b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington GSignalCMarshaller c_marshaller, 1031b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington GType return_type, 1032b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington guint n_params, 1033b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington ...) 1034b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington{ 1035b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington va_list args; 1036b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington guint signal_id; 1037b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington 1038b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington g_return_val_if_fail (signal_name != NULL, 0); 1039b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington 1040b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington va_start (args, n_params); 1041b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington 1042b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington signal_id = g_signal_new_valist (signal_name, itype, signal_flags, 1043bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik g_signal_type_cclosure_new (itype, class_offset), 1044617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik accumulator, accu_data, c_marshaller, 1045b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington return_type, n_params, args); 1046b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington 1047b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington va_end (args); 1048b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington 1049b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington return signal_id; 1050b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington} 1051b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington 1052b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Penningtonguint 1053ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_newv (const gchar *signal_name, 1054ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType itype, 1055830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik GSignalFlags signal_flags, 1056ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GClosure *class_closure, 1057ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GSignalAccumulator accumulator, 1058617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik gpointer accu_data, 1059ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GSignalCMarshaller c_marshaller, 1060ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType return_type, 1061ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint n_params, 1062ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType *param_types) 1063ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1064ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gchar *name; 1065ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id, i; 1066ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode *node; 1067ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1068ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (signal_name != NULL, 0); 1069ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); 1070ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (n_params) 1071ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (param_types != NULL, 0); 1072617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 1073ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (accumulator == NULL, 0); 1074617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (!accumulator) 1075617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_return_val_if_fail (accu_data == NULL, 0); 1076617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 1077ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik name = g_strdup (signal_name); 1078ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_strdelimit (name, G_STR_DELIMITERS ":^", '_'); // FIXME do character checks like for types 1079ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1080ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 1081ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 10828a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik signal_id = signal_id_lookup (g_quark_try_string (name), itype); 1083ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 1084ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node && !node->destroyed) 1085ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1086ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s", 1087ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik name, 1088ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_type_name (node->itype), 1089ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry"); 1090ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_free (name); 1091ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1092ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return 0; 1093ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1094ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node && node->itype != itype) 1095ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1096ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'", 1097ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik name, 1098ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_type_name (itype), 1099ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_type_name (node->itype)); 1100ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_free (name); 1101ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1102ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return 0; 1103ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1104ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (i = 0; i < n_params; i++) 110537e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 1106ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1107ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type", 1108bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik i + 1, g_type_name (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE), g_type_name (itype), name); 1109ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_free (name); 1110ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1111ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return 0; 1112ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1113bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 1114ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1115ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type", 1116bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik g_type_name (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE), g_type_name (itype), name); 1117ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_free (name); 1118ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1119ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return 0; 1120ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1121ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1122ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* setup permanent portion of signal node */ 1123ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!node) 1124ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1125ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalKey key; 1126ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1127ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_id = g_n_signal_nodes++; 1128ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node = g_new (SignalNode, 1); 1129ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->signal_id = signal_id; 1130ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); 1131ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_signal_nodes[signal_id] = node; 1132ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->itype = itype; 1133ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->name = name; 1134ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.itype = itype; 1135ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.quark = g_quark_from_string (node->name); 1136ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.signal_id = signal_id; 1137ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE); 1138ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_strdelimit (node->name, "_", '-'); 1139ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.quark = g_quark_from_static_string (node->name); 1140ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_bsearch_array_insert (&g_signal_key_bsa, &key, FALSE); 1141ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1142ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->destroyed = FALSE; 1143ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1144ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* setup reinitializable portion */ 1145830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik node->flags = signal_flags & G_SIGNAL_FLAGS_MASK; 1146ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->n_params = n_params; 1147ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->param_types = g_memdup (param_types, sizeof (GType) * n_params); 1148ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->return_type = return_type; 1149ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->class_closure = class_closure ? g_closure_ref (class_closure) : NULL; 115012a0d19c11c29e3d4b7a5f02a07576309e2787a6Tim Janik if (class_closure) 115112a0d19c11c29e3d4b7a5f02a07576309e2787a6Tim Janik g_closure_sink (class_closure); 1152617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (accumulator) 1153617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 1154617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->accumulator = g_new (SignalAccumulator, 1); 1155617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->accumulator->func = accumulator; 1156617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->accumulator->data = accu_data; 1157617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 1158617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik else 1159617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->accumulator = NULL; 1160ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->c_marshaller = c_marshaller; 1161ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->emission_hooks = NULL; 1162ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node->c_marshaller && class_closure && G_CLOSURE_NEEDS_MARSHAL (class_closure)) 1163ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_closure_set_marshal (class_closure, node->c_marshaller); 1164ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1165ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return signal_id; 1166ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 1167ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1168ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic void 1169ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_destroy_R (SignalNode *signal_node) 1170ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1171ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode node = *signal_node; 1172ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1173ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_node->destroyed = TRUE; 1174ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1175ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* reentrancy caution, zero out real contents first */ 1176ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_node->n_params = 0; 1177ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_node->param_types = NULL; 1178ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_node->return_type = 0; 1179ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_node->class_closure = NULL; 1180ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_node->accumulator = NULL; 1181ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_node->c_marshaller = NULL; 1182ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_node->emission_hooks = NULL; 1183ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1184782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifdef G_ENABLE_DEBUG 1185ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* check current emissions */ 1186ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1187ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Emission *emission; 1188ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1189ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions; 1190ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission; emission = emission->next) 1191ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission->signal_id == node.signal_id) 1192ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')", 1193ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node.name, emission->instance); 1194ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1195ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif 1196ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1197ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* free contents that need to 1198ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 1199ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1200ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_free (node.param_types); 1201ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_closure_unref (node.class_closure); 1202617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_free (node.accumulator); 1203ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node.emission_hooks) 1204ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1205ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_hook_list_clear (node.emission_hooks); 1206ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_free (node.emission_hooks); 1207ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1208ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 1209ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 1210ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1211ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint 12123cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikg_signal_connect_closure_by_id (gpointer instance, 12133cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik guint signal_id, 12143cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik GQuark detail, 12153cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik GClosure *closure, 12163cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik gboolean after) 1217ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1218ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode *node; 1219ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint handler_id = 0; 1220ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1221ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1222ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (signal_id > 0, 0); 1223ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (closure != NULL, 0); 1224ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1225ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 1226ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 1227e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (node) 1228830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 1229e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 1230e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 1231e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 1232e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 1233e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 1234e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1235e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik Handler *handler = handler_new (after); 1236e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1237e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler_id = handler->id; 1238e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler->detail = detail; 1239e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler->closure = g_closure_ref (closure); 124012a0d19c11c29e3d4b7a5f02a07576309e2787a6Tim Janik g_closure_sink (closure); 1241e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler_insert (signal_id, instance, handler); 1242e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure)) 1243e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_closure_set_marshal (closure, node->c_marshaller); 1244e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1245ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1246ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 1247ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 1248ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1249ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1250ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return handler_id; 1251ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 1252ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1253e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikguint 1254e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_connect_closure (gpointer instance, 1255e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik const gchar *detailed_signal, 1256e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GClosure *closure, 1257e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik gboolean after) 1258e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{ 1259e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint signal_id, handler_id = 0; 1260e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GQuark detail = 0; 1261e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GType itype; 1262e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1263e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1264e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_val_if_fail (detailed_signal != NULL, 0); 1265e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_val_if_fail (closure != NULL, 0); 1266e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1267e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_LOCK (g_signal_mutex); 1268e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik itype = G_TYPE_FROM_INSTANCE (instance); 1269e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); 1270e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (signal_id) 1271e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1272e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 1273e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1274e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 1275e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); 1276e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else if (!g_type_is_a (itype, node->itype)) 1277e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1278e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 1279e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1280e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik Handler *handler = handler_new (after); 1281e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1282e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler_id = handler->id; 1283e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler->detail = detail; 1284e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler->closure = g_closure_ref (closure); 128512a0d19c11c29e3d4b7a5f02a07576309e2787a6Tim Janik g_closure_sink (closure); 1286e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler_insert (signal_id, instance, handler); 1287e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure)) 1288e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_closure_set_marshal (handler->closure, node->c_marshaller); 1289e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1290e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1291e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 1292e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1293e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_UNLOCK (g_signal_mutex); 1294e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1295e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return handler_id; 1296e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik} 1297e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1298e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikguint 1299e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_connect_data (gpointer instance, 1300e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik const gchar *detailed_signal, 1301e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GCallback c_handler, 1302e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik gpointer data, 1303e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GClosureNotify destroy_data, 1304e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik gboolean swapped, 1305e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik gboolean after) 1306e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{ 1307e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint signal_id, handler_id = 0; 1308e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GQuark detail = 0; 1309e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GType itype; 1310e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1311e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1312e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_val_if_fail (detailed_signal != NULL, 0); 1313e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_val_if_fail (c_handler != NULL, 0); 1314e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1315e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_LOCK (g_signal_mutex); 1316e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik itype = G_TYPE_FROM_INSTANCE (instance); 1317e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); 1318e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (signal_id) 1319e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1320e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 1321e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1322e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 1323e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); 1324e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else if (!g_type_is_a (itype, node->itype)) 1325e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1326e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 1327e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1328e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik Handler *handler = handler_new (after); 1329e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1330e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler_id = handler->id; 1331e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler->detail = detail; 1332e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data)); 133312a0d19c11c29e3d4b7a5f02a07576309e2787a6Tim Janik g_closure_sink (handler->closure); 1334e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler_insert (signal_id, instance, handler); 1335e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure)) 1336e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_closure_set_marshal (handler->closure, node->c_marshaller); 1337e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1338e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1339e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 1340e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1341e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_UNLOCK (g_signal_mutex); 1342e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1343e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return handler_id; 1344e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik} 1345e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1346ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid 1347cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_block (gpointer instance, 1348cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint handler_id) 1349cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{ 1350cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik Handler *handler; 1351cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 1352cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1353cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_if_fail (handler_id > 0); 1354cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 1355cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_LOCK (g_signal_mutex); 1356cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik handler = handler_lookup (instance, handler_id, NULL); 1357cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (handler) 1358cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik { 1359cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik#ifndef G_DISABLE_CHECKS 1360cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1) 1361cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG); 1362cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik#endif 1363cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 1364cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik handler->block_count += 1; 1365cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik } 1366cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik else 1367cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id); 1368cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_UNLOCK (g_signal_mutex); 1369cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik} 1370cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 1371cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikvoid 1372cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_unblock (gpointer instance, 1373cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint handler_id) 1374cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{ 1375cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik Handler *handler; 1376cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 1377cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1378cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_if_fail (handler_id > 0); 1379cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 1380cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_LOCK (g_signal_mutex); 1381cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik handler = handler_lookup (instance, handler_id, NULL); 1382cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (handler) 1383cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik { 1384cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (handler->block_count) 1385cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik handler->block_count -= 1; 1386cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik else 1387cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_warning (G_STRLOC ": handler `%u' of instance `%p' is not blocked", handler_id, instance); 1388cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik } 1389cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik else 1390cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id); 1391cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_UNLOCK (g_signal_mutex); 1392cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik} 1393cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 1394cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikvoid 1395ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_handler_disconnect (gpointer instance, 1396ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint handler_id) 1397ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1398ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler; 1399ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id; 1400ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1401ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1402ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (handler_id > 0); 1403ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1404ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 1405ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler = handler_lookup (instance, handler_id, &signal_id); 1406ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler) 1407ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1408ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->id = 0; 1409ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->block_count = 1; 1410ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_unref_R (signal_id, instance, handler); 1411ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1412ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 1413ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning ("%s: instance `%p' has no handler with id `%u'", G_STRLOC, instance, handler_id); 1414ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1415ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 1416ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1417ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid 141883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikg_signal_handlers_destroy (gpointer instance) 1419ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1420ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GBSearchArray *hlbsa; 1421ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1422ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1423ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1424ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 1425ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 1426ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (hlbsa) 1427ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1428ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint i; 1429ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1430ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* reentrancy caution, delete instance trace first */ 1431ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_hash_table_remove (g_handler_list_bsa_ht, instance); 143283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1433ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (i = 0; i < hlbsa->n_nodes; i++) 1434ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1435ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i); 1436ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler = hlist->handlers; 1437ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1438ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik while (handler) 1439ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1440ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *tmp = handler; 1441ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1442ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler = tmp->next; 1443ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp->block_count = 1; 1444ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* cruel unlink, this works because _all_ handlers vanish */ 1445ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp->next = NULL; 1446ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp->prev = tmp; 1447ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (tmp->id) 1448ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1449ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp->id = 0; 1450ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_unref_R (0, NULL, tmp); 1451ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1452ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1453ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1454ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_free (hlbsa->nodes); 1455ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_generic_node_free (&g_bsa_ts, hlbsa); 1456ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1457ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1458ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 1459ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1460cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint 1461cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_find (gpointer instance, 1462cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GSignalMatchType mask, 1463cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint signal_id, 1464cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GQuark detail, 1465cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GClosure *closure, 1466cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer func, 1467cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer data) 1468ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1469cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint handler_id = 0; 1470ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1471cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 1472cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); 147383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1474cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (mask & G_SIGNAL_MATCH_MASK) 1475ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 147683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik HandlerMatch *mlist; 147783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1478cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_LOCK (g_signal_mutex); 147983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE); 148083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik if (mlist) 148183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik { 148283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik handler_id = mlist->handler->id; 148383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik handler_match_free1_R (mlist, instance); 148483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 1485cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_UNLOCK (g_signal_mutex); 1486ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 148783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1488cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik return handler_id; 1489ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 1490ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1491cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikstatic guint 149283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiksignal_handlers_foreach_matched_R (gpointer instance, 149383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GSignalMatchType mask, 149483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id, 149583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GQuark detail, 149683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GClosure *closure, 149783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer func, 149883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer data, 149983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik void (*callback) (gpointer instance, 150083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint handler_id)) 1501ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 150283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik HandlerMatch *mlist; 1503cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint n_handlers = 0; 150483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 150583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE); 150683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik while (mlist) 1507ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1508cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik n_handlers++; 1509cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_UNLOCK (g_signal_mutex); 151083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik callback (instance, mlist->handler->id); 1511cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_LOCK (g_signal_mutex); 151283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik mlist = handler_match_free1_R (mlist, instance); 1513ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 151483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1515cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik return n_handlers; 1516ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 1517ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1518ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint 1519cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_block_matched (gpointer instance, 1520cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GSignalMatchType mask, 1521cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint signal_id, 1522cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GQuark detail, 1523cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GClosure *closure, 1524cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer func, 1525cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer data) 1526ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1527cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint n_handlers = 0; 152883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1529cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 1530cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE); 153183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1532cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 1533cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik { 1534cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_LOCK (g_signal_mutex); 153583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 153683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik closure, func, data, 153783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik g_signal_handler_block); 1538cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_UNLOCK (g_signal_mutex); 1539cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik } 154083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1541cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik return n_handlers; 1542cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik} 1543cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 1544cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint 1545cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_unblock_matched (gpointer instance, 1546cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GSignalMatchType mask, 1547cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint signal_id, 1548cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GQuark detail, 1549cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GClosure *closure, 1550cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer func, 1551cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer data) 1552cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{ 1553cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint n_handlers = 0; 1554ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1555cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 1556cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE); 1557ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1558cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 1559cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik { 1560cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_LOCK (g_signal_mutex); 156183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 156283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik closure, func, data, 156383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik g_signal_handler_unblock); 1564cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_UNLOCK (g_signal_mutex); 1565cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik } 156683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1567cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik return n_handlers; 1568cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik} 1569cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 1570cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint 1571cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_disconnect_matched (gpointer instance, 1572cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GSignalMatchType mask, 1573cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint signal_id, 1574cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GQuark detail, 1575cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GClosure *closure, 1576cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer func, 1577cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer data) 1578cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{ 1579cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint n_handlers = 0; 158083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1581cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 1582cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE); 158383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1584cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 1585cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik { 1586cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_LOCK (g_signal_mutex); 158783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 158883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik closure, func, data, 158983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik g_signal_handler_disconnect); 1590cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_UNLOCK (g_signal_mutex); 1591cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik } 159283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 1593cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik return n_handlers; 1594ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 1595ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1596ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikgboolean 1597cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_has_handler_pending (gpointer instance, 1598cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint signal_id, 1599cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GQuark detail, 1600cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gboolean may_be_blocked) 1601ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 160283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik HandlerMatch *mlist; 160383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gboolean has_pending; 1604ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1605ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 1606ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (signal_id > 0, FALSE); 1607ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1608ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 1609830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (detail) 1610830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 1611830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 1612830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 1613830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (!(node->flags & G_SIGNAL_DETAILED)) 1614830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 1615830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 1616830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik G_UNLOCK (g_signal_mutex); 1617830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik return FALSE; 1618830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik } 1619830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik } 162083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik mlist = handlers_find (instance, 162183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)), 162283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik signal_id, detail, NULL, NULL, NULL, TRUE); 162383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik if (mlist) 162483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik { 162583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik has_pending = TRUE; 162683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik handler_match_free1_R (mlist, instance); 162783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 162883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik else 162983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik has_pending = FALSE; 1630ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1631ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 163283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return has_pending; 1633ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 1634ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1635ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid 1636ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_emitv (const GValue *instance_and_params, 1637ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id, 1638830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik GQuark detail, 1639ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GValue *return_value) 1640ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1641ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik const GValue *param_values; 1642e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik gpointer instance; 1643e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SignalNode *node; 1644ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint i; 1645ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1646ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (instance_and_params != NULL); 164737e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik instance = g_value_peek_pointer (instance_and_params); 1648ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1649ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (signal_id > 0); 1650e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1651ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik param_values = instance_and_params + 1; 1652ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1653ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 1654ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 1655e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 1656cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik { 1657cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 1658cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik G_UNLOCK (g_signal_mutex); 1659cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik return; 1660cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik } 1661782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#ifdef G_ENABLE_DEBUG 1662830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 1663830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 1664830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 1665830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik G_UNLOCK (g_signal_mutex); 1666830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik return; 1667830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik } 1668ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (i = 0; i < node->n_params; i++) 166937e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik if (!G_TYPE_CHECK_VALUE_TYPE (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 1670ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1671e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'", 1672e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_STRLOC, 1673bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik g_type_name (node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE), 1674ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik i, 1675ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->name, 1676ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_VALUE_TYPE_NAME (param_values + i)); 1677ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1678ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return; 1679ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1680ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node->return_type != G_TYPE_NONE) 1681ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1682ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!return_value) 1683ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1684e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)", 1685e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_STRLOC, 1686bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik g_type_name (node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE), 1687ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->name); 1688ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1689ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return; 1690ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 169137e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik else if (!node->accumulator && !G_TYPE_CHECK_VALUE_TYPE (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 1692ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1693e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'", 1694e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_STRLOC, 1695bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik g_type_name (node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE), 1696ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->name, 1697ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_VALUE_TYPE_NAME (return_value)); 1698ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1699ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return; 1700ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1701ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1702ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 1703ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return_value = NULL; 1704782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik#endif /* G_ENABLE_DEBUG */ 1705e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1706830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik signal_emit_R (node, detail, instance, return_value, instance_and_params); 1707ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1708ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 1709ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1710e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid 1711e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit_valist (gpointer instance, 1712e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint signal_id, 1713e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GQuark detail, 1714e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik va_list var_args) 1715e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{ 1716e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GValue *instance_and_params, stack_values[MAX_STACK_VALUES], *free_me = NULL; 1717e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GValue *param_values; 1718e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SignalNode *node; 1719e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint i; 1720e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1721e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1722e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_if_fail (signal_id > 0); 1723e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1724e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_LOCK (g_signal_mutex); 1725e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 1726e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 1727e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1728e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 1729e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_UNLOCK (g_signal_mutex); 1730e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return; 1731e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1732e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#ifndef G_DISABLE_CHECKS 1733e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 1734e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1735e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 1736e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_UNLOCK (g_signal_mutex); 1737e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return; 1738e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1739e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#endif /* !G_DISABLE_CHECKS */ 1740e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1741e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (node->n_params < MAX_STACK_VALUES) 1742e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik instance_and_params = stack_values; 1743e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 1744e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1745e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik free_me = g_new (GValue, node->n_params + 1); 1746e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik instance_and_params = free_me; 1747e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1748e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik param_values = instance_and_params + 1; 1749e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik for (i = 0; i < node->n_params; i++) 1750e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1751e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik gchar *error; 1752e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1753e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik param_values[i].g_type = 0; 1754bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik g_value_init (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE); 1755bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik G_VALUE_COLLECT (param_values + i, 1756bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik var_args, 1757bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE ? G_VALUE_NOCOPY_CONTENTS : 0, 1758bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik &error); 1759e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (error) 1760e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1761e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: %s", G_STRLOC, error); 1762e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_free (error); 1763e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1764e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik /* we purposely leak the value here, it might not be 1765e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * in a sane state if an error condition occoured 1766e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik */ 1767e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik while (i--) 1768e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_value_unset (param_values + i); 1769e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1770e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_UNLOCK (g_signal_mutex); 1771e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_free (free_me); 1772e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return; 1773e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1774e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1775e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik instance_and_params->g_type = 0; 1776f3ec41e8d22b5fa99b93ea753acb0de873732e94Jonathan Blandford g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (instance)); 1777e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_value_set_instance (instance_and_params, instance); 1778e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (node->return_type == G_TYPE_NONE) 1779e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik signal_emit_R (node, detail, instance, NULL, instance_and_params); 1780e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 1781e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1782e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GValue return_value = { 0, }; 1783e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik gchar *error = NULL; 1784e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1785bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik g_value_init (&return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); 1786e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (signal_emit_R (node, detail, instance, &return_value, instance_and_params)) 1787bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik G_VALUE_LCOPY (&return_value, 1788bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik var_args, 1789bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik node->return_type & G_SIGNAL_TYPE_STATIC_SCOPE ? G_VALUE_NOCOPY_CONTENTS : 0, 1790bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik &error); 1791e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (!error) 1792e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_value_unset (&return_value); 1793e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 1794e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1795e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: %s", G_STRLOC, error); 1796e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_free (error); 1797e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1798e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik /* we purposely leak the value here, it might not be 1799e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * in a sane state if an error condition occoured 1800e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik */ 1801e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1802e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1803e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik for (i = 0; i < node->n_params; i++) 1804e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_value_unset (param_values + i); 1805e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_value_unset (instance_and_params); 1806e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (free_me) 1807e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_free (free_me); 1808e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_UNLOCK (g_signal_mutex); 1809e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik} 1810e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1811e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid 1812e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit (gpointer instance, 1813e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint signal_id, 1814e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GQuark detail, 1815e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik ...) 1816e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{ 1817e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik va_list var_args; 1818e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1819e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik va_start (var_args, detail); 1820e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_signal_emit_valist (instance, signal_id, detail, var_args); 1821e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik va_end (var_args); 1822e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik} 1823e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1824e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid 1825e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit_by_name (gpointer instance, 1826e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik const gchar *detailed_signal, 1827e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik ...) 1828e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{ 1829e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GQuark detail = 0; 1830e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint signal_id; 1831e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1832e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1833e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_if_fail (detailed_signal != NULL); 1834e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1835e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_LOCK (g_signal_mutex); 1836e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE); 1837e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_UNLOCK (g_signal_mutex); 1838e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1839e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (signal_id) 1840e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 1841e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik va_list var_args; 1842e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1843e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik va_start (var_args, detailed_signal); 1844e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_signal_emit_valist (instance, signal_id, detail, var_args); 1845e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik va_end (var_args); 1846e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 1847e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 1848e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1849e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik} 1850e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 1851617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikstatic inline gboolean 1852617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikaccumulate (GSignalInvocationHint *ihint, 1853617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GValue *return_accu, 1854617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GValue *handler_return, 1855617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SignalAccumulator *accumulator) 1856617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{ 1857617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik gboolean continue_emission; 1858617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 1859617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (!accumulator) 1860617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return TRUE; 1861617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 1862617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data); 1863617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_value_reset (handler_return); 1864617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 1865617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return continue_emission; 1866617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik} 1867617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 1868e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikstatic gboolean 1869ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_emit_R (SignalNode *node, 1870830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik GQuark detail, 1871ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance, 1872617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GValue *emission_return, 1873ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik const GValue *instance_and_params) 1874ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1875ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EmissionState emission_state = 0; 1876617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SignalAccumulator *accumulator; 1877830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik GSignalInvocationHint ihint; 1878ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GClosure *class_closure; 1879ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList *hlist; 1880830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik Handler *handler_list = NULL; 1881617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GValue *return_accu, accu = { 0, }; 1882ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id = node->signal_id; 1883e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik gboolean return_value_altered = FALSE; 1884ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 188522357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#ifdef G_ENABLE_DEBUG 188622357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik IF_DEBUG (SIGNALS, g_trace_instance_signals == instance || g_trap_instance_signals == instance) 188722357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik { 188822357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik g_message ("%s::%s(%u) emitted (instance=%p signal-node=%p)\n", 188922357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik g_type_name (G_TYPE_FROM_INSTANCE (instance)), 189022357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik node->name, detail, 189122357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik instance, node); 189222357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik if (g_trap_instance_signals == instance) 189322357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik G_BREAKPOINT (); 189422357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik } 189522357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#endif /* G_ENABLE_DEBUG */ 189622357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik 1897ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node->flags & G_SIGNAL_NO_RECURSE) 1898ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1899830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik Emission *emission = emission_find (g_restart_emissions, signal_id, detail, instance); 1900ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1901ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission) 1902ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1903ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik *emission->state_p = EMISSION_RESTART; 1904e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return return_value_altered; 1905ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1906ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1907830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik ihint.signal_id = node->signal_id; 1908830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik ihint.detail = detail; 1909ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik accumulator = node->accumulator; 1910ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (accumulator) 1911617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 1912617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); 1913617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return_accu = &accu; 1914617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 1915617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik else 1916617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return_accu = emission_return; 1917ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, 1918830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik signal_id, detail, instance, &emission_state); 1919ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik class_closure = node->class_closure; 1920ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1921ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMIT_RESTART: 1922ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1923830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (handler_list) 1924830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik handler_unref_R (signal_id, instance, handler_list); 1925830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik hlist = handler_list_lookup (signal_id, instance); 1926830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik handler_list = hlist ? hlist->handlers : NULL; 1927830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (handler_list) 1928830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik handler_ref (handler_list); 1929830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 1930830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik ihint.run_type = G_SIGNAL_RUN_FIRST; 1931830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 1932ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure) 1933ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1934ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission_state = EMISSION_RUN; 1935ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1936ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 1937617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_closure_invoke (class_closure, 1938617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return_accu, 1939617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->n_params + 1, 1940617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik instance_and_params, 1941617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik &ihint); 1942617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (!accumulate (&ihint, emission_return, &accu, accumulator) && 1943617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission_state == EMISSION_RUN) 1944617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission_state = EMISSION_STOP; 1945ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 1946e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return_value_altered = TRUE; 1947ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1948ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission_state == EMISSION_STOP) 1949ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_CLEANUP; 1950ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else if (emission_state == EMISSION_RESTART) 1951ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_RESTART; 1952ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1953ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1954ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node->emission_hooks) 1955ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1956617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik gboolean need_destroy, was_in_call, may_recurse = TRUE; 1957617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GHook *hook; 19589490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik 1959617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission_state = EMISSION_HOOK; 1960617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik hook = g_hook_first_valid (node->emission_hooks, may_recurse); 1961617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik while (hook) 1962617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 19639490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik SignalHook *signal_hook = SIGNAL_HOOK (hook); 1964617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 19659490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik if (!signal_hook->detail || signal_hook->detail == detail) 1966617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 1967617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GSignalEmissionHook hook_func = hook->func; 1968617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 1969617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik was_in_call = G_HOOK_IN_CALL (hook); 1970617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik hook->flags |= G_HOOK_FLAG_IN_CALL; 1971617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik G_UNLOCK (g_signal_mutex); 1972617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik need_destroy = !hook_func (&ihint, node->n_params + 1, instance_and_params, hook->data); 1973617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik G_LOCK (g_signal_mutex); 1974617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (!was_in_call) 1975617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik hook->flags &= ~G_HOOK_FLAG_IN_CALL; 1976617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (need_destroy) 1977617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_hook_destroy_link (node->emission_hooks, hook); 1978617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 1979617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse); 1980617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 1981ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1982ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission_state == EMISSION_RESTART) 1983ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_RESTART; 1984ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1985ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1986830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (handler_list) 1987ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1988830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik Handler *handler = handler_list; 1989ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1990ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission_state = EMISSION_RUN; 1991ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_ref (handler); 1992ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik do 1993ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1994ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *tmp; 1995ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1996830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (handler->after) 1997830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 1998830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik handler_unref_R (signal_id, instance, handler_list); 1999830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik handler_list = handler; 2000830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik break; 2001830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik } 2002830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik else if (!handler->block_count && (!handler->detail || handler->detail == detail)) 2003ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 2004ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 2005617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_closure_invoke (handler->closure, 2006617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return_accu, 2007617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->n_params + 1, 2008617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik instance_and_params, 2009617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik &ihint); 2010617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (!accumulate (&ihint, emission_return, &accu, accumulator) && 2011617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission_state == EMISSION_RUN) 2012617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission_state = EMISSION_STOP; 2013ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 2014e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return_value_altered = TRUE; 2015ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2016ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp = emission_state == EMISSION_RUN ? handler->next : NULL; 2017ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 2018ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 2019ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp = handler->next; 2020ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2021ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (tmp) 2022ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_ref (tmp); 2023830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik handler_unref_R (signal_id, instance, handler_list); 2024830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik handler_list = handler; 2025ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler = tmp; 2026ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 2027ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik while (handler); 2028ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2029ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission_state == EMISSION_STOP) 2030ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_CLEANUP; 2031ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else if (emission_state == EMISSION_RESTART) 2032ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_RESTART; 2033ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 2034ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2035830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik ihint.run_type = G_SIGNAL_RUN_LAST; 2036830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 2037ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure) 2038ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 2039ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission_state = EMISSION_RUN; 2040ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2041ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 2042617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_closure_invoke (class_closure, 2043617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return_accu, 2044617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->n_params + 1, 2045617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik instance_and_params, 2046617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik &ihint); 2047617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (!accumulate (&ihint, emission_return, &accu, accumulator) && 2048617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission_state == EMISSION_RUN) 2049617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission_state = EMISSION_STOP; 2050ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 2051e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return_value_altered = TRUE; 2052ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2053ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission_state == EMISSION_STOP) 2054ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_CLEANUP; 2055ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else if (emission_state == EMISSION_RESTART) 2056ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_RESTART; 2057ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 2058ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2059830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (handler_list) 2060ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 2061830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik Handler *handler = handler_list; 2062ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2063ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission_state = EMISSION_RUN; 2064ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_ref (handler); 2065ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik do 2066ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 2067ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *tmp; 2068ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2069830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail)) 2070ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 2071ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 2072617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_closure_invoke (handler->closure, 2073617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return_accu, 2074617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->n_params + 1, 2075617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik instance_and_params, 2076617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik &ihint); 2077617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (!accumulate (&ihint, emission_return, &accu, accumulator) && 2078617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission_state == EMISSION_RUN) 2079617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission_state = EMISSION_STOP; 2080ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 2081e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return_value_altered = TRUE; 2082ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2083ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp = emission_state == EMISSION_RUN ? handler->next : NULL; 2084ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 2085ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 2086ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp = handler->next; 2087ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2088ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (tmp) 2089ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_ref (tmp); 2090ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_unref_R (signal_id, instance, handler); 2091ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler = tmp; 2092ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 2093ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik while (handler); 2094ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2095ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission_state == EMISSION_STOP) 2096ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_CLEANUP; 2097ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else if (emission_state == EMISSION_RESTART) 2098ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_RESTART; 2099ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 2100ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2101ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMIT_CLEANUP: 2102ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2103830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik ihint.run_type = G_SIGNAL_RUN_CLEANUP; 2104830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 2105ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure) 2106ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 2107830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik gboolean need_unset = FALSE; 2108830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 2109ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission_state = EMISSION_STOP; 2110ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2111ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_UNLOCK (g_signal_mutex); 2112617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (node->return_type != G_TYPE_NONE && !accumulator) 2113ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 2114617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); 2115617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik need_unset = TRUE; 2116ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 2117ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_closure_invoke (class_closure, 2118ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->return_type != G_TYPE_NONE ? &accu : NULL, 2119ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->n_params + 1, 2120830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik instance_and_params, 2121830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik &ihint); 2122830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (need_unset) 2123ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_value_unset (&accu); 2124ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_LOCK (g_signal_mutex); 2125830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 2126ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission_state == EMISSION_RESTART) 2127ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_RESTART; 2128ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 2129ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2130830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (handler_list) 2131830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik handler_unref_R (signal_id, instance, handler_list); 2132ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2133830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission_state); 2134ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (accumulator) 2135e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_value_unset (&accu); 2136617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 2137e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return return_value_altered; 2138ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 2139e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2140e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2141f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik/* --- compile standard marshallers --- */ 214237e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik#include "gobject.h" 214337e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik#include "genums.h" 2144e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#include "gmarshal.c" 2145