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