LCOV - code coverage report
Current view: top level - glib/gobject - gsignal.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 1308 1494 87.6 %
Date: 2024-04-23 05:16:05 Functions: 82 85 96.5 %
Branches: 703 1020 68.9 %

           Branch data     Line data    Source code
       1                 :            : /* GObject - GLib Type, Object, Parameter and Signal Library
       2                 :            :  * Copyright (C) 2000-2001 Red Hat, Inc.
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: LGPL-2.1-or-later
       5                 :            :  *
       6                 :            :  * This library is free software; you can redistribute it and/or
       7                 :            :  * modify it under the terms of the GNU Lesser General Public
       8                 :            :  * License as published by the Free Software Foundation; either
       9                 :            :  * version 2.1 of the License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This library is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14                 :            :  * Lesser General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU Lesser General
      17                 :            :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18                 :            :  *
      19                 :            :  * this code is based on the original GtkSignal implementation
      20                 :            :  * for the Gtk+ library by Peter Mattis <petm@xcf.berkeley.edu>
      21                 :            :  */
      22                 :            : 
      23                 :            : /*
      24                 :            :  * MT safe
      25                 :            :  */
      26                 :            : 
      27                 :            : #include "config.h"
      28                 :            : 
      29                 :            : #include <string.h>
      30                 :            : #include <signal.h>
      31                 :            : 
      32                 :            : #include "gsignal.h"
      33                 :            : #include "gtype-private.h"
      34                 :            : #include "gbsearcharray.h"
      35                 :            : #include "gvaluecollector.h"
      36                 :            : #include "gvaluetypes.h"
      37                 :            : #include "gobject.h"
      38                 :            : #include "genums.h"
      39                 :            : #include "gobject_trace.h"
      40                 :            : 
      41                 :            : 
      42                 :            : #define REPORT_BUG      "please report occurrence circumstances to https://gitlab.gnome.org/GNOME/glib/issues/new"
      43                 :            : 
      44                 :            : /* --- typedefs --- */
      45                 :            : typedef struct _SignalNode   SignalNode;
      46                 :            : typedef struct _SignalKey    SignalKey;
      47                 :            : typedef struct _Emission     Emission;
      48                 :            : typedef struct _Handler      Handler;
      49                 :            : typedef struct _HandlerList  HandlerList;
      50                 :            : typedef struct _HandlerMatch HandlerMatch;
      51                 :            : typedef enum
      52                 :            : {
      53                 :            :   EMISSION_STOP,
      54                 :            :   EMISSION_RUN,
      55                 :            :   EMISSION_HOOK,
      56                 :            :   EMISSION_RESTART
      57                 :            : } EmissionState;
      58                 :            : 
      59                 :            : 
      60                 :            : /* --- prototypes --- */
      61                 :            : static inline guint   signal_id_lookup  (const gchar *name,
      62                 :            :                                          GType        itype);
      63                 :            : static        void              signal_destroy_R        (SignalNode      *signal_node);
      64                 :            : static inline HandlerList*      handler_list_ensure     (guint            signal_id,
      65                 :            :                                                          gpointer         instance);
      66                 :            : static inline HandlerList*      handler_list_lookup     (guint            signal_id,
      67                 :            :                                                          gpointer         instance);
      68                 :            : static inline Handler*          handler_new             (guint            signal_id,
      69                 :            :                                                          gpointer         instance,
      70                 :            :                                                          gboolean         after);
      71                 :            : static        void              handler_insert          (guint            signal_id,
      72                 :            :                                                          gpointer         instance,
      73                 :            :                                                          Handler         *handler);
      74                 :            : static        Handler*          handler_lookup          (gpointer         instance,
      75                 :            :                                                          gulong           handler_id,
      76                 :            :                                                          GClosure        *closure,
      77                 :            :                                                          guint           *signal_id_p);
      78                 :            : static inline HandlerMatch*     handler_match_prepend   (HandlerMatch    *list,
      79                 :            :                                                          Handler         *handler,
      80                 :            :                                                          guint            signal_id);
      81                 :            : static inline HandlerMatch*     handler_match_free1_R   (HandlerMatch    *node,
      82                 :            :                                                          gpointer         instance);
      83                 :            : static        HandlerMatch*     handlers_find           (gpointer         instance,
      84                 :            :                                                          GSignalMatchType mask,
      85                 :            :                                                          guint            signal_id,
      86                 :            :                                                          GQuark           detail,
      87                 :            :                                                          GClosure        *closure,
      88                 :            :                                                          gpointer         func,
      89                 :            :                                                          gpointer         data,
      90                 :            :                                                          gboolean         one_and_only);
      91                 :            : static inline void              handler_ref             (Handler         *handler);
      92                 :            : static inline void              handler_unref_R         (guint            signal_id,
      93                 :            :                                                          gpointer         instance,
      94                 :            :                                                          Handler         *handler);
      95                 :            : static gint                     handler_lists_cmp       (gconstpointer    node1,
      96                 :            :                                                          gconstpointer    node2);
      97                 :            : static inline void              emission_push           (Emission        *emission);
      98                 :            : static inline void              emission_pop            (Emission        *emission);
      99                 :            : static inline Emission*         emission_find           (guint            signal_id,
     100                 :            :                                                          GQuark           detail,
     101                 :            :                                                          gpointer         instance);
     102                 :            : static gint                     class_closures_cmp      (gconstpointer    node1,
     103                 :            :                                                          gconstpointer    node2);
     104                 :            : static gint                     signal_key_cmp          (gconstpointer    node1,
     105                 :            :                                                          gconstpointer    node2);
     106                 :            : static        gboolean          signal_emit_unlocked_R  (SignalNode      *node,
     107                 :            :                                                          GQuark           detail,
     108                 :            :                                                          gpointer         instance,
     109                 :            :                                                          GValue          *return_value,
     110                 :            :                                                          const GValue    *instance_and_params);
     111                 :            : static       void               add_invalid_closure_notify    (Handler         *handler,
     112                 :            :                                                                gpointer         instance);
     113                 :            : static       void               remove_invalid_closure_notify (Handler         *handler,
     114                 :            :                                                                gpointer         instance);
     115                 :            : static       void               invalid_closure_notify  (gpointer         data,
     116                 :            :                                                          GClosure        *closure);
     117                 :            : static const gchar *            type_debug_name         (GType            type);
     118                 :            : static void                     node_check_deprecated   (const SignalNode *node);
     119                 :            : static void                     node_update_single_va_closure (SignalNode *node);
     120                 :            : 
     121                 :            : 
     122                 :            : /* --- structures --- */
     123                 :            : typedef struct
     124                 :            : {
     125                 :            :   GSignalAccumulator func;
     126                 :            :   gpointer           data;
     127                 :            : } SignalAccumulator;
     128                 :            : typedef struct
     129                 :            : {
     130                 :            :   GHook hook;
     131                 :            :   GQuark detail;
     132                 :            : } SignalHook;
     133                 :            : #define SIGNAL_HOOK(hook)       ((SignalHook*) (hook))
     134                 :            : 
     135                 :            : struct _SignalNode
     136                 :            : {
     137                 :            :   /* permanent portion */
     138                 :            :   guint              signal_id;
     139                 :            :   GType              itype;
     140                 :            :   const gchar       *name;
     141                 :            :   guint              destroyed : 1;
     142                 :            :   
     143                 :            :   /* reinitializable portion */
     144                 :            :   guint              flags : 9;
     145                 :            :   guint              n_params : 8;
     146                 :            :   guint              single_va_closure_is_valid : 1;
     147                 :            :   guint              single_va_closure_is_after : 1;
     148                 :            :   GType             *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
     149                 :            :   GType              return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
     150                 :            :   GBSearchArray     *class_closure_bsa;
     151                 :            :   SignalAccumulator *accumulator;
     152                 :            :   GSignalCMarshaller c_marshaller;
     153                 :            :   GSignalCVaMarshaller va_marshaller;
     154                 :            :   GHookList         *emission_hooks;
     155                 :            : 
     156                 :            :   GClosure *single_va_closure;
     157                 :            : };
     158                 :            : 
     159                 :            : #define SINGLE_VA_CLOSURE_EMPTY_MAGIC GINT_TO_POINTER(1)        /* indicates single_va_closure is valid but empty */
     160                 :            : 
     161                 :            : struct _SignalKey
     162                 :            : {
     163                 :            :   GType  itype;
     164                 :            :   GQuark quark;
     165                 :            :   guint  signal_id;
     166                 :            : };
     167                 :            : 
     168                 :            : struct _Emission
     169                 :            : {
     170                 :            :   Emission             *next;
     171                 :            :   gpointer              instance;
     172                 :            :   GSignalInvocationHint ihint;
     173                 :            :   EmissionState         state;
     174                 :            :   GType                 chain_type;
     175                 :            : };
     176                 :            : 
     177                 :            : struct _HandlerList
     178                 :            : {
     179                 :            :   guint    signal_id;
     180                 :            :   Handler *handlers;
     181                 :            :   Handler *tail_before;  /* normal signal handlers are appended here  */
     182                 :            :   Handler *tail_after;   /* CONNECT_AFTER handlers are appended here  */
     183                 :            : };
     184                 :            : 
     185                 :            : struct _Handler
     186                 :            : {
     187                 :            :   gulong        sequential_number;
     188                 :            :   Handler      *next;
     189                 :            :   Handler      *prev;
     190                 :            :   GQuark        detail;
     191                 :            :   guint         signal_id;
     192                 :            :   guint         ref_count;
     193                 :            :   guint         block_count : 16;
     194                 :            : #define HANDLER_MAX_BLOCK_COUNT (1 << 16)
     195                 :            :   guint         after : 1;
     196                 :            :   guint         has_invalid_closure_notify : 1;
     197                 :            :   GClosure     *closure;
     198                 :            :   gpointer      instance;
     199                 :            : };
     200                 :            : struct _HandlerMatch
     201                 :            : {
     202                 :            :   Handler      *handler;
     203                 :            :   HandlerMatch *next;
     204                 :            :   guint         signal_id;
     205                 :            : };
     206                 :            : 
     207                 :            : typedef struct
     208                 :            : {
     209                 :            :   GType     instance_type; /* 0 for default closure */
     210                 :            :   GClosure *closure;
     211                 :            : } ClassClosure;
     212                 :            : 
     213                 :            : 
     214                 :            : /* --- variables --- */
     215                 :            : static GBSearchArray *g_signal_key_bsa = NULL;
     216                 :            : static const GBSearchConfig g_signal_key_bconfig = {
     217                 :            :   sizeof (SignalKey),
     218                 :            :   signal_key_cmp,
     219                 :            :   G_BSEARCH_ARRAY_ALIGN_POWER2,
     220                 :            : };
     221                 :            : static GBSearchConfig g_signal_hlbsa_bconfig = {
     222                 :            :   sizeof (HandlerList),
     223                 :            :   handler_lists_cmp,
     224                 :            :   0,
     225                 :            : };
     226                 :            : static GBSearchConfig g_class_closure_bconfig = {
     227                 :            :   sizeof (ClassClosure),
     228                 :            :   class_closures_cmp,
     229                 :            :   0,
     230                 :            : };
     231                 :            : static GHashTable    *g_handler_list_bsa_ht = NULL;
     232                 :            : static Emission      *g_emissions = NULL;
     233                 :            : static gulong         g_handler_sequential_number = 1;
     234                 :            : static GHashTable    *g_handlers = NULL;
     235                 :            : 
     236                 :            : G_LOCK_DEFINE_STATIC (g_signal_mutex);
     237                 :            : #define SIGNAL_LOCK()           G_LOCK (g_signal_mutex)
     238                 :            : #define SIGNAL_UNLOCK()         G_UNLOCK (g_signal_mutex)
     239                 :            : 
     240                 :            : 
     241                 :            : /* --- signal nodes --- */
     242                 :            : static guint          g_n_signal_nodes = 0;
     243                 :            : static SignalNode   **g_signal_nodes = NULL;
     244                 :            : 
     245                 :            : static inline SignalNode*
     246                 :   39022703 : LOOKUP_SIGNAL_NODE (guint signal_id)
     247                 :            : {
     248         [ +  - ]:   39022703 :   if (signal_id < g_n_signal_nodes)
     249                 :   39022703 :     return g_signal_nodes[signal_id];
     250                 :            :   else
     251                 :          0 :     return NULL;
     252                 :            : }
     253                 :            : 
     254                 :            : 
     255                 :            : /* --- functions --- */
     256                 :            : /* @key must have already been validated with is_valid()
     257                 :            :  * Modifies @key in place. */
     258                 :            : static void
     259                 :          4 : canonicalize_key (gchar *key)
     260                 :            : {
     261                 :            :   gchar *p;
     262                 :            : 
     263         [ +  + ]:         49 :   for (p = key; *p != 0; p++)
     264                 :            :     {
     265                 :         45 :       gchar c = *p;
     266                 :            : 
     267         [ +  + ]:         45 :       if (c == '_')
     268                 :          4 :         *p = '-';
     269                 :            :     }
     270                 :          4 : }
     271                 :            : 
     272                 :            : /* @key must have already been validated with is_valid() */
     273                 :            : static gboolean
     274                 :       3580 : is_canonical (const gchar *key)
     275                 :            : {
     276                 :       3580 :   return (strchr (key, '_') == NULL);
     277                 :            : }
     278                 :            : 
     279                 :            : /**
     280                 :            :  * g_signal_is_valid_name:
     281                 :            :  * @name: the canonical name of the signal
     282                 :            :  *
     283                 :            :  * Validate a signal name. This can be useful for dynamically-generated signals
     284                 :            :  * which need to be validated at run-time before actually trying to create them.
     285                 :            :  *
     286                 :            :  * See [canonical parameter names][canonical-parameter-names] for details of
     287                 :            :  * the rules for valid names. The rules for signal names are the same as those
     288                 :            :  * for property names.
     289                 :            :  *
     290                 :            :  * Returns: %TRUE if @name is a valid signal name, %FALSE otherwise.
     291                 :            :  * Since: 2.66
     292                 :            :  */
     293                 :            : gboolean
     294                 :       1795 : g_signal_is_valid_name (const gchar *name)
     295                 :            : {
     296                 :            :   /* FIXME: We allow this, against our own documentation (the leading `-` is
     297                 :            :    * invalid), because GTK has historically used this. */
     298         [ -  + ]:       1795 :   if (g_str_equal (name, "-gtk-private-changed"))
     299                 :          0 :     return TRUE;
     300                 :            : 
     301                 :       1795 :   return g_param_spec_is_valid_name (name);
     302                 :            : }
     303                 :            : 
     304                 :            : static inline guint
     305                 :     544032 : signal_id_lookup (const gchar *name,
     306                 :            :                   GType  itype)
     307                 :            : {
     308                 :            :   GQuark quark;
     309                 :     544032 :   GType *ifaces, type = itype;
     310                 :            :   SignalKey key;
     311                 :            :   guint n_ifaces;
     312                 :            : 
     313                 :     544032 :   quark = g_quark_try_string (name);
     314                 :     544032 :   key.quark = quark;
     315                 :            : 
     316                 :            :   /* try looking up signals for this type and its ancestors */
     317                 :            :   do
     318                 :            :     {
     319                 :            :       SignalKey *signal_key;
     320                 :            :       
     321                 :     952033 :       key.itype = type;
     322                 :     952033 :       signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
     323                 :            :       
     324         [ +  + ]:     952033 :       if (signal_key)
     325                 :     141646 :         return signal_key->signal_id;
     326                 :            :       
     327                 :     810387 :       type = g_type_parent (type);
     328                 :            :     }
     329         [ +  + ]:     810387 :   while (type);
     330                 :            : 
     331                 :            :   /* no luck, try interfaces it exports */
     332                 :     402386 :   ifaces = g_type_interfaces (itype, &n_ifaces);
     333         [ +  + ]:     804394 :   while (n_ifaces--)
     334                 :            :     {
     335                 :            :       SignalKey *signal_key;
     336                 :            : 
     337                 :     802600 :       key.itype = ifaces[n_ifaces];
     338                 :     802600 :       signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key);
     339                 :            : 
     340         [ +  + ]:     802600 :       if (signal_key)
     341                 :            :         {
     342                 :     400592 :           g_free (ifaces);
     343                 :     400592 :           return signal_key->signal_id;
     344                 :            :         }
     345                 :            :     }
     346                 :       1794 :   g_free (ifaces);
     347                 :            : 
     348                 :            :   /* If the @name is non-canonical, try again. This is the slow path — people
     349                 :            :    * should use canonical names in their queries if they want performance. */
     350         [ +  + ]:       1794 :   if (!is_canonical (name))
     351                 :            :     {
     352                 :            :       guint signal_id;
     353                 :          3 :       gchar *name_copy = g_strdup (name);
     354                 :          3 :       canonicalize_key (name_copy);
     355                 :            : 
     356                 :          3 :       signal_id = signal_id_lookup (name_copy, itype);
     357                 :            : 
     358                 :          3 :       g_free (name_copy);
     359                 :            : 
     360                 :          3 :       return signal_id;
     361                 :            :     }
     362                 :            : 
     363                 :       1791 :   return 0;
     364                 :            : }
     365                 :            : 
     366                 :            : static gint
     367                 :         90 : class_closures_cmp (gconstpointer node1,
     368                 :            :                     gconstpointer node2)
     369                 :            : {
     370                 :         90 :   const ClassClosure *c1 = node1, *c2 = node2;
     371                 :            :   
     372   [ +  +  +  + ]:         90 :   return G_BSEARCH_ARRAY_CMP (c1->instance_type, c2->instance_type);
     373                 :            : }
     374                 :            : 
     375                 :            : static gint
     376                 :   38211368 : handler_lists_cmp (gconstpointer node1,
     377                 :            :                    gconstpointer node2)
     378                 :            : {
     379                 :   38211368 :   const HandlerList *hlist1 = node1, *hlist2 = node2;
     380                 :            :   
     381   [ +  +  +  + ]:   38211368 :   return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id);
     382                 :            : }
     383                 :            : 
     384                 :            : static inline HandlerList*
     385                 :     539760 : handler_list_ensure (guint    signal_id,
     386                 :            :                      gpointer instance)
     387                 :            : {
     388                 :     539760 :   GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
     389                 :            :   HandlerList key;
     390                 :            :   
     391                 :     539760 :   key.signal_id = signal_id;
     392                 :     539760 :   key.handlers    = NULL;
     393                 :     539760 :   key.tail_before = NULL;
     394                 :     539760 :   key.tail_after  = NULL;
     395         [ +  + ]:     539760 :   if (!hlbsa)
     396                 :            :     {
     397                 :     107030 :       hlbsa = g_bsearch_array_create (&g_signal_hlbsa_bconfig);
     398                 :            :     }
     399                 :     539760 :   hlbsa = g_bsearch_array_insert (hlbsa, &g_signal_hlbsa_bconfig, &key);
     400                 :     539760 :   g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa);
     401                 :     539760 :   return g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key);
     402                 :            : }
     403                 :            : 
     404                 :            : static inline HandlerList*
     405                 :   29501552 : handler_list_lookup (guint    signal_id,
     406                 :            :                      gpointer instance)
     407                 :            : {
     408                 :   29501552 :   GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
     409                 :            :   HandlerList key;
     410                 :            :   
     411                 :   29501552 :   key.signal_id = signal_id;
     412                 :            :   
     413         [ +  + ]:   29501552 :   return hlbsa ? g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key) : NULL;
     414                 :            : }
     415                 :            : 
     416                 :            : static guint
     417                 :    1618259 : handler_hash (gconstpointer key)
     418                 :            : {
     419                 :    1618259 :   return (guint)((Handler*)key)->sequential_number;
     420                 :            : }
     421                 :            : 
     422                 :            : static gboolean
     423                 :    1078586 : handler_equal (gconstpointer a, gconstpointer b)
     424                 :            : {
     425                 :    1078586 :   Handler *ha = (Handler *)a;
     426                 :    1078586 :   Handler *hb = (Handler *)b;
     427         [ +  + ]:    2157063 :   return (ha->sequential_number == hb->sequential_number) &&
     428         [ +  + ]:    1078477 :       (ha->instance  == hb->instance);
     429                 :            : }
     430                 :            : 
     431                 :            : static Handler*
     432                 :     539128 : handler_lookup (gpointer  instance,
     433                 :            :                 gulong    handler_id,
     434                 :            :                 GClosure *closure,
     435                 :            :                 guint    *signal_id_p)
     436                 :            : {
     437                 :            :   GBSearchArray *hlbsa;
     438                 :            : 
     439         [ +  + ]:     539128 :   if (handler_id)
     440                 :            :     {
     441                 :            :       Handler key;
     442                 :     539070 :       key.sequential_number = handler_id;
     443                 :     539070 :       key.instance = instance;
     444                 :     539070 :       return g_hash_table_lookup (g_handlers, &key);
     445                 :            : 
     446                 :            :     }
     447                 :            : 
     448                 :         58 :   hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
     449                 :            :   
     450         [ +  + ]:         58 :   if (hlbsa)
     451                 :            :     {
     452                 :            :       guint i;
     453                 :            :       
     454         [ +  - ]:         57 :       for (i = 0; i < hlbsa->n_nodes; i++)
     455                 :            :         {
     456                 :         57 :           HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
     457                 :            :           Handler *handler;
     458                 :            :           
     459         [ +  - ]:         58 :           for (handler = hlist->handlers; handler; handler = handler->next)
     460   [ +  -  +  + ]:         58 :             if (closure ? (handler->closure == closure) : (handler->sequential_number == handler_id))
     461                 :            :               {
     462         [ +  - ]:         57 :                 if (signal_id_p)
     463                 :         57 :                   *signal_id_p = hlist->signal_id;
     464                 :            : 
     465                 :         57 :                 return handler;
     466                 :            :               }
     467                 :            :         }
     468                 :            :     }
     469                 :            :   
     470                 :          1 :   return NULL;
     471                 :            : }
     472                 :            : 
     473                 :            : static inline HandlerMatch*
     474                 :     402015 : handler_match_prepend (HandlerMatch *list,
     475                 :            :                        Handler      *handler,
     476                 :            :                        guint         signal_id)
     477                 :            : {
     478                 :            :   HandlerMatch *node;
     479                 :            :   
     480                 :     402015 :   node = g_slice_new (HandlerMatch);
     481                 :     402015 :   node->handler = handler;
     482                 :     402015 :   node->next = list;
     483                 :     402015 :   node->signal_id = signal_id;
     484                 :     402015 :   handler_ref (handler);
     485                 :            :   
     486                 :     402015 :   return node;
     487                 :            : }
     488                 :            : static inline HandlerMatch*
     489                 :     402015 : handler_match_free1_R (HandlerMatch *node,
     490                 :            :                        gpointer      instance)
     491                 :            : {
     492                 :     402015 :   HandlerMatch *next = node->next;
     493                 :            :   
     494                 :     402015 :   handler_unref_R (node->signal_id, instance, node->handler);
     495                 :     402015 :   g_slice_free (HandlerMatch, node);
     496                 :            :   
     497                 :     402015 :   return next;
     498                 :            : }
     499                 :            : 
     500                 :            : static HandlerMatch*
     501                 :     402122 : handlers_find (gpointer         instance,
     502                 :            :                GSignalMatchType mask,
     503                 :            :                guint            signal_id,
     504                 :            :                GQuark           detail,
     505                 :            :                GClosure        *closure,
     506                 :            :                gpointer         func,
     507                 :            :                gpointer         data,
     508                 :            :                gboolean         one_and_only)
     509                 :            : {
     510                 :     402122 :   HandlerMatch *mlist = NULL;
     511                 :            :   
     512         [ +  + ]:     402122 :   if (mask & G_SIGNAL_MATCH_ID)
     513                 :            :     {
     514                 :        122 :       HandlerList *hlist = handler_list_lookup (signal_id, instance);
     515                 :            :       Handler *handler;
     516                 :        122 :       SignalNode *node = NULL;
     517                 :            :       
     518         [ +  + ]:        122 :       if (mask & G_SIGNAL_MATCH_FUNC)
     519                 :            :         {
     520                 :          4 :           node = LOOKUP_SIGNAL_NODE (signal_id);
     521   [ +  -  -  + ]:          4 :           if (!node || !node->c_marshaller)
     522                 :          0 :             return NULL;
     523                 :            :         }
     524                 :            :       
     525                 :        122 :       mask = ~mask;
     526   [ +  +  +  + ]:        126 :       for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next)
     527         [ +  - ]:         73 :         if (handler->sequential_number &&
     528   [ +  +  +  - ]:         73 :             ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
     529   [ -  +  -  - ]:         73 :             ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
     530   [ +  +  +  - ]:         73 :             ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
     531   [ +  +  +  - ]:         73 :             ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
     532   [ +  +  +  - ]:         73 :             ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
     533         [ +  - ]:          2 :                                               G_REAL_CLOSURE (handler->closure)->meta_marshal == NULL &&
     534         [ +  - ]:          2 :                                               ((GCClosure*) handler->closure)->callback == func)))
     535                 :            :           {
     536                 :         73 :             mlist = handler_match_prepend (mlist, handler, signal_id);
     537         [ +  + ]:         73 :             if (one_and_only)
     538                 :         69 :               return mlist;
     539                 :            :           }
     540                 :            :     }
     541                 :            :   else
     542                 :            :     {
     543                 :     402000 :       GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
     544                 :            :       
     545                 :     402000 :       mask = ~mask;
     546         [ +  + ]:     402000 :       if (hlbsa)
     547                 :            :         {
     548                 :            :           guint i;
     549                 :            :           
     550         [ +  + ]:    2004514 :           for (i = 0; i < hlbsa->n_nodes; i++)
     551                 :            :             {
     552                 :    1602532 :               HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
     553                 :    1602532 :               SignalNode *node = NULL;
     554                 :            :               Handler *handler;
     555                 :            :               
     556         [ +  + ]:    1602532 :               if (!(mask & G_SIGNAL_MATCH_FUNC))
     557                 :            :                 {
     558                 :    1602524 :                   node = LOOKUP_SIGNAL_NODE (hlist->signal_id);
     559         [ -  + ]:    1602524 :                   if (!node->c_marshaller)
     560                 :          0 :                     continue;
     561                 :            :                 }
     562                 :            :               
     563         [ +  + ]:    3129377 :               for (handler = hlist->handlers; handler; handler = handler->next)
     564         [ +  - ]:    1526845 :                 if (handler->sequential_number &&
     565   [ -  +  -  - ]:    1526845 :                     ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) &&
     566   [ -  +  -  - ]:    1526845 :                     ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) &&
     567   [ +  +  +  + ]:    1526845 :                     ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
     568   [ -  +  -  - ]:    1002182 :                     ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
     569   [ +  +  +  - ]:    1002182 :                     ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
     570         [ +  - ]:    1002174 :                                                       G_REAL_CLOSURE (handler->closure)->meta_marshal == NULL &&
     571         [ +  + ]:    1002174 :                                                       ((GCClosure*) handler->closure)->callback == func)))
     572                 :            :                   {
     573                 :     401942 :                     mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
     574         [ -  + ]:     401942 :                     if (one_and_only)
     575                 :          0 :                       return mlist;
     576                 :            :                   }
     577                 :            :             }
     578                 :            :         }
     579                 :            :     }
     580                 :            :   
     581                 :     402053 :   return mlist;
     582                 :            : }
     583                 :            : 
     584                 :            : static inline Handler*
     585                 :     539760 : handler_new (guint signal_id, gpointer instance, gboolean after)
     586                 :            : {
     587                 :     539760 :   Handler *handler = g_slice_new (Handler);
     588                 :            : #ifndef G_DISABLE_CHECKS
     589         [ -  + ]:     539760 :   if (g_handler_sequential_number < 1)
     590                 :          0 :     g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG);
     591                 :            : #endif
     592                 :            :   
     593                 :     539760 :   handler->sequential_number = g_handler_sequential_number++;
     594                 :     539760 :   handler->prev = NULL;
     595                 :     539760 :   handler->next = NULL;
     596                 :     539760 :   handler->detail = 0;
     597                 :     539760 :   handler->signal_id = signal_id;
     598                 :     539760 :   handler->instance = instance;
     599                 :     539760 :   handler->ref_count = 1;
     600                 :     539760 :   handler->block_count = 0;
     601                 :     539760 :   handler->after = after != FALSE;
     602                 :     539760 :   handler->closure = NULL;
     603                 :     539760 :   handler->has_invalid_closure_notify = 0;
     604                 :            : 
     605                 :     539760 :   g_hash_table_add (g_handlers, handler);
     606                 :            :   
     607                 :     539760 :   return handler;
     608                 :            : }
     609                 :            : 
     610                 :            : static inline void
     611                 :   31721707 : handler_ref (Handler *handler)
     612                 :            : {
     613                 :   31721707 :   g_return_if_fail (handler->ref_count > 0);
     614                 :            :   
     615                 :   31721707 :   handler->ref_count++;
     616                 :            : }
     617                 :            : 
     618                 :            : static inline void
     619                 :   32261122 : handler_unref_R (guint    signal_id,
     620                 :            :                  gpointer instance,
     621                 :            :                  Handler *handler)
     622                 :            : {
     623                 :   32261122 :   g_return_if_fail (handler->ref_count > 0);
     624                 :            : 
     625                 :   32261122 :   handler->ref_count--;
     626                 :            : 
     627         [ +  + ]:   32261122 :   if (G_UNLIKELY (handler->ref_count == 0))
     628                 :            :     {
     629                 :     539423 :       HandlerList *hlist = NULL;
     630                 :            : 
     631         [ +  + ]:     539423 :       if (handler->next)
     632                 :       8272 :         handler->next->prev = handler->prev;
     633         [ +  + ]:     539423 :       if (handler->prev)    /* watch out for g_signal_handlers_destroy()! */
     634                 :      11914 :         handler->prev->next = handler->next;
     635                 :            :       else
     636                 :            :         {
     637                 :     527509 :           hlist = handler_list_lookup (signal_id, instance);
     638                 :     527509 :           g_assert (hlist != NULL);
     639                 :     527509 :           hlist->handlers = handler->next;
     640                 :            :         }
     641                 :            : 
     642         [ +  + ]:     539423 :       if (instance)
     643                 :            :         {
     644                 :            :           /*  check if we are removing the handler pointed to by tail_before  */
     645   [ +  +  +  +  :     538727 :           if (!handler->after && (!handler->next || handler->next->after))
                   +  + ]
     646                 :            :             {
     647         [ +  + ]:     530454 :               if (!hlist)
     648                 :      10300 :                 hlist = handler_list_lookup (signal_id, instance);
     649         [ +  - ]:     530454 :               if (hlist)
     650                 :            :                 {
     651                 :     530454 :                   g_assert (hlist->tail_before == handler); /* paranoid */
     652                 :     530454 :                   hlist->tail_before = handler->prev;
     653                 :            :                 }
     654                 :            :             }
     655                 :            : 
     656                 :            :           /*  check if we are removing the handler pointed to by tail_after  */
     657         [ +  + ]:     538727 :           if (!handler->next)
     658                 :            :             {
     659         [ +  + ]:     530455 :               if (!hlist)
     660                 :          2 :                 hlist = handler_list_lookup (signal_id, instance);
     661         [ +  - ]:     530455 :               if (hlist)
     662                 :            :                 {
     663                 :     530455 :                   g_assert (hlist->tail_after == handler); /* paranoid */
     664                 :     530455 :                   hlist->tail_after = handler->prev;
     665                 :            :                 }
     666                 :            :             }
     667                 :            :         }
     668                 :            : 
     669                 :     539423 :       SIGNAL_UNLOCK ();
     670                 :     539257 :       g_closure_unref (handler->closure);
     671                 :     539209 :       SIGNAL_LOCK ();
     672                 :     539423 :       g_slice_free (Handler, handler);
     673                 :            :     }
     674                 :            : }
     675                 :            : 
     676                 :            : static void
     677                 :     539760 : handler_insert (guint    signal_id,
     678                 :            :                 gpointer instance,
     679                 :            :                 Handler  *handler)
     680                 :            : {
     681                 :            :   HandlerList *hlist;
     682                 :            :   
     683                 :     539760 :   g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */
     684                 :            : 
     685                 :     539760 :   hlist = handler_list_ensure (signal_id, instance);
     686         [ +  + ]:     539760 :   if (!hlist->handlers)
     687                 :            :     {
     688                 :     521129 :       hlist->handlers = handler;
     689         [ +  + ]:     521129 :       if (!handler->after)
     690                 :     521128 :         hlist->tail_before = handler;
     691                 :            :     }
     692         [ +  + ]:      18631 :   else if (handler->after)
     693                 :            :     {
     694                 :         17 :       handler->prev = hlist->tail_after;
     695                 :         17 :       hlist->tail_after->next = handler;
     696                 :            :     }
     697                 :            :   else
     698                 :            :     {
     699         [ +  + ]:      18614 :       if (hlist->tail_before)
     700                 :            :         {
     701                 :      18612 :           handler->next = hlist->tail_before->next;
     702         [ +  + ]:      18612 :           if (handler->next)
     703                 :         28 :             handler->next->prev = handler;
     704                 :      18612 :           handler->prev = hlist->tail_before;
     705                 :      18612 :           hlist->tail_before->next = handler;
     706                 :            :         }
     707                 :            :       else /* insert !after handler into a list of only after handlers */
     708                 :            :         {
     709                 :          2 :           handler->next = hlist->handlers;
     710         [ +  - ]:          2 :           if (handler->next)
     711                 :          2 :             handler->next->prev = handler;
     712                 :          2 :           hlist->handlers = handler;
     713                 :            :         }
     714                 :      18614 :       hlist->tail_before = handler;
     715                 :            :     }
     716                 :            : 
     717         [ +  + ]:     539760 :   if (!handler->next)
     718                 :     539730 :     hlist->tail_after = handler;
     719                 :     539760 : }
     720                 :            : 
     721                 :            : static void
     722                 :        472 : node_update_single_va_closure (SignalNode *node)
     723                 :            : {
     724                 :        472 :   GClosure *closure = NULL;
     725                 :        472 :   gboolean is_after = FALSE;
     726                 :            : 
     727                 :            :   /* Fast path single-handler without boxing the arguments in GValues */
     728         [ +  + ]:        472 :   if (G_TYPE_IS_OBJECT (node->itype) &&
     729         [ +  + ]:        398 :       (node->flags & (G_SIGNAL_MUST_COLLECT)) == 0 &&
     730   [ +  +  +  + ]:        376 :       (node->emission_hooks == NULL || node->emission_hooks->hooks == NULL))
     731                 :            :     {
     732                 :            :       GSignalFlags run_type;
     733                 :            :       ClassClosure * cc; 
     734                 :        368 :       GBSearchArray *bsa = node->class_closure_bsa;
     735                 :            : 
     736   [ +  +  -  + ]:        368 :       if (bsa == NULL || bsa->n_nodes == 0)
     737                 :         26 :         closure = SINGLE_VA_CLOSURE_EMPTY_MAGIC;
     738         [ +  + ]:        342 :       else if (bsa->n_nodes == 1)
     739                 :            :         {
     740                 :            :           /* Look for default class closure (can't support non-default as it
     741                 :            :              chains up using GValues */
     742                 :        338 :           cc = g_bsearch_array_get_nth (bsa, &g_class_closure_bconfig, 0);
     743         [ +  - ]:        338 :           if (cc->instance_type == 0)
     744                 :            :             {
     745                 :        338 :               run_type = node->flags & (G_SIGNAL_RUN_FIRST|G_SIGNAL_RUN_LAST|G_SIGNAL_RUN_CLEANUP);
     746                 :            :               /* Only support *one* of run-first or run-last, not multiple or cleanup */
     747   [ +  +  +  + ]:        338 :               if (run_type == G_SIGNAL_RUN_FIRST ||
     748                 :            :                   run_type == G_SIGNAL_RUN_LAST)
     749                 :            :                 {
     750                 :        333 :                   closure = cc->closure;
     751                 :        333 :                   is_after = (run_type == G_SIGNAL_RUN_LAST);
     752                 :            :                 }
     753                 :            :             }
     754                 :            :         }
     755                 :            :     }
     756                 :            : 
     757                 :        472 :   node->single_va_closure_is_valid = TRUE;
     758                 :        472 :   node->single_va_closure = closure;
     759                 :        472 :   node->single_va_closure_is_after = is_after;
     760                 :        472 : }
     761                 :            : 
     762                 :            : static inline void
     763                 :   17047792 : emission_push (Emission  *emission)
     764                 :            : {
     765                 :   17047792 :   emission->next = g_emissions;
     766                 :   17047792 :   g_emissions = emission;
     767                 :   17047792 : }
     768                 :            : 
     769                 :            : static inline void
     770                 :   17047784 : emission_pop (Emission  *emission)
     771                 :            : {
     772                 :   17047784 :   Emission *node, *last = NULL;
     773                 :            : 
     774         [ +  - ]:   18070174 :   for (node = g_emissions; node; last = node, node = last->next)
     775         [ +  + ]:   18070174 :     if (node == emission)
     776                 :            :       {
     777         [ +  + ]:   17047784 :         if (last)
     778                 :     833388 :           last->next = node->next;
     779                 :            :         else
     780                 :   16214396 :           g_emissions = node->next;
     781                 :   17047784 :         return;
     782                 :            :       }
     783                 :            :   g_assert_not_reached ();
     784                 :            : }
     785                 :            : 
     786                 :            : static inline Emission*
     787                 :    4616973 : emission_find (guint     signal_id,
     788                 :            :                GQuark    detail,
     789                 :            :                gpointer  instance)
     790                 :            : {
     791                 :            :   Emission *emission;
     792                 :            :   
     793         [ +  + ]:    5803597 :   for (emission = g_emissions; emission; emission = emission->next)
     794         [ +  + ]:    1254487 :     if (emission->instance == instance &&
     795         [ +  + ]:      67930 :         emission->ihint.signal_id == signal_id &&
     796         [ +  + ]:      67869 :         emission->ihint.detail == detail)
     797                 :      67863 :       return emission;
     798                 :    4549110 :   return NULL;
     799                 :            : }
     800                 :            : 
     801                 :            : static inline Emission*
     802                 :         24 : emission_find_innermost (gpointer instance)
     803                 :            : {
     804                 :            :   Emission *emission;
     805                 :            :   
     806         [ +  - ]:         24 :   for (emission = g_emissions; emission; emission = emission->next)
     807         [ +  - ]:         24 :     if (emission->instance == instance)
     808                 :         24 :       return emission;
     809                 :            : 
     810                 :          0 :   return NULL;
     811                 :            : }
     812                 :            : 
     813                 :            : static gint
     814                 :    7803629 : signal_key_cmp (gconstpointer node1,
     815                 :            :                 gconstpointer node2)
     816                 :            : {
     817                 :    7803629 :   const SignalKey *key1 = node1, *key2 = node2;
     818                 :            :   
     819         [ +  + ]:    7803629 :   if (key1->itype == key2->itype)
     820   [ +  +  +  + ]:    1348120 :     return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark);
     821                 :            :   else
     822   [ +  +  -  + ]:    6455509 :     return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype);
     823                 :            : }
     824                 :            : 
     825                 :            : void
     826                 :        527 : _g_signal_init (void)
     827                 :            : {
     828                 :        527 :   SIGNAL_LOCK ();
     829         [ +  - ]:        527 :   if (!g_n_signal_nodes)
     830                 :            :     {
     831                 :            :       /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */
     832                 :        527 :       g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL);
     833                 :        527 :       g_signal_key_bsa = g_bsearch_array_create (&g_signal_key_bconfig);
     834                 :            :       
     835                 :            :       /* invalid (0) signal_id */
     836                 :        527 :       g_n_signal_nodes = 1;
     837                 :        527 :       g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
     838                 :        527 :       g_signal_nodes[0] = NULL;
     839                 :        527 :       g_handlers = g_hash_table_new (handler_hash, handler_equal);
     840                 :            :     }
     841                 :        527 :   SIGNAL_UNLOCK ();
     842                 :        527 : }
     843                 :            : 
     844                 :            : void
     845                 :          0 : _g_signals_destroy (GType itype)
     846                 :            : {
     847                 :            :   guint i;
     848                 :            :   
     849                 :          0 :   SIGNAL_LOCK ();
     850         [ #  # ]:          0 :   for (i = 1; i < g_n_signal_nodes; i++)
     851                 :            :     {
     852                 :          0 :       SignalNode *node = g_signal_nodes[i];
     853                 :            :       
     854         [ #  # ]:          0 :       if (node->itype == itype)
     855                 :            :         {
     856         [ #  # ]:          0 :           if (node->destroyed)
     857                 :          0 :             g_critical (G_STRLOC ": signal \"%s\" of type '%s' already destroyed",
     858                 :            :                         node->name,
     859                 :            :                         type_debug_name (node->itype));
     860                 :            :           else
     861                 :          0 :             signal_destroy_R (node);
     862                 :            :         }
     863                 :            :     }
     864                 :          0 :   SIGNAL_UNLOCK ();
     865                 :          0 : }
     866                 :            : 
     867                 :            : /**
     868                 :            :  * g_signal_stop_emission:
     869                 :            :  * @instance: (type GObject.Object): the object whose signal handlers you wish to stop.
     870                 :            :  * @signal_id: the signal identifier, as returned by g_signal_lookup().
     871                 :            :  * @detail: the detail which the signal was emitted with.
     872                 :            :  *
     873                 :            :  * Stops a signal's current emission.
     874                 :            :  *
     875                 :            :  * This will prevent the default method from running, if the signal was
     876                 :            :  * %G_SIGNAL_RUN_LAST and you connected normally (i.e. without the "after"
     877                 :            :  * flag).
     878                 :            :  *
     879                 :            :  * Prints a warning if used on a signal which isn't being emitted.
     880                 :            :  */
     881                 :            : void
     882                 :          1 : g_signal_stop_emission (gpointer instance,
     883                 :            :                         guint    signal_id,
     884                 :            :                         GQuark   detail)
     885                 :            : {
     886                 :            :   SignalNode *node;
     887                 :            :   
     888                 :          1 :   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
     889                 :          1 :   g_return_if_fail (signal_id > 0);
     890                 :            :   
     891                 :          1 :   SIGNAL_LOCK ();
     892                 :          1 :   node = LOOKUP_SIGNAL_NODE (signal_id);
     893   [ +  -  -  +  :          1 :   if (node && detail && !(node->flags & G_SIGNAL_DETAILED))
                   -  - ]
     894                 :            :     {
     895                 :          0 :       g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
     896                 :          0 :       SIGNAL_UNLOCK ();
     897                 :          0 :       return;
     898                 :            :     }
     899   [ +  -  -  +  :          1 :   if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
                   -  - ]
     900                 :          1 :     {
     901                 :          1 :       Emission *emission = emission_find (signal_id, detail, instance);
     902                 :            :       
     903         [ +  - ]:          1 :       if (emission)
     904                 :            :         {
     905         [ -  + ]:          1 :           if (emission->state == EMISSION_HOOK)
     906                 :          0 :             g_critical (G_STRLOC ": emission of signal \"%s\" for instance '%p' cannot be stopped from emission hook",
     907                 :            :                         node->name, instance);
     908         [ +  - ]:          1 :           else if (emission->state == EMISSION_RUN)
     909                 :          1 :             emission->state = EMISSION_STOP;
     910                 :            :         }
     911                 :            :       else
     912                 :          0 :         g_critical (G_STRLOC ": no emission of signal \"%s\" to stop for instance '%p'",
     913                 :            :                     node->name, instance);
     914                 :            :     }
     915                 :            :   else
     916                 :          0 :     g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
     917                 :          1 :   SIGNAL_UNLOCK ();
     918                 :            : }
     919                 :            : 
     920                 :            : static void
     921                 :         26 : signal_finalize_hook (GHookList *hook_list,
     922                 :            :                       GHook     *hook)
     923                 :            : {
     924                 :         26 :   GDestroyNotify destroy = hook->destroy;
     925                 :            : 
     926         [ -  + ]:         26 :   if (destroy)
     927                 :            :     {
     928                 :          0 :       hook->destroy = NULL;
     929                 :          0 :       SIGNAL_UNLOCK ();
     930                 :          0 :       destroy (hook->data);
     931                 :          0 :       SIGNAL_LOCK ();
     932                 :            :     }
     933                 :         26 : }
     934                 :            : 
     935                 :            : /**
     936                 :            :  * g_signal_add_emission_hook:
     937                 :            :  * @signal_id: the signal identifier, as returned by g_signal_lookup().
     938                 :            :  * @detail: the detail on which to call the hook.
     939                 :            :  * @hook_func: (not nullable): a #GSignalEmissionHook function.
     940                 :            :  * @hook_data: (nullable) (closure hook_func): user data for @hook_func.
     941                 :            :  * @data_destroy: (nullable) (destroy hook_data): a #GDestroyNotify for @hook_data.
     942                 :            :  *
     943                 :            :  * Adds an emission hook for a signal, which will get called for any emission
     944                 :            :  * of that signal, independent of the instance. This is possible only
     945                 :            :  * for signals which don't have %G_SIGNAL_NO_HOOKS flag set.
     946                 :            :  *
     947                 :            :  * Returns: the hook id, for later use with g_signal_remove_emission_hook().
     948                 :            :  */
     949                 :            : gulong
     950                 :         26 : g_signal_add_emission_hook (guint               signal_id,
     951                 :            :                             GQuark              detail,
     952                 :            :                             GSignalEmissionHook hook_func,
     953                 :            :                             gpointer            hook_data,
     954                 :            :                             GDestroyNotify      data_destroy)
     955                 :            : {
     956                 :            :   static gulong seq_hook_id = 1;
     957                 :            :   SignalNode *node;
     958                 :            :   GHook *hook;
     959                 :            :   SignalHook *signal_hook;
     960                 :            : 
     961                 :         26 :   g_return_val_if_fail (signal_id > 0, 0);
     962                 :         26 :   g_return_val_if_fail (hook_func != NULL, 0);
     963                 :            : 
     964                 :         26 :   SIGNAL_LOCK ();
     965                 :         26 :   node = LOOKUP_SIGNAL_NODE (signal_id);
     966   [ +  -  -  + ]:         26 :   if (!node || node->destroyed)
     967                 :            :     {
     968                 :          0 :       g_critical ("%s: invalid signal id '%u'", G_STRLOC, signal_id);
     969                 :          0 :       SIGNAL_UNLOCK ();
     970                 :          0 :       return 0;
     971                 :            :     }
     972         [ -  + ]:         26 :   if (node->flags & G_SIGNAL_NO_HOOKS) 
     973                 :            :     {
     974                 :          0 :       g_critical ("%s: signal id '%u' does not support emission hooks (G_SIGNAL_NO_HOOKS flag set)", G_STRLOC, signal_id);
     975                 :          0 :       SIGNAL_UNLOCK ();
     976                 :          0 :       return 0;
     977                 :            :     }
     978   [ -  +  -  - ]:         26 :   if (detail && !(node->flags & G_SIGNAL_DETAILED))
     979                 :            :     {
     980                 :          0 :       g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
     981                 :          0 :       SIGNAL_UNLOCK ();
     982                 :          0 :       return 0;
     983                 :            :     }
     984                 :         26 :     node->single_va_closure_is_valid = FALSE;
     985         [ +  + ]:         26 :   if (!node->emission_hooks)
     986                 :            :     {
     987                 :          3 :       node->emission_hooks = g_new (GHookList, 1);
     988                 :          3 :       g_hook_list_init (node->emission_hooks, sizeof (SignalHook));
     989                 :          3 :       node->emission_hooks->finalize_hook = signal_finalize_hook;
     990                 :            :     }
     991                 :            : 
     992                 :         26 :   node_check_deprecated (node);
     993                 :            : 
     994                 :         26 :   hook = g_hook_alloc (node->emission_hooks);
     995                 :         26 :   hook->data = hook_data;
     996                 :         26 :   hook->func = (gpointer) hook_func;
     997                 :         26 :   hook->destroy = data_destroy;
     998                 :         26 :   signal_hook = SIGNAL_HOOK (hook);
     999                 :         26 :   signal_hook->detail = detail;
    1000                 :         26 :   node->emission_hooks->seq_id = seq_hook_id;
    1001                 :         26 :   g_hook_append (node->emission_hooks, hook);
    1002                 :         26 :   seq_hook_id = node->emission_hooks->seq_id;
    1003                 :            : 
    1004                 :         26 :   SIGNAL_UNLOCK ();
    1005                 :            : 
    1006                 :         26 :   return hook->hook_id;
    1007                 :            : }
    1008                 :            : 
    1009                 :            : /**
    1010                 :            :  * g_signal_remove_emission_hook:
    1011                 :            :  * @signal_id: the id of the signal
    1012                 :            :  * @hook_id: the id of the emission hook, as returned by
    1013                 :            :  *  g_signal_add_emission_hook()
    1014                 :            :  *
    1015                 :            :  * Deletes an emission hook.
    1016                 :            :  */
    1017                 :            : void
    1018                 :         27 : g_signal_remove_emission_hook (guint  signal_id,
    1019                 :            :                                gulong hook_id)
    1020                 :            : {
    1021                 :            :   SignalNode *node;
    1022                 :            : 
    1023                 :         27 :   g_return_if_fail (signal_id > 0);
    1024                 :         27 :   g_return_if_fail (hook_id > 0);
    1025                 :            : 
    1026                 :         27 :   SIGNAL_LOCK ();
    1027                 :         27 :   node = LOOKUP_SIGNAL_NODE (signal_id);
    1028   [ +  -  -  + ]:         27 :   if (!node || node->destroyed)
    1029                 :            :     {
    1030                 :          0 :       g_critical ("%s: invalid signal id '%u'", G_STRLOC, signal_id);
    1031                 :          0 :       goto out;
    1032                 :            :     }
    1033   [ +  -  +  + ]:         27 :   else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id))
    1034                 :         12 :     g_critical ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id);
    1035                 :            : 
    1036                 :         27 :   node->single_va_closure_is_valid = FALSE;
    1037                 :            : 
    1038                 :         27 :  out:
    1039                 :         27 :   SIGNAL_UNLOCK ();
    1040                 :            : }
    1041                 :            : 
    1042                 :            : static inline guint
    1043                 :     539885 : signal_parse_name (const gchar *name,
    1044                 :            :                    GType        itype,
    1045                 :            :                    GQuark      *detail_p,
    1046                 :            :                    gboolean     force_quark)
    1047                 :            : {
    1048                 :     539885 :   const gchar *colon = strchr (name, ':');
    1049                 :            :   guint signal_id;
    1050                 :            :   
    1051         [ +  + ]:     539885 :   if (!colon)
    1052                 :            :     {
    1053                 :     539567 :       signal_id = signal_id_lookup (name, itype);
    1054   [ +  +  +  - ]:     539567 :       if (signal_id && detail_p)
    1055                 :     539564 :         *detail_p = 0;
    1056                 :            :     }
    1057         [ +  + ]:        318 :   else if (colon[1] == ':')
    1058                 :            :     {
    1059                 :            :       gchar buffer[32];
    1060                 :        314 :       guint l = colon - name;
    1061                 :            :       
    1062         [ +  + ]:        314 :       if (colon[2] == '\0')
    1063                 :          2 :         return 0;
    1064                 :            : 
    1065         [ +  - ]:        312 :       if (l < 32)
    1066                 :            :         {
    1067                 :        312 :           memcpy (buffer, name, l);
    1068                 :        312 :           buffer[l] = 0;
    1069                 :        312 :           signal_id = signal_id_lookup (buffer, itype);
    1070                 :            :         }
    1071                 :            :       else
    1072                 :            :         {
    1073                 :          0 :           gchar *signal = g_new (gchar, l + 1);
    1074                 :            :           
    1075                 :          0 :           memcpy (signal, name, l);
    1076                 :          0 :           signal[l] = 0;
    1077                 :          0 :           signal_id = signal_id_lookup (signal, itype);
    1078                 :          0 :           g_free (signal);
    1079                 :            :         }
    1080                 :            :       
    1081   [ +  +  +  - ]:        312 :       if (signal_id && detail_p)
    1082         [ +  + ]:        311 :         *detail_p = (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2);
    1083                 :            :     }
    1084                 :            :   else
    1085                 :          4 :     signal_id = 0;
    1086                 :     539883 :   return signal_id;
    1087                 :            : }
    1088                 :            : 
    1089                 :            : /**
    1090                 :            :  * g_signal_parse_name:
    1091                 :            :  * @detailed_signal: a string of the form "signal-name::detail".
    1092                 :            :  * @itype: The interface/instance type that introduced "signal-name".
    1093                 :            :  * @signal_id_p: (out): Location to store the signal id.
    1094                 :            :  * @detail_p: (out): Location to store the detail quark.
    1095                 :            :  * @force_detail_quark: %TRUE forces creation of a #GQuark for the detail.
    1096                 :            :  *
    1097                 :            :  * Internal function to parse a signal name into its @signal_id
    1098                 :            :  * and @detail quark.
    1099                 :            :  *
    1100                 :            :  * Returns: Whether the signal name could successfully be parsed and @signal_id_p and @detail_p contain valid return values.
    1101                 :            :  */
    1102                 :            : gboolean
    1103                 :         49 : g_signal_parse_name (const gchar *detailed_signal,
    1104                 :            :                      GType        itype,
    1105                 :            :                      guint       *signal_id_p,
    1106                 :            :                      GQuark      *detail_p,
    1107                 :            :                      gboolean     force_detail_quark)
    1108                 :            : {
    1109                 :            :   SignalNode *node;
    1110                 :         49 :   GQuark detail = 0;
    1111                 :            :   guint signal_id;
    1112                 :            :   
    1113                 :         49 :   g_return_val_if_fail (detailed_signal != NULL, FALSE);
    1114                 :         49 :   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE);
    1115                 :            :   
    1116                 :         49 :   SIGNAL_LOCK ();
    1117                 :         49 :   signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark);
    1118                 :            : 
    1119         [ +  + ]:         49 :   node = signal_id ? LOOKUP_SIGNAL_NODE (signal_id) : NULL;
    1120                 :            : 
    1121   [ +  +  +  - ]:         49 :   if (!node || node->destroyed ||
    1122   [ +  +  +  + ]:         39 :       (detail && !(node->flags & G_SIGNAL_DETAILED)))
    1123                 :            :     {
    1124                 :         11 :       SIGNAL_UNLOCK ();
    1125                 :         11 :       return FALSE;
    1126                 :            :     }
    1127                 :            : 
    1128                 :         38 :   SIGNAL_UNLOCK ();
    1129                 :            : 
    1130         [ +  - ]:         38 :   if (signal_id_p)
    1131                 :         38 :     *signal_id_p = signal_id;
    1132         [ +  - ]:         38 :   if (detail_p)
    1133                 :         38 :     *detail_p = detail;
    1134                 :            :   
    1135                 :         38 :   return TRUE;
    1136                 :            : }
    1137                 :            : 
    1138                 :            : /**
    1139                 :            :  * g_signal_stop_emission_by_name:
    1140                 :            :  * @instance: (type GObject.Object): the object whose signal handlers you wish to stop.
    1141                 :            :  * @detailed_signal: a string of the form "signal-name::detail".
    1142                 :            :  *
    1143                 :            :  * Stops a signal's current emission.
    1144                 :            :  *
    1145                 :            :  * This is just like g_signal_stop_emission() except it will look up the
    1146                 :            :  * signal id for you.
    1147                 :            :  */
    1148                 :            : void
    1149                 :          1 : g_signal_stop_emission_by_name (gpointer     instance,
    1150                 :            :                                 const gchar *detailed_signal)
    1151                 :            : {
    1152                 :            :   guint signal_id;
    1153                 :          1 :   GQuark detail = 0;
    1154                 :            :   GType itype;
    1155                 :            :   
    1156                 :          1 :   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
    1157                 :          1 :   g_return_if_fail (detailed_signal != NULL);
    1158                 :            :   
    1159                 :          1 :   SIGNAL_LOCK ();
    1160                 :          1 :   itype = G_TYPE_FROM_INSTANCE (instance);
    1161                 :          1 :   signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
    1162         [ +  - ]:          1 :   if (signal_id)
    1163                 :            :     {
    1164                 :          1 :       SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
    1165                 :            :       
    1166   [ -  +  -  - ]:          1 :       if (detail && !(node->flags & G_SIGNAL_DETAILED))
    1167                 :          0 :         g_critical ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal);
    1168   [ -  +  -  - ]:          1 :       else if (!g_type_is_a (itype, node->itype))
    1169                 :          0 :         g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
    1170                 :            :                     G_STRLOC, detailed_signal, instance, g_type_name (itype));
    1171                 :            :       else
    1172                 :            :         {
    1173                 :          1 :           Emission *emission = emission_find (signal_id, detail, instance);
    1174                 :            :           
    1175         [ +  - ]:          1 :           if (emission)
    1176                 :            :             {
    1177         [ -  + ]:          1 :               if (emission->state == EMISSION_HOOK)
    1178                 :          0 :                 g_critical (G_STRLOC ": emission of signal \"%s\" for instance '%p' cannot be stopped from emission hook",
    1179                 :            :                             node->name, instance);
    1180         [ +  - ]:          1 :               else if (emission->state == EMISSION_RUN)
    1181                 :          1 :                 emission->state = EMISSION_STOP;
    1182                 :            :             }
    1183                 :            :           else
    1184                 :          0 :             g_critical (G_STRLOC ": no emission of signal \"%s\" to stop for instance '%p'",
    1185                 :            :                         node->name, instance);
    1186                 :            :         }
    1187                 :            :     }
    1188                 :            :   else
    1189                 :          0 :     g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
    1190                 :            :                 G_STRLOC, detailed_signal, instance, g_type_name (itype));
    1191                 :          1 :   SIGNAL_UNLOCK ();
    1192                 :            : }
    1193                 :            : 
    1194                 :            : /**
    1195                 :            :  * g_signal_lookup:
    1196                 :            :  * @name: the signal's name.
    1197                 :            :  * @itype: the type that the signal operates on.
    1198                 :            :  *
    1199                 :            :  * Given the name of the signal and the type of object it connects to, gets
    1200                 :            :  * the signal's identifying integer. Emitting the signal by number is
    1201                 :            :  * somewhat faster than using the name each time.
    1202                 :            :  *
    1203                 :            :  * Also tries the ancestors of the given type.
    1204                 :            :  *
    1205                 :            :  * The type class passed as @itype must already have been instantiated (for
    1206                 :            :  * example, using g_type_class_ref()) for this function to work, as signals are
    1207                 :            :  * always installed during class initialization.
    1208                 :            :  *
    1209                 :            :  * See g_signal_new() for details on allowed signal names.
    1210                 :            :  *
    1211                 :            :  * Returns: the signal's identifying number, or 0 if no signal was found.
    1212                 :            :  */
    1213                 :            : guint
    1214                 :       2364 : g_signal_lookup (const gchar *name,
    1215                 :            :                  GType        itype)
    1216                 :            : {
    1217                 :            :   guint signal_id;
    1218                 :       2364 :   g_return_val_if_fail (name != NULL, 0);
    1219                 :       2364 :   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
    1220                 :            :   
    1221                 :       2364 :   SIGNAL_LOCK ();
    1222                 :       2364 :   signal_id = signal_id_lookup (name, itype);
    1223                 :       2364 :   SIGNAL_UNLOCK ();
    1224         [ +  + ]:       2364 :   if (!signal_id)
    1225                 :            :     {
    1226                 :            :       /* give elaborate warnings */
    1227         [ -  + ]:          1 :       if (!g_type_name (itype))
    1228                 :          0 :         g_critical (G_STRLOC ": unable to look up signal \"%s\" for invalid type id '%"G_GUINTPTR_FORMAT"'",
    1229                 :            :                     name, (guintptr) itype);
    1230         [ -  + ]:          1 :       else if (!g_signal_is_valid_name (name))
    1231                 :          0 :         g_critical (G_STRLOC ": unable to look up invalid signal name \"%s\" on type '%s'",
    1232                 :            :                     name, g_type_name (itype));
    1233                 :            :     }
    1234                 :            :   
    1235                 :       2364 :   return signal_id;
    1236                 :            : }
    1237                 :            : 
    1238                 :            : /**
    1239                 :            :  * g_signal_list_ids:
    1240                 :            :  * @itype: Instance or interface type.
    1241                 :            :  * @n_ids: Location to store the number of signal ids for @itype.
    1242                 :            :  *
    1243                 :            :  * Lists the signals by id that a certain instance or interface type
    1244                 :            :  * created. Further information about the signals can be acquired through
    1245                 :            :  * g_signal_query().
    1246                 :            :  *
    1247                 :            :  * Returns: (array length=n_ids) (transfer full): Newly allocated array of signal IDs.
    1248                 :            :  */
    1249                 :            : guint*
    1250                 :        164 : g_signal_list_ids (GType  itype,
    1251                 :            :                    guint *n_ids)
    1252                 :            : {
    1253                 :            :   SignalKey *keys;
    1254                 :            :   GArray *result;
    1255                 :            :   guint n_nodes;
    1256                 :            :   guint i;
    1257                 :            :   
    1258                 :        164 :   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
    1259                 :        164 :   g_return_val_if_fail (n_ids != NULL, NULL);
    1260                 :            :   
    1261                 :        164 :   SIGNAL_LOCK ();
    1262                 :        164 :   keys = g_bsearch_array_get_nth (g_signal_key_bsa, &g_signal_key_bconfig, 0);
    1263                 :        164 :   n_nodes = g_bsearch_array_get_n_nodes (g_signal_key_bsa);
    1264                 :        164 :   result = g_array_new (FALSE, FALSE, sizeof (guint));
    1265                 :            :   
    1266         [ +  + ]:       6949 :   for (i = 0; i < n_nodes; i++)
    1267         [ +  + ]:       6785 :     if (keys[i].itype == itype)
    1268                 :            :       {
    1269                 :        113 :         g_array_append_val (result, keys[i].signal_id);
    1270                 :            :       }
    1271                 :        164 :   *n_ids = result->len;
    1272                 :        164 :   SIGNAL_UNLOCK ();
    1273         [ -  + ]:        164 :   if (!n_nodes)
    1274                 :            :     {
    1275                 :            :       /* give elaborate warnings */
    1276         [ #  # ]:          0 :       if (!g_type_name (itype))
    1277                 :          0 :         g_critical (G_STRLOC ": unable to list signals for invalid type id '%"G_GUINTPTR_FORMAT"'",
    1278                 :            :                     (guintptr) itype);
    1279   [ #  #  #  # ]:          0 :       else if (!G_TYPE_IS_INSTANTIATABLE (itype) && !G_TYPE_IS_INTERFACE (itype))
    1280                 :          0 :         g_critical (G_STRLOC ": unable to list signals of non instantiatable type '%s'",
    1281                 :            :                     g_type_name (itype));
    1282   [ #  #  #  # ]:          0 :       else if (!g_type_class_peek (itype) && !G_TYPE_IS_INTERFACE (itype))
    1283                 :          0 :         g_critical (G_STRLOC ": unable to list signals of unloaded type '%s'",
    1284                 :            :                     g_type_name (itype));
    1285                 :            :     }
    1286                 :            :   
    1287                 :        164 :   return (guint*) g_array_free (result, FALSE);
    1288                 :            : }
    1289                 :            : 
    1290                 :            : /**
    1291                 :            :  * g_signal_name:
    1292                 :            :  * @signal_id: the signal's identifying number.
    1293                 :            :  *
    1294                 :            :  * Given the signal's identifier, finds its name.
    1295                 :            :  *
    1296                 :            :  * Two different signals may have the same name, if they have differing types.
    1297                 :            :  *
    1298                 :            :  * Returns: (nullable): the signal name, or %NULL if the signal number was invalid.
    1299                 :            :  */
    1300                 :            : const gchar *
    1301                 :         29 : g_signal_name (guint signal_id)
    1302                 :            : {
    1303                 :            :   SignalNode *node;
    1304                 :            :   const gchar *name;
    1305                 :            :   
    1306                 :         29 :   SIGNAL_LOCK ();
    1307                 :         29 :   node = LOOKUP_SIGNAL_NODE (signal_id);
    1308         [ +  - ]:         29 :   name = node ? node->name : NULL;
    1309                 :         29 :   SIGNAL_UNLOCK ();
    1310                 :            :   
    1311                 :         29 :   return (char*) name;
    1312                 :            : }
    1313                 :            : 
    1314                 :            : /**
    1315                 :            :  * g_signal_query:
    1316                 :            :  * @signal_id: The signal id of the signal to query information for.
    1317                 :            :  * @query: (out caller-allocates) (not optional): A user provided structure that is
    1318                 :            :  *  filled in with constant values upon success.
    1319                 :            :  *
    1320                 :            :  * Queries the signal system for in-depth information about a
    1321                 :            :  * specific signal. This function will fill in a user-provided
    1322                 :            :  * structure to hold signal-specific information. If an invalid
    1323                 :            :  * signal id is passed in, the @signal_id member of the #GSignalQuery
    1324                 :            :  * is 0. All members filled into the #GSignalQuery structure should
    1325                 :            :  * be considered constant and have to be left untouched.
    1326                 :            :  */
    1327                 :            : void
    1328                 :         87 : g_signal_query (guint         signal_id,
    1329                 :            :                 GSignalQuery *query)
    1330                 :            : {
    1331                 :            :   SignalNode *node;
    1332                 :            :   
    1333                 :         87 :   g_return_if_fail (query != NULL);
    1334                 :            :   
    1335                 :         87 :   SIGNAL_LOCK ();
    1336                 :         87 :   node = LOOKUP_SIGNAL_NODE (signal_id);
    1337   [ +  -  -  + ]:         87 :   if (!node || node->destroyed)
    1338                 :          0 :     query->signal_id = 0;
    1339                 :            :   else
    1340                 :            :     {
    1341                 :         87 :       query->signal_id = node->signal_id;
    1342                 :         87 :       query->signal_name = node->name;
    1343                 :         87 :       query->itype = node->itype;
    1344                 :         87 :       query->signal_flags = node->flags;
    1345                 :         87 :       query->return_type = node->return_type;
    1346                 :         87 :       query->n_params = node->n_params;
    1347                 :         87 :       query->param_types = node->param_types;
    1348                 :            :     }
    1349                 :         87 :   SIGNAL_UNLOCK ();
    1350                 :            : }
    1351                 :            : 
    1352                 :            : /**
    1353                 :            :  * g_signal_new:
    1354                 :            :  * @signal_name: the name for the signal
    1355                 :            :  * @itype: the type this signal pertains to. It will also pertain to
    1356                 :            :  *  types which are derived from this type.
    1357                 :            :  * @signal_flags: a combination of #GSignalFlags specifying detail of when
    1358                 :            :  *  the default handler is to be invoked. You should at least specify
    1359                 :            :  *  %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST.
    1360                 :            :  * @class_offset: The offset of the function pointer in the class structure
    1361                 :            :  *  for this type. Used to invoke a class method generically. Pass 0 to
    1362                 :            :  *  not associate a class method slot with this signal.
    1363                 :            :  * @accumulator: (nullable) (scope forever): the accumulator for this signal; may be %NULL.
    1364                 :            :  * @accu_data: (nullable) (closure accumulator): user data for the @accumulator.
    1365                 :            :  * @c_marshaller: (nullable): the function to translate arrays of parameter
    1366                 :            :  *  values to signal emissions into C language callback invocations or %NULL.
    1367                 :            :  * @return_type: the type of return value, or %G_TYPE_NONE for a signal
    1368                 :            :  *  without a return value.
    1369                 :            :  * @n_params: the number of parameter types to follow.
    1370                 :            :  * @...: a list of types, one for each parameter.
    1371                 :            :  *
    1372                 :            :  * Creates a new signal. (This is usually done in the class initializer.)
    1373                 :            :  *
    1374                 :            :  * A signal name consists of segments consisting of ASCII letters and
    1375                 :            :  * digits, separated by either the `-` or `_` character. The first
    1376                 :            :  * character of a signal name must be a letter. Names which violate these
    1377                 :            :  * rules lead to undefined behaviour. These are the same rules as for property
    1378                 :            :  * naming (see g_param_spec_internal()).
    1379                 :            :  *
    1380                 :            :  * When registering a signal and looking up a signal, either separator can
    1381                 :            :  * be used, but they cannot be mixed. Using `-` is considerably more efficient.
    1382                 :            :  * Using `_` is discouraged.
    1383                 :            :  *
    1384                 :            :  * If 0 is used for @class_offset subclasses cannot override the class handler
    1385                 :            :  * in their class_init method by doing super_class->signal_handler = my_signal_handler.
    1386                 :            :  * Instead they will have to use g_signal_override_class_handler().
    1387                 :            :  *
    1388                 :            :  * If @c_marshaller is %NULL, g_cclosure_marshal_generic() will be used as
    1389                 :            :  * the marshaller for this signal. In some simple cases, g_signal_new()
    1390                 :            :  * will use a more optimized c_marshaller and va_marshaller for the signal
    1391                 :            :  * instead of g_cclosure_marshal_generic().
    1392                 :            :  *
    1393                 :            :  * If @c_marshaller is non-%NULL, you need to also specify a va_marshaller
    1394                 :            :  * using g_signal_set_va_marshaller() or the generic va_marshaller will
    1395                 :            :  * be used.
    1396                 :            :  *
    1397                 :            :  * Returns: the signal id
    1398                 :            :  */
    1399                 :            : guint
    1400                 :       1784 : g_signal_new (const gchar        *signal_name,
    1401                 :            :               GType               itype,
    1402                 :            :               GSignalFlags        signal_flags,
    1403                 :            :               guint               class_offset,
    1404                 :            :               GSignalAccumulator  accumulator,
    1405                 :            :               gpointer            accu_data,
    1406                 :            :               GSignalCMarshaller  c_marshaller,
    1407                 :            :               GType               return_type,
    1408                 :            :               guint               n_params,
    1409                 :            :               ...)
    1410                 :            : {
    1411                 :            :   va_list args;
    1412                 :            :   guint signal_id;
    1413                 :            : 
    1414                 :       1784 :   g_return_val_if_fail (signal_name != NULL, 0);
    1415                 :            :   
    1416                 :       1784 :   va_start (args, n_params);
    1417                 :            : 
    1418         [ +  + ]:       3507 :   signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
    1419                 :       1723 :                                    class_offset ? g_signal_type_cclosure_new (itype, class_offset) : NULL,
    1420                 :            :                                    accumulator, accu_data, c_marshaller,
    1421                 :            :                                    return_type, n_params, args);
    1422                 :            : 
    1423                 :       1784 :   va_end (args);
    1424                 :            : 
    1425                 :       1784 :   return signal_id;
    1426                 :            : }
    1427                 :            : 
    1428                 :            : /**
    1429                 :            :  * g_signal_new_class_handler:
    1430                 :            :  * @signal_name: the name for the signal
    1431                 :            :  * @itype: the type this signal pertains to. It will also pertain to
    1432                 :            :  *  types which are derived from this type.
    1433                 :            :  * @signal_flags: a combination of #GSignalFlags specifying detail of when
    1434                 :            :  *  the default handler is to be invoked. You should at least specify
    1435                 :            :  *  %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST.
    1436                 :            :  * @class_handler: (nullable) (scope forever): a #GCallback which acts as class implementation of
    1437                 :            :  *  this signal. Used to invoke a class method generically. Pass %NULL to
    1438                 :            :  *  not associate a class method with this signal.
    1439                 :            :  * @accumulator: (nullable) (scope forever): the accumulator for this signal; may be %NULL.
    1440                 :            :  * @accu_data: (nullable) (closure accumulator): user data for the @accumulator.
    1441                 :            :  * @c_marshaller: (nullable): the function to translate arrays of parameter
    1442                 :            :  *  values to signal emissions into C language callback invocations or %NULL.
    1443                 :            :  * @return_type: the type of return value, or %G_TYPE_NONE for a signal
    1444                 :            :  *  without a return value.
    1445                 :            :  * @n_params: the number of parameter types to follow.
    1446                 :            :  * @...: a list of types, one for each parameter.
    1447                 :            :  *
    1448                 :            :  * Creates a new signal. (This is usually done in the class initializer.)
    1449                 :            :  *
    1450                 :            :  * This is a variant of g_signal_new() that takes a C callback instead
    1451                 :            :  * of a class offset for the signal's class handler. This function
    1452                 :            :  * doesn't need a function pointer exposed in the class structure of
    1453                 :            :  * an object definition, instead the function pointer is passed
    1454                 :            :  * directly and can be overridden by derived classes with
    1455                 :            :  * g_signal_override_class_closure() or
    1456                 :            :  * g_signal_override_class_handler() and chained to with
    1457                 :            :  * g_signal_chain_from_overridden() or
    1458                 :            :  * g_signal_chain_from_overridden_handler().
    1459                 :            :  *
    1460                 :            :  * See g_signal_new() for information about signal names.
    1461                 :            :  *
    1462                 :            :  * If c_marshaller is %NULL, g_cclosure_marshal_generic() will be used as
    1463                 :            :  * the marshaller for this signal.
    1464                 :            :  *
    1465                 :            :  * Returns: the signal id
    1466                 :            :  *
    1467                 :            :  * Since: 2.18
    1468                 :            :  */
    1469                 :            : guint
    1470                 :          1 : g_signal_new_class_handler (const gchar        *signal_name,
    1471                 :            :                             GType               itype,
    1472                 :            :                             GSignalFlags        signal_flags,
    1473                 :            :                             GCallback           class_handler,
    1474                 :            :                             GSignalAccumulator  accumulator,
    1475                 :            :                             gpointer            accu_data,
    1476                 :            :                             GSignalCMarshaller  c_marshaller,
    1477                 :            :                             GType               return_type,
    1478                 :            :                             guint               n_params,
    1479                 :            :                             ...)
    1480                 :            : {
    1481                 :            :   va_list args;
    1482                 :            :   guint signal_id;
    1483                 :            : 
    1484                 :          1 :   g_return_val_if_fail (signal_name != NULL, 0);
    1485                 :            : 
    1486                 :          1 :   va_start (args, n_params);
    1487                 :            : 
    1488         [ +  - ]:          2 :   signal_id = g_signal_new_valist (signal_name, itype, signal_flags,
    1489                 :          1 :                                    class_handler ? g_cclosure_new (class_handler, NULL, NULL) : NULL,
    1490                 :            :                                    accumulator, accu_data, c_marshaller,
    1491                 :            :                                    return_type, n_params, args);
    1492                 :            : 
    1493                 :          1 :   va_end (args);
    1494                 :            : 
    1495                 :          1 :   return signal_id;
    1496                 :            : }
    1497                 :            : 
    1498                 :            : static inline ClassClosure*
    1499                 :   16806730 : signal_find_class_closure (SignalNode *node,
    1500                 :            :                            GType       itype)
    1501                 :            : {
    1502                 :   16806730 :   GBSearchArray *bsa = node->class_closure_bsa;
    1503                 :            :   ClassClosure *cc;
    1504                 :            : 
    1505         [ +  + ]:   16806730 :   if (bsa)
    1506                 :            :     {
    1507                 :            :       ClassClosure key;
    1508                 :            : 
    1509                 :            :       /* cc->instance_type is 0 for default closure */
    1510                 :            : 
    1511         [ +  + ]:   16787546 :       if (g_bsearch_array_get_n_nodes (bsa) == 1)
    1512                 :            :         {
    1513                 :   16787511 :           cc = g_bsearch_array_get_nth (bsa, &g_class_closure_bconfig, 0);
    1514   [ +  -  +  - ]:   16787511 :           if (cc && cc->instance_type == 0) /* check for default closure */
    1515                 :   16787511 :             return cc;
    1516                 :            :         }
    1517                 :            : 
    1518                 :         35 :       key.instance_type = itype;
    1519                 :         35 :       cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key);
    1520   [ +  +  +  - ]:         50 :       while (!cc && key.instance_type)
    1521                 :            :         {
    1522                 :         15 :           key.instance_type = g_type_parent (key.instance_type);
    1523                 :         15 :           cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key);
    1524                 :            :         }
    1525                 :            :     }
    1526                 :            :   else
    1527                 :      19184 :     cc = NULL;
    1528                 :      19219 :   return cc;
    1529                 :            : }
    1530                 :            : 
    1531                 :            : static inline GClosure*
    1532                 :   16806655 : signal_lookup_closure (SignalNode    *node,
    1533                 :            :                        GTypeInstance *instance)
    1534                 :            : {
    1535                 :            :   ClassClosure *cc;
    1536                 :            : 
    1537                 :   16806655 :   cc = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance));
    1538         [ +  + ]:   16806655 :   return cc ? cc->closure : NULL;
    1539                 :            : }
    1540                 :            : 
    1541                 :            : static void
    1542                 :       1732 : signal_add_class_closure (SignalNode *node,
    1543                 :            :                           GType       itype,
    1544                 :            :                           GClosure   *closure)
    1545                 :            : {
    1546                 :            :   ClassClosure key;
    1547                 :            : 
    1548                 :       1732 :   node->single_va_closure_is_valid = FALSE;
    1549                 :            : 
    1550         [ +  + ]:       1732 :   if (!node->class_closure_bsa)
    1551                 :       1725 :     node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig);
    1552                 :       1732 :   key.instance_type = itype;
    1553                 :       1732 :   key.closure = g_closure_ref (closure);
    1554                 :       1732 :   node->class_closure_bsa = g_bsearch_array_insert (node->class_closure_bsa,
    1555                 :            :                                                     &g_class_closure_bconfig,
    1556                 :            :                                                     &key);
    1557                 :       1732 :   g_closure_sink (closure);
    1558   [ +  -  +  -  :       1732 :   if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (closure))
                   +  - ]
    1559                 :            :     {
    1560                 :       1732 :       g_closure_set_marshal (closure, node->c_marshaller);
    1561         [ +  + ]:       1732 :       if (node->va_marshaller)
    1562                 :        635 :         _g_closure_set_va_marshal (closure, node->va_marshaller);
    1563                 :            :     }
    1564                 :       1732 : }
    1565                 :            : 
    1566                 :            : /**
    1567                 :            :  * g_signal_newv:
    1568                 :            :  * @signal_name: the name for the signal
    1569                 :            :  * @itype: the type this signal pertains to. It will also pertain to
    1570                 :            :  *     types which are derived from this type
    1571                 :            :  * @signal_flags: a combination of #GSignalFlags specifying detail of when
    1572                 :            :  *     the default handler is to be invoked. You should at least specify
    1573                 :            :  *     %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST
    1574                 :            :  * @class_closure: (nullable): The closure to invoke on signal emission;
    1575                 :            :  *     may be %NULL
    1576                 :            :  * @accumulator: (nullable) (scope forever): the accumulator for this signal; may be %NULL
    1577                 :            :  * @accu_data: (nullable) (closure accumulator): user data for the @accumulator
    1578                 :            :  * @c_marshaller: (nullable): the function to translate arrays of
    1579                 :            :  *     parameter values to signal emissions into C language callback
    1580                 :            :  *     invocations or %NULL
    1581                 :            :  * @return_type: the type of return value, or %G_TYPE_NONE for a signal
    1582                 :            :  *     without a return value
    1583                 :            :  * @n_params: the length of @param_types
    1584                 :            :  * @param_types: (array length=n_params) (nullable): an array of types, one for
    1585                 :            :  *     each parameter (may be %NULL if @n_params is zero)
    1586                 :            :  *
    1587                 :            :  * Creates a new signal. (This is usually done in the class initializer.)
    1588                 :            :  *
    1589                 :            :  * See g_signal_new() for details on allowed signal names.
    1590                 :            :  *
    1591                 :            :  * If c_marshaller is %NULL, g_cclosure_marshal_generic() will be used as
    1592                 :            :  * the marshaller for this signal.
    1593                 :            :  *
    1594                 :            :  * Returns: the signal id
    1595                 :            :  */
    1596                 :            : guint
    1597                 :       1786 : g_signal_newv (const gchar       *signal_name,
    1598                 :            :                GType              itype,
    1599                 :            :                GSignalFlags       signal_flags,
    1600                 :            :                GClosure          *class_closure,
    1601                 :            :                GSignalAccumulator accumulator,
    1602                 :            :                gpointer           accu_data,
    1603                 :            :                GSignalCMarshaller c_marshaller,
    1604                 :            :                GType              return_type,
    1605                 :            :                guint              n_params,
    1606                 :            :                GType             *param_types)
    1607                 :            : {
    1608                 :            :   const gchar *name;
    1609                 :       1786 :   gchar *signal_name_copy = NULL;
    1610                 :            :   guint signal_id, i;
    1611                 :            :   SignalNode *node;
    1612                 :            :   GSignalCMarshaller builtin_c_marshaller;
    1613                 :            :   GSignalCVaMarshaller builtin_va_marshaller;
    1614                 :            :   GSignalCVaMarshaller va_marshaller;
    1615                 :            :   
    1616                 :       1786 :   g_return_val_if_fail (signal_name != NULL, 0);
    1617                 :       1786 :   g_return_val_if_fail (g_signal_is_valid_name (signal_name), 0);
    1618                 :       1786 :   g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
    1619         [ +  + ]:       1786 :   if (n_params)
    1620                 :       1554 :     g_return_val_if_fail (param_types != NULL, 0);
    1621                 :       1786 :   g_return_val_if_fail ((return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == 0, 0);
    1622         [ +  + ]:       1786 :   if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE))
    1623                 :       1354 :     g_return_val_if_fail (accumulator == NULL, 0);
    1624         [ +  + ]:       1786 :   if (!accumulator)
    1625                 :       1366 :     g_return_val_if_fail (accu_data == NULL, 0);
    1626                 :       1786 :   g_return_val_if_fail ((signal_flags & G_SIGNAL_ACCUMULATOR_FIRST_RUN) == 0, 0);
    1627                 :            : 
    1628         [ +  + ]:       1786 :   if (!is_canonical (signal_name))
    1629                 :            :     {
    1630                 :          1 :       signal_name_copy = g_strdup (signal_name);
    1631                 :          1 :       canonicalize_key (signal_name_copy);
    1632                 :          1 :       name = signal_name_copy;
    1633                 :            :     }
    1634                 :            :   else
    1635                 :            :     {
    1636                 :       1785 :       name = signal_name;
    1637                 :            :     }
    1638                 :            :   
    1639                 :       1786 :   SIGNAL_LOCK ();
    1640                 :            :   
    1641                 :       1786 :   signal_id = signal_id_lookup (name, itype);
    1642                 :       1786 :   node = LOOKUP_SIGNAL_NODE (signal_id);
    1643   [ -  +  -  - ]:       1786 :   if (node && !node->destroyed)
    1644                 :            :     {
    1645         [ #  # ]:          0 :       g_critical (G_STRLOC ": signal \"%s\" already exists in the '%s' %s",
    1646                 :            :                   name,
    1647                 :            :                   type_debug_name (node->itype),
    1648                 :            :                   G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry");
    1649                 :          0 :       g_free (signal_name_copy);
    1650                 :          0 :       SIGNAL_UNLOCK ();
    1651                 :          0 :       return 0;
    1652                 :            :     }
    1653   [ -  +  -  - ]:       1786 :   if (node && node->itype != itype)
    1654                 :            :     {
    1655                 :          0 :       g_critical (G_STRLOC ": signal \"%s\" for type '%s' was previously created for type '%s'",
    1656                 :            :                   name,
    1657                 :            :                   type_debug_name (itype),
    1658                 :            :                   type_debug_name (node->itype));
    1659                 :          0 :       g_free (signal_name_copy);
    1660                 :          0 :       SIGNAL_UNLOCK ();
    1661                 :          0 :       return 0;
    1662                 :            :     }
    1663         [ +  + ]:       4758 :   for (i = 0; i < n_params; i++)
    1664         [ -  + ]:       2972 :     if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
    1665                 :            :       {
    1666                 :          0 :         g_critical (G_STRLOC ": parameter %d of type '%s' for signal \"%s::%s\" is not a value type",
    1667                 :            :                     i + 1, type_debug_name (param_types[i]), type_debug_name (itype), name);
    1668                 :          0 :         g_free (signal_name_copy);
    1669                 :          0 :         SIGNAL_UNLOCK ();
    1670                 :          0 :         return 0;
    1671                 :            :       }
    1672   [ +  +  -  + ]:       1786 :   if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
    1673                 :            :     {
    1674                 :          0 :       g_critical (G_STRLOC ": return value of type '%s' for signal \"%s::%s\" is not a value type",
    1675                 :            :                   type_debug_name (return_type), type_debug_name (itype), name);
    1676                 :          0 :       g_free (signal_name_copy);
    1677                 :          0 :       SIGNAL_UNLOCK ();
    1678                 :          0 :       return 0;
    1679                 :            :     }
    1680                 :            :   
    1681                 :            :   /* setup permanent portion of signal node */
    1682         [ +  - ]:       1786 :   if (!node)
    1683                 :            :     {
    1684                 :            :       SignalKey key;
    1685                 :            :       
    1686                 :       1786 :       signal_id = g_n_signal_nodes++;
    1687                 :       1786 :       node = g_new (SignalNode, 1);
    1688                 :       1786 :       node->signal_id = signal_id;
    1689                 :       1786 :       g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes);
    1690                 :       1786 :       g_signal_nodes[signal_id] = node;
    1691                 :       1786 :       node->itype = itype;
    1692                 :       1786 :       key.itype = itype;
    1693                 :       1786 :       key.signal_id = signal_id;
    1694                 :       1786 :       node->name = g_intern_string (name);
    1695                 :       1786 :       key.quark = g_quark_from_string (name);
    1696                 :       1786 :       g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key);
    1697                 :            : 
    1698                 :       1786 :       TRACE(GOBJECT_SIGNAL_NEW(signal_id, name, itype));
    1699                 :            :     }
    1700                 :       1786 :   node->destroyed = FALSE;
    1701                 :            : 
    1702                 :            :   /* setup reinitializable portion */
    1703                 :       1786 :   node->single_va_closure_is_valid = FALSE;
    1704                 :       1786 :   node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
    1705                 :       1786 :   node->n_params = n_params;
    1706                 :       1786 :   node->param_types = g_memdup2 (param_types, sizeof (GType) * n_params);
    1707                 :       1786 :   node->return_type = return_type;
    1708                 :       1786 :   node->class_closure_bsa = NULL;
    1709         [ +  + ]:       1786 :   if (accumulator)
    1710                 :            :     {
    1711                 :        420 :       node->accumulator = g_new (SignalAccumulator, 1);
    1712                 :        420 :       node->accumulator->func = accumulator;
    1713                 :        420 :       node->accumulator->data = accu_data;
    1714                 :            :     }
    1715                 :            :   else
    1716                 :       1366 :     node->accumulator = NULL;
    1717                 :            : 
    1718                 :       1786 :   builtin_c_marshaller = NULL;
    1719                 :       1786 :   builtin_va_marshaller = NULL;
    1720                 :            : 
    1721                 :            :   /* Pick up built-in va marshallers for standard types, and
    1722                 :            :      instead of generic marshaller if no marshaller specified */
    1723   [ +  +  +  + ]:       1786 :   if (n_params == 0 && return_type == G_TYPE_NONE)
    1724                 :            :     {
    1725                 :        205 :       builtin_c_marshaller = g_cclosure_marshal_VOID__VOID;
    1726                 :        205 :       builtin_va_marshaller = g_cclosure_marshal_VOID__VOIDv;
    1727                 :            :     }
    1728   [ +  +  +  + ]:       1581 :   else if (n_params == 1 && return_type == G_TYPE_NONE)
    1729                 :            :     {
    1730                 :            : #define ADD_CHECK(__type__) \
    1731                 :            :       else if (g_type_is_a (param_types[0] & ~G_SIGNAL_TYPE_STATIC_SCOPE, G_TYPE_ ##__type__))         \
    1732                 :            :         {                                                                \
    1733                 :            :           builtin_c_marshaller = g_cclosure_marshal_VOID__ ## __type__;  \
    1734                 :            :           builtin_va_marshaller = g_cclosure_marshal_VOID__ ## __type__ ##v;     \
    1735                 :            :         }
    1736                 :            : 
    1737                 :            :       if (0) {}
    1738   [ +  +  -  + ]:        484 :       ADD_CHECK (BOOLEAN)
    1739   [ +  -  -  + ]:        462 :       ADD_CHECK (CHAR)
    1740   [ +  -  -  + ]:        462 :       ADD_CHECK (UCHAR)
    1741   [ +  +  -  + ]:        462 :       ADD_CHECK (INT)
    1742   [ +  -  -  + ]:        452 :       ADD_CHECK (UINT)
    1743   [ +  -  -  + ]:        452 :       ADD_CHECK (LONG)
    1744   [ +  -  -  + ]:        452 :       ADD_CHECK (ULONG)
    1745   [ +  -  +  + ]:        452 :       ADD_CHECK (ENUM)
    1746   [ +  -  -  + ]:        447 :       ADD_CHECK (FLAGS)
    1747   [ +  -  -  + ]:        447 :       ADD_CHECK (FLOAT)
    1748   [ +  +  -  + ]:        447 :       ADD_CHECK (DOUBLE)
    1749   [ +  +  -  + ]:        446 :       ADD_CHECK (STRING)
    1750   [ +  +  -  + ]:        402 :       ADD_CHECK (PARAM)
    1751   [ +  -  -  + ]:         83 :       ADD_CHECK (BOXED)
    1752   [ +  +  -  + ]:         83 :       ADD_CHECK (POINTER)
    1753   [ +  +  +  + ]:         82 :       ADD_CHECK (OBJECT)
    1754   [ -  +  -  - ]:         16 :       ADD_CHECK (VARIANT)
    1755                 :            :     }
    1756                 :            : 
    1757         [ +  + ]:       1786 :   if (c_marshaller == NULL)
    1758                 :            :     {
    1759         [ +  + ]:        680 :       if (builtin_c_marshaller)
    1760                 :            :         {
    1761                 :        659 :           c_marshaller = builtin_c_marshaller;
    1762                 :        659 :           va_marshaller = builtin_va_marshaller;
    1763                 :            :         }
    1764                 :            :       else
    1765                 :            :         {
    1766                 :         21 :           c_marshaller = g_cclosure_marshal_generic;
    1767                 :         21 :           va_marshaller = g_cclosure_marshal_generic_va;
    1768                 :            :         }
    1769                 :            :     }
    1770                 :            :   else
    1771                 :       1106 :     va_marshaller = NULL;
    1772                 :            : 
    1773                 :       1786 :   node->c_marshaller = c_marshaller;
    1774                 :       1786 :   node->va_marshaller = va_marshaller;
    1775                 :       1786 :   node->emission_hooks = NULL;
    1776         [ +  + ]:       1786 :   if (class_closure)
    1777                 :       1725 :     signal_add_class_closure (node, 0, class_closure);
    1778                 :            : 
    1779                 :       1786 :   SIGNAL_UNLOCK ();
    1780                 :            : 
    1781                 :       1786 :   g_free (signal_name_copy);
    1782                 :            : 
    1783                 :       1786 :   return signal_id;
    1784                 :            : }
    1785                 :            : 
    1786                 :            : /**
    1787                 :            :  * g_signal_set_va_marshaller:
    1788                 :            :  * @signal_id: the signal id
    1789                 :            :  * @instance_type: the instance type on which to set the marshaller.
    1790                 :            :  * @va_marshaller: the marshaller to set.
    1791                 :            :  *
    1792                 :            :  * Change the #GSignalCVaMarshaller used for a given signal.  This is a
    1793                 :            :  * specialised form of the marshaller that can often be used for the
    1794                 :            :  * common case of a single connected signal handler and avoids the
    1795                 :            :  * overhead of #GValue.  Its use is optional.
    1796                 :            :  *
    1797                 :            :  * Since: 2.32
    1798                 :            :  */
    1799                 :            : void
    1800                 :        986 : g_signal_set_va_marshaller (guint              signal_id,
    1801                 :            :                             GType              instance_type,
    1802                 :            :                             GSignalCVaMarshaller va_marshaller)
    1803                 :            : {
    1804                 :            :   SignalNode *node;
    1805                 :            :   
    1806                 :        986 :   g_return_if_fail (signal_id > 0);
    1807                 :        986 :   g_return_if_fail (va_marshaller != NULL);
    1808                 :            :   
    1809                 :        986 :   SIGNAL_LOCK ();
    1810                 :        986 :   node = LOOKUP_SIGNAL_NODE (signal_id);
    1811         [ +  - ]:        986 :   if (node)
    1812                 :            :     {
    1813                 :        986 :       node->va_marshaller = va_marshaller;
    1814         [ +  + ]:        986 :       if (node->class_closure_bsa)
    1815                 :            :         {
    1816                 :        978 :           ClassClosure *cc = g_bsearch_array_get_nth (node->class_closure_bsa, &g_class_closure_bconfig, 0);
    1817         [ +  - ]:        978 :           if (cc->closure->marshal == node->c_marshaller)
    1818                 :        978 :             _g_closure_set_va_marshal (cc->closure, va_marshaller);
    1819                 :            :         }
    1820                 :            : 
    1821                 :        986 :       node->single_va_closure_is_valid = FALSE;
    1822                 :            :     }
    1823                 :            : 
    1824                 :        986 :   SIGNAL_UNLOCK ();
    1825                 :            : }
    1826                 :            : 
    1827                 :            : 
    1828                 :            : /**
    1829                 :            :  * g_signal_new_valist:
    1830                 :            :  * @signal_name: the name for the signal
    1831                 :            :  * @itype: the type this signal pertains to. It will also pertain to
    1832                 :            :  *  types which are derived from this type.
    1833                 :            :  * @signal_flags: a combination of #GSignalFlags specifying detail of when
    1834                 :            :  *  the default handler is to be invoked. You should at least specify
    1835                 :            :  *  %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST.
    1836                 :            :  * @class_closure: (nullable): The closure to invoke on signal emission; may be %NULL.
    1837                 :            :  * @accumulator: (nullable) (scope forever): the accumulator for this signal; may be %NULL.
    1838                 :            :  * @accu_data: (nullable) (closure accumulator): user data for the @accumulator.
    1839                 :            :  * @c_marshaller: (nullable): the function to translate arrays of parameter
    1840                 :            :  *  values to signal emissions into C language callback invocations or %NULL.
    1841                 :            :  * @return_type: the type of return value, or %G_TYPE_NONE for a signal
    1842                 :            :  *  without a return value.
    1843                 :            :  * @n_params: the number of parameter types in @args.
    1844                 :            :  * @args: va_list of #GType, one for each parameter.
    1845                 :            :  *
    1846                 :            :  * Creates a new signal. (This is usually done in the class initializer.)
    1847                 :            :  *
    1848                 :            :  * See g_signal_new() for details on allowed signal names.
    1849                 :            :  *
    1850                 :            :  * If c_marshaller is %NULL, g_cclosure_marshal_generic() will be used as
    1851                 :            :  * the marshaller for this signal.
    1852                 :            :  *
    1853                 :            :  * Returns: the signal id
    1854                 :            :  */
    1855                 :            : guint
    1856                 :       1785 : g_signal_new_valist (const gchar       *signal_name,
    1857                 :            :                      GType              itype,
    1858                 :            :                      GSignalFlags       signal_flags,
    1859                 :            :                      GClosure          *class_closure,
    1860                 :            :                      GSignalAccumulator accumulator,
    1861                 :            :                      gpointer           accu_data,
    1862                 :            :                      GSignalCMarshaller c_marshaller,
    1863                 :            :                      GType              return_type,
    1864                 :            :                      guint              n_params,
    1865                 :            :                      va_list            args)
    1866                 :            : {
    1867                 :            :   /* Somewhat arbitrarily reserve 200 bytes. That should cover the majority
    1868                 :            :    * of cases where n_params is small and still be small enough for what we
    1869                 :            :    * want to put on the stack. */
    1870                 :            :   GType param_types_stack[200 / sizeof (GType)];
    1871                 :       1785 :   GType *param_types_heap = NULL;
    1872                 :            :   GType *param_types;
    1873                 :            :   guint i;
    1874                 :            :   guint signal_id;
    1875                 :            : 
    1876                 :       1785 :   param_types = param_types_stack;
    1877         [ +  + ]:       1785 :   if (n_params > 0)
    1878                 :            :     {
    1879         [ -  + ]:       1554 :       if (G_UNLIKELY (n_params > G_N_ELEMENTS (param_types_stack)))
    1880                 :            :         {
    1881                 :          0 :           param_types_heap = g_new (GType, n_params);
    1882                 :          0 :           param_types = param_types_heap;
    1883                 :            :         }
    1884                 :            : 
    1885         [ +  + ]:       4526 :       for (i = 0; i < n_params; i++)
    1886                 :       2972 :         param_types[i] = va_arg (args, GType);
    1887                 :            :     }
    1888                 :            : 
    1889                 :       1785 :   signal_id = g_signal_newv (signal_name, itype, signal_flags,
    1890                 :            :                              class_closure, accumulator, accu_data, c_marshaller,
    1891                 :            :                              return_type, n_params, param_types);
    1892                 :       1785 :   g_free (param_types_heap);
    1893                 :            : 
    1894                 :       1785 :   return signal_id;
    1895                 :            : }
    1896                 :            : 
    1897                 :            : static void
    1898                 :          0 : signal_destroy_R (SignalNode *signal_node)
    1899                 :            : {
    1900                 :          0 :   SignalNode node = *signal_node;
    1901                 :            : 
    1902                 :          0 :   signal_node->destroyed = TRUE;
    1903                 :            :   
    1904                 :            :   /* reentrancy caution, zero out real contents first */
    1905                 :          0 :   signal_node->single_va_closure_is_valid = FALSE;
    1906                 :          0 :   signal_node->n_params = 0;
    1907                 :          0 :   signal_node->param_types = NULL;
    1908                 :          0 :   signal_node->return_type = 0;
    1909                 :          0 :   signal_node->class_closure_bsa = NULL;
    1910                 :          0 :   signal_node->accumulator = NULL;
    1911                 :          0 :   signal_node->c_marshaller = NULL;
    1912                 :          0 :   signal_node->va_marshaller = NULL;
    1913                 :          0 :   signal_node->emission_hooks = NULL;
    1914                 :            :   
    1915                 :            : #ifdef  G_ENABLE_DEBUG
    1916                 :            :   /* check current emissions */
    1917                 :            :   {
    1918                 :            :     Emission *emission;
    1919                 :            :     
    1920         [ #  # ]:          0 :     for (emission = g_emissions; emission; emission = emission->next)
    1921         [ #  # ]:          0 :       if (emission->ihint.signal_id == node.signal_id)
    1922                 :          0 :         g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance '%p')",
    1923                 :            :                     node.name, emission->instance);
    1924                 :            :   }
    1925                 :            : #endif
    1926                 :            :   
    1927                 :            :   /* free contents that need to
    1928                 :            :    */
    1929                 :          0 :   SIGNAL_UNLOCK ();
    1930                 :          0 :   g_free (node.param_types);
    1931         [ #  # ]:          0 :   if (node.class_closure_bsa)
    1932                 :            :     {
    1933                 :            :       guint i;
    1934                 :            : 
    1935         [ #  # ]:          0 :       for (i = 0; i < node.class_closure_bsa->n_nodes; i++)
    1936                 :            :         {
    1937                 :          0 :           ClassClosure *cc = g_bsearch_array_get_nth (node.class_closure_bsa, &g_class_closure_bconfig, i);
    1938                 :            : 
    1939                 :          0 :           g_closure_unref (cc->closure);
    1940                 :            :         }
    1941                 :          0 :       g_bsearch_array_free (node.class_closure_bsa, &g_class_closure_bconfig);
    1942                 :            :     }
    1943                 :          0 :   g_free (node.accumulator);
    1944         [ #  # ]:          0 :   if (node.emission_hooks)
    1945                 :            :     {
    1946                 :          0 :       g_hook_list_clear (node.emission_hooks);
    1947                 :          0 :       g_free (node.emission_hooks);
    1948                 :            :     }
    1949                 :          0 :   SIGNAL_LOCK ();
    1950                 :          0 : }
    1951                 :            : 
    1952                 :            : /**
    1953                 :            :  * g_signal_override_class_closure:
    1954                 :            :  * @signal_id: the signal id
    1955                 :            :  * @instance_type: the instance type on which to override the class closure
    1956                 :            :  *  for the signal.
    1957                 :            :  * @class_closure: the closure.
    1958                 :            :  *
    1959                 :            :  * Overrides the class closure (i.e. the default handler) for the given signal
    1960                 :            :  * for emissions on instances of @instance_type. @instance_type must be derived
    1961                 :            :  * from the type to which the signal belongs.
    1962                 :            :  *
    1963                 :            :  * See g_signal_chain_from_overridden() and
    1964                 :            :  * g_signal_chain_from_overridden_handler() for how to chain up to the
    1965                 :            :  * parent class closure from inside the overridden one.
    1966                 :            :  */
    1967                 :            : void
    1968                 :          7 : g_signal_override_class_closure (guint     signal_id,
    1969                 :            :                                  GType     instance_type,
    1970                 :            :                                  GClosure *class_closure)
    1971                 :            : {
    1972                 :            :   SignalNode *node;
    1973                 :            :   
    1974                 :          7 :   g_return_if_fail (signal_id > 0);
    1975                 :          7 :   g_return_if_fail (class_closure != NULL);
    1976                 :            :   
    1977                 :          7 :   SIGNAL_LOCK ();
    1978                 :          7 :   node = LOOKUP_SIGNAL_NODE (signal_id);
    1979                 :          7 :   node_check_deprecated (node);
    1980   [ +  -  -  + ]:          7 :   if (!g_type_is_a (instance_type, node->itype))
    1981                 :          0 :     g_critical ("%s: type '%s' cannot be overridden for signal id '%u'", G_STRLOC, type_debug_name (instance_type), signal_id);
    1982                 :            :   else
    1983                 :            :     {
    1984                 :          7 :       ClassClosure *cc = signal_find_class_closure (node, instance_type);
    1985                 :            :       
    1986   [ +  -  -  + ]:          7 :       if (cc && cc->instance_type == instance_type)
    1987                 :          0 :         g_critical ("%s: type '%s' is already overridden for signal id '%u'", G_STRLOC, type_debug_name (instance_type), signal_id);
    1988                 :            :       else
    1989                 :          7 :         signal_add_class_closure (node, instance_type, class_closure);
    1990                 :            :     }
    1991                 :          7 :   SIGNAL_UNLOCK ();
    1992                 :            : }
    1993                 :            : 
    1994                 :            : /**
    1995                 :            :  * g_signal_override_class_handler:
    1996                 :            :  * @signal_name: the name for the signal
    1997                 :            :  * @instance_type: the instance type on which to override the class handler
    1998                 :            :  *  for the signal.
    1999                 :            :  * @class_handler: (scope forever): the handler.
    2000                 :            :  *
    2001                 :            :  * Overrides the class closure (i.e. the default handler) for the
    2002                 :            :  * given signal for emissions on instances of @instance_type with
    2003                 :            :  * callback @class_handler. @instance_type must be derived from the
    2004                 :            :  * type to which the signal belongs.
    2005                 :            :  *
    2006                 :            :  * See g_signal_chain_from_overridden() and
    2007                 :            :  * g_signal_chain_from_overridden_handler() for how to chain up to the
    2008                 :            :  * parent class closure from inside the overridden one.
    2009                 :            :  *
    2010                 :            :  * Since: 2.18
    2011                 :            :  */
    2012                 :            : void
    2013                 :          2 : g_signal_override_class_handler (const gchar *signal_name,
    2014                 :            :                                  GType        instance_type,
    2015                 :            :                                  GCallback    class_handler)
    2016                 :            : {
    2017                 :            :   guint signal_id;
    2018                 :            : 
    2019                 :          2 :   g_return_if_fail (signal_name != NULL);
    2020                 :          2 :   g_return_if_fail (instance_type != G_TYPE_NONE);
    2021                 :          2 :   g_return_if_fail (class_handler != NULL);
    2022                 :            : 
    2023                 :          2 :   signal_id = g_signal_lookup (signal_name, instance_type);
    2024                 :            : 
    2025         [ +  - ]:          2 :   if (signal_id)
    2026                 :          2 :     g_signal_override_class_closure (signal_id, instance_type,
    2027                 :            :                                      g_cclosure_new (class_handler, NULL, NULL));
    2028                 :            :   else
    2029                 :          0 :     g_critical ("%s: signal name '%s' is invalid for type id '%"G_GUINTPTR_FORMAT"'",
    2030                 :            :                 G_STRLOC, signal_name, (guintptr) instance_type);
    2031                 :            : 
    2032                 :            : }
    2033                 :            : 
    2034                 :            : /**
    2035                 :            :  * g_signal_chain_from_overridden:
    2036                 :            :  * @instance_and_params: (array): the argument list of the signal emission.
    2037                 :            :  *  The first element in the array is a #GValue for the instance the signal
    2038                 :            :  *  is being emitted on. The rest are any arguments to be passed to the signal.
    2039                 :            :  * @return_value: Location for the return value.
    2040                 :            :  *
    2041                 :            :  * Calls the original class closure of a signal. This function should only
    2042                 :            :  * be called from an overridden class closure; see
    2043                 :            :  * g_signal_override_class_closure() and
    2044                 :            :  * g_signal_override_class_handler().
    2045                 :            :  */
    2046                 :            : void
    2047                 :          9 : g_signal_chain_from_overridden (const GValue *instance_and_params,
    2048                 :            :                                 GValue       *return_value)
    2049                 :            : {
    2050                 :          9 :   GType chain_type = 0, restore_type = 0;
    2051                 :          9 :   Emission *emission = NULL;
    2052                 :          9 :   GClosure *closure = NULL;
    2053                 :          9 :   guint n_params = 0;
    2054                 :            :   gpointer instance;
    2055                 :            :   
    2056                 :          9 :   g_return_if_fail (instance_and_params != NULL);
    2057                 :          9 :   instance = g_value_peek_pointer (instance_and_params);
    2058                 :          9 :   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
    2059                 :            :   
    2060                 :          9 :   SIGNAL_LOCK ();
    2061                 :          9 :   emission = emission_find_innermost (instance);
    2062         [ +  - ]:          9 :   if (emission)
    2063                 :            :     {
    2064                 :          9 :       SignalNode *node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id);
    2065                 :            :       
    2066                 :          9 :       g_assert (node != NULL);  /* paranoid */
    2067                 :            :       
    2068                 :            :       /* we should probably do the same parameter checks as g_signal_emit() here.
    2069                 :            :        */
    2070         [ +  - ]:          9 :       if (emission->chain_type != G_TYPE_NONE)
    2071                 :            :         {
    2072                 :          9 :           ClassClosure *cc = signal_find_class_closure (node, emission->chain_type);
    2073                 :            :           
    2074                 :          9 :           g_assert (cc != NULL);        /* closure currently in call stack */
    2075                 :            : 
    2076                 :          9 :           n_params = node->n_params;
    2077                 :          9 :           restore_type = cc->instance_type;
    2078                 :          9 :           cc = signal_find_class_closure (node, g_type_parent (cc->instance_type));
    2079   [ +  -  +  - ]:          9 :           if (cc && cc->instance_type != restore_type)
    2080                 :            :             {
    2081                 :          9 :               closure = cc->closure;
    2082                 :          9 :               chain_type = cc->instance_type;
    2083                 :            :             }
    2084                 :            :         }
    2085                 :            :       else
    2086                 :          0 :         g_critical ("%s: signal id '%u' cannot be chained from current emission stage for instance '%p'", G_STRLOC, node->signal_id, instance);
    2087                 :            :     }
    2088                 :            :   else
    2089                 :          0 :     g_critical ("%s: no signal is currently being emitted for instance '%p'", G_STRLOC, instance);
    2090                 :            : 
    2091         [ +  - ]:          9 :   if (closure)
    2092                 :            :     {
    2093                 :          9 :       emission->chain_type = chain_type;
    2094                 :          9 :       SIGNAL_UNLOCK ();
    2095                 :          9 :       g_closure_invoke (closure,
    2096                 :            :                         return_value,
    2097                 :            :                         n_params + 1,
    2098                 :            :                         instance_and_params,
    2099                 :          9 :                         &emission->ihint);
    2100                 :          9 :       SIGNAL_LOCK ();
    2101                 :          9 :       emission->chain_type = restore_type;
    2102                 :            :     }
    2103                 :          9 :   SIGNAL_UNLOCK ();
    2104                 :            : }
    2105                 :            : 
    2106                 :            : /**
    2107                 :            :  * g_signal_chain_from_overridden_handler: (skip)
    2108                 :            :  * @instance: (type GObject.TypeInstance): the instance the signal is being
    2109                 :            :  *    emitted on.
    2110                 :            :  * @...: parameters to be passed to the parent class closure, followed by a
    2111                 :            :  *  location for the return value. If the return type of the signal
    2112                 :            :  *  is %G_TYPE_NONE, the return value location can be omitted.
    2113                 :            :  *
    2114                 :            :  * Calls the original class closure of a signal. This function should
    2115                 :            :  * only be called from an overridden class closure; see
    2116                 :            :  * g_signal_override_class_closure() and
    2117                 :            :  * g_signal_override_class_handler().
    2118                 :            :  *
    2119                 :            :  * Since: 2.18
    2120                 :            :  */
    2121                 :            : void
    2122                 :          3 : g_signal_chain_from_overridden_handler (gpointer instance,
    2123                 :            :                                         ...)
    2124                 :            : {
    2125                 :          3 :   GType chain_type = 0, restore_type = 0;
    2126                 :          3 :   Emission *emission = NULL;
    2127                 :          3 :   GClosure *closure = NULL;
    2128                 :          3 :   SignalNode *node = NULL;
    2129                 :          3 :   guint n_params = 0;
    2130                 :            : 
    2131                 :          3 :   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
    2132                 :            : 
    2133                 :          3 :   SIGNAL_LOCK ();
    2134                 :          3 :   emission = emission_find_innermost (instance);
    2135         [ +  - ]:          3 :   if (emission)
    2136                 :            :     {
    2137                 :          3 :       node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id);
    2138                 :            : 
    2139                 :          3 :       g_assert (node != NULL);  /* paranoid */
    2140                 :            : 
    2141                 :            :       /* we should probably do the same parameter checks as g_signal_emit() here.
    2142                 :            :        */
    2143         [ +  - ]:          3 :       if (emission->chain_type != G_TYPE_NONE)
    2144                 :            :         {
    2145                 :          3 :           ClassClosure *cc = signal_find_class_closure (node, emission->chain_type);
    2146                 :            : 
    2147                 :          3 :           g_assert (cc != NULL);        /* closure currently in call stack */
    2148                 :            : 
    2149                 :          3 :           n_params = node->n_params;
    2150                 :          3 :           restore_type = cc->instance_type;
    2151                 :          3 :           cc = signal_find_class_closure (node, g_type_parent (cc->instance_type));
    2152   [ +  -  +  - ]:          3 :           if (cc && cc->instance_type != restore_type)
    2153                 :            :             {
    2154                 :          3 :               closure = cc->closure;
    2155                 :          3 :               chain_type = cc->instance_type;
    2156                 :            :             }
    2157                 :            :         }
    2158                 :            :       else
    2159                 :          0 :         g_critical ("%s: signal id '%u' cannot be chained from current emission stage for instance '%p'", G_STRLOC, node->signal_id, instance);
    2160                 :            :     }
    2161                 :            :   else
    2162                 :          0 :     g_critical ("%s: no signal is currently being emitted for instance '%p'", G_STRLOC, instance);
    2163                 :            : 
    2164         [ +  - ]:          3 :   if (closure)
    2165                 :            :     {
    2166                 :            :       GValue *instance_and_params;
    2167                 :            :       GType signal_return_type;
    2168                 :            :       GValue *param_values;
    2169                 :            :       va_list var_args;
    2170                 :            :       guint i;
    2171                 :            : 
    2172                 :          3 :       va_start (var_args, instance);
    2173                 :            : 
    2174                 :          3 :       signal_return_type = node->return_type;
    2175         [ +  - ]:          3 :       instance_and_params = g_newa0 (GValue, n_params + 1);
    2176                 :          3 :       param_values = instance_and_params + 1;
    2177                 :            : 
    2178         [ +  + ]:          9 :       for (i = 0; i < node->n_params; i++)
    2179                 :            :         {
    2180                 :            :           gchar *error;
    2181                 :          6 :           GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
    2182                 :          6 :           gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
    2183                 :            : 
    2184                 :          6 :           SIGNAL_UNLOCK ();
    2185   [ -  +  -  -  :         12 :           G_VALUE_COLLECT_INIT (param_values + i, ptype,
          -  -  +  -  +  
                      + ]
    2186                 :            :                                 var_args,
    2187                 :            :                                 static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
    2188                 :            :                                 &error);
    2189         [ -  + ]:          6 :           if (error)
    2190                 :            :             {
    2191                 :          0 :               g_critical ("%s: %s", G_STRLOC, error);
    2192                 :          0 :               g_free (error);
    2193                 :            : 
    2194                 :            :               /* we purposely leak the value here, it might not be
    2195                 :            :                * in a correct state if an error condition occurred
    2196                 :            :                */
    2197         [ #  # ]:          0 :               while (i--)
    2198                 :          0 :                 g_value_unset (param_values + i);
    2199                 :            : 
    2200                 :          0 :               va_end (var_args);
    2201                 :          0 :               return;
    2202                 :            :             }
    2203                 :          6 :           SIGNAL_LOCK ();
    2204                 :            :         }
    2205                 :            : 
    2206                 :          3 :       SIGNAL_UNLOCK ();
    2207                 :          3 :       g_value_init_from_instance (instance_and_params, instance);
    2208                 :          3 :       SIGNAL_LOCK ();
    2209                 :            : 
    2210                 :          3 :       emission->chain_type = chain_type;
    2211                 :          3 :       SIGNAL_UNLOCK ();
    2212                 :            : 
    2213         [ -  + ]:          3 :       if (signal_return_type == G_TYPE_NONE)
    2214                 :            :         {
    2215                 :          0 :           g_closure_invoke (closure,
    2216                 :            :                             NULL,
    2217                 :            :                             n_params + 1,
    2218                 :            :                             instance_and_params,
    2219                 :          0 :                             &emission->ihint);
    2220                 :            :         }
    2221                 :            :       else
    2222                 :            :         {
    2223                 :          3 :           GValue return_value = G_VALUE_INIT;
    2224                 :          3 :           gchar *error = NULL;
    2225                 :          3 :           GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
    2226                 :          3 :           gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
    2227                 :            : 
    2228                 :          3 :           g_value_init (&return_value, rtype);
    2229                 :            : 
    2230                 :          3 :           g_closure_invoke (closure,
    2231                 :            :                             &return_value,
    2232                 :            :                             n_params + 1,
    2233                 :            :                             instance_and_params,
    2234                 :          3 :                             &emission->ihint);
    2235                 :            : 
    2236   [ -  +  -  -  :          6 :           G_VALUE_LCOPY (&return_value,
          -  -  +  -  +  
                      + ]
    2237                 :            :                          var_args,
    2238                 :            :                          static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
    2239                 :            :                          &error);
    2240         [ +  - ]:          3 :           if (!error)
    2241                 :            :             {
    2242                 :          3 :               g_value_unset (&return_value);
    2243                 :            :             }
    2244                 :            :           else
    2245                 :            :             {
    2246                 :          0 :               g_critical ("%s: %s", G_STRLOC, error);
    2247                 :          0 :               g_free (error);
    2248                 :            : 
    2249                 :            :               /* we purposely leak the value here, it might not be
    2250                 :            :                * in a correct state if an error condition occurred
    2251                 :            :                */
    2252                 :            :             }
    2253                 :            :         }
    2254                 :            : 
    2255         [ +  + ]:          9 :       for (i = 0; i < n_params; i++)
    2256                 :          6 :         g_value_unset (param_values + i);
    2257                 :          3 :       g_value_unset (instance_and_params);
    2258                 :            : 
    2259                 :          3 :       va_end (var_args);
    2260                 :            : 
    2261                 :          3 :       SIGNAL_LOCK ();
    2262                 :          3 :       emission->chain_type = restore_type;
    2263                 :            :     }
    2264                 :          3 :   SIGNAL_UNLOCK ();
    2265                 :            : }
    2266                 :            : 
    2267                 :            : /**
    2268                 :            :  * g_signal_get_invocation_hint:
    2269                 :            :  * @instance: (type GObject.Object): the instance to query
    2270                 :            :  *
    2271                 :            :  * Returns the invocation hint of the innermost signal emission of instance.
    2272                 :            :  *
    2273                 :            :  * Returns: (transfer none) (nullable): the invocation hint of the innermost
    2274                 :            :  *     signal emission, or %NULL if not found.
    2275                 :            :  */
    2276                 :            : GSignalInvocationHint*
    2277                 :         12 : g_signal_get_invocation_hint (gpointer instance)
    2278                 :            : {
    2279                 :         12 :   Emission *emission = NULL;
    2280                 :            :   
    2281                 :         12 :   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), NULL);
    2282                 :            : 
    2283                 :         12 :   SIGNAL_LOCK ();
    2284                 :         12 :   emission = emission_find_innermost (instance);
    2285                 :         12 :   SIGNAL_UNLOCK ();
    2286                 :            :   
    2287         [ +  - ]:         12 :   return emission ? &emission->ihint : NULL;
    2288                 :            : }
    2289                 :            : 
    2290                 :            : /**
    2291                 :            :  * g_signal_connect_closure_by_id:
    2292                 :            :  * @instance: (type GObject.Object): the instance to connect to.
    2293                 :            :  * @signal_id: the id of the signal.
    2294                 :            :  * @detail: the detail.
    2295                 :            :  * @closure: (not nullable): the closure to connect.
    2296                 :            :  * @after: whether the handler should be called before or after the
    2297                 :            :  *  default handler of the signal.
    2298                 :            :  *
    2299                 :            :  * Connects a closure to a signal for a particular object.
    2300                 :            :  *
    2301                 :            :  * If @closure is a floating reference (see g_closure_sink()), this function
    2302                 :            :  * takes ownership of @closure.
    2303                 :            :  *
    2304                 :            :  * This function cannot fail. If the given signal doesn’t exist, a critical
    2305                 :            :  * warning is emitted.
    2306                 :            :  *
    2307                 :            :  * Returns: the handler ID (always greater than 0)
    2308                 :            :  */
    2309                 :            : gulong
    2310                 :        338 : g_signal_connect_closure_by_id (gpointer  instance,
    2311                 :            :                                 guint     signal_id,
    2312                 :            :                                 GQuark    detail,
    2313                 :            :                                 GClosure *closure,
    2314                 :            :                                 gboolean  after)
    2315                 :            : {
    2316                 :            :   SignalNode *node;
    2317                 :        338 :   gulong handler_seq_no = 0;
    2318                 :            :   
    2319                 :        338 :   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
    2320                 :        338 :   g_return_val_if_fail (signal_id > 0, 0);
    2321                 :        338 :   g_return_val_if_fail (closure != NULL, 0);
    2322                 :            :   
    2323                 :        338 :   SIGNAL_LOCK ();
    2324                 :        338 :   node = LOOKUP_SIGNAL_NODE (signal_id);
    2325         [ +  - ]:        338 :   if (node)
    2326                 :            :     {
    2327   [ +  +  -  + ]:        338 :       if (detail && !(node->flags & G_SIGNAL_DETAILED))
    2328                 :          0 :         g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
    2329   [ +  +  -  + ]:        338 :       else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
    2330                 :          0 :         g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
    2331                 :            :       else
    2332                 :            :         {
    2333                 :        338 :           Handler *handler = handler_new (signal_id, instance, after);
    2334                 :            : 
    2335         [ +  - ]:        338 :           if (G_TYPE_IS_OBJECT (node->itype))
    2336                 :        338 :             _g_object_set_has_signal_handler ((GObject *) instance, signal_id);
    2337                 :            : 
    2338                 :        338 :           handler_seq_no = handler->sequential_number;
    2339                 :        338 :           handler->detail = detail;
    2340                 :        338 :           handler->closure = g_closure_ref (closure);
    2341                 :        338 :           g_closure_sink (closure);
    2342                 :        338 :           add_invalid_closure_notify (handler, instance);
    2343                 :        338 :           handler_insert (signal_id, instance, handler);
    2344   [ +  -  +  + ]:        338 :           if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
    2345                 :            :             {
    2346                 :        322 :               g_closure_set_marshal (closure, node->c_marshaller);
    2347         [ +  - ]:        322 :               if (node->va_marshaller)
    2348                 :        322 :                 _g_closure_set_va_marshal (closure, node->va_marshaller);
    2349                 :            :             }
    2350                 :            :         }
    2351                 :            :     }
    2352                 :            :   else
    2353                 :          0 :     g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
    2354                 :        338 :   SIGNAL_UNLOCK ();
    2355                 :            :   
    2356                 :        338 :   return handler_seq_no;
    2357                 :            : }
    2358                 :            : 
    2359                 :            : /**
    2360                 :            :  * g_signal_connect_closure:
    2361                 :            :  * @instance: (type GObject.Object): the instance to connect to.
    2362                 :            :  * @detailed_signal: a string of the form "signal-name::detail".
    2363                 :            :  * @closure: (not nullable): the closure to connect.
    2364                 :            :  * @after: whether the handler should be called before or after the
    2365                 :            :  *  default handler of the signal.
    2366                 :            :  *
    2367                 :            :  * Connects a closure to a signal for a particular object.
    2368                 :            :  *
    2369                 :            :  * If @closure is a floating reference (see g_closure_sink()), this function
    2370                 :            :  * takes ownership of @closure.
    2371                 :            :  *
    2372                 :            :  * This function cannot fail. If the given signal doesn’t exist, a critical
    2373                 :            :  * warning is emitted.
    2374                 :            :  *
    2375                 :            :  * Returns: the handler ID (always greater than 0)
    2376                 :            :  */
    2377                 :            : gulong
    2378                 :         58 : g_signal_connect_closure (gpointer     instance,
    2379                 :            :                           const gchar *detailed_signal,
    2380                 :            :                           GClosure    *closure,
    2381                 :            :                           gboolean     after)
    2382                 :            : {
    2383                 :            :   guint signal_id;
    2384                 :         58 :   gulong handler_seq_no = 0;
    2385                 :         58 :   GQuark detail = 0;
    2386                 :            :   GType itype;
    2387                 :            : 
    2388                 :         58 :   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
    2389                 :         58 :   g_return_val_if_fail (detailed_signal != NULL, 0);
    2390                 :         58 :   g_return_val_if_fail (closure != NULL, 0);
    2391                 :            : 
    2392                 :         58 :   SIGNAL_LOCK ();
    2393                 :         58 :   itype = G_TYPE_FROM_INSTANCE (instance);
    2394                 :         58 :   signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
    2395         [ +  - ]:         58 :   if (signal_id)
    2396                 :            :     {
    2397                 :         58 :       SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
    2398                 :            : 
    2399   [ -  +  -  - ]:         58 :       if (detail && !(node->flags & G_SIGNAL_DETAILED))
    2400                 :          0 :         g_critical ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal);
    2401   [ -  +  -  - ]:         58 :       else if (!g_type_is_a (itype, node->itype))
    2402                 :          0 :         g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
    2403                 :            :                     G_STRLOC, detailed_signal, instance, g_type_name (itype));
    2404                 :            :       else
    2405                 :            :         {
    2406                 :         58 :           Handler *handler = handler_new (signal_id, instance, after);
    2407                 :            : 
    2408         [ +  - ]:         58 :           if (G_TYPE_IS_OBJECT (node->itype))
    2409                 :         58 :             _g_object_set_has_signal_handler ((GObject *) instance, signal_id);
    2410                 :            : 
    2411                 :         58 :           handler_seq_no = handler->sequential_number;
    2412                 :         58 :           handler->detail = detail;
    2413                 :         58 :           handler->closure = g_closure_ref (closure);
    2414                 :         58 :           g_closure_sink (closure);
    2415                 :         58 :           add_invalid_closure_notify (handler, instance);
    2416                 :         58 :           handler_insert (signal_id, instance, handler);
    2417   [ +  -  +  + ]:         58 :           if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
    2418                 :            :             {
    2419                 :         57 :               g_closure_set_marshal (handler->closure, node->c_marshaller);
    2420         [ +  + ]:         57 :               if (node->va_marshaller)
    2421                 :         56 :                 _g_closure_set_va_marshal (handler->closure, node->va_marshaller);
    2422                 :            :             }
    2423                 :            :         }
    2424                 :            :     }
    2425                 :            :   else
    2426                 :          0 :     g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
    2427                 :            :                 G_STRLOC, detailed_signal, instance, g_type_name (itype));
    2428                 :         58 :   SIGNAL_UNLOCK ();
    2429                 :            : 
    2430                 :         58 :   return handler_seq_no;
    2431                 :            : }
    2432                 :            : 
    2433                 :            : static void
    2434                 :     539397 : node_check_deprecated (const SignalNode *node)
    2435                 :            : {
    2436                 :            :   static const gchar * g_enable_diagnostic = NULL;
    2437                 :            : 
    2438         [ +  + ]:     539397 :   if (G_UNLIKELY (!g_enable_diagnostic))
    2439                 :            :     {
    2440                 :        190 :       g_enable_diagnostic = g_getenv ("G_ENABLE_DIAGNOSTIC");
    2441         [ -  + ]:        190 :       if (!g_enable_diagnostic)
    2442                 :          0 :         g_enable_diagnostic = "0";
    2443                 :            :     }
    2444                 :            : 
    2445         [ +  + ]:     539397 :   if (g_enable_diagnostic[0] == '1')
    2446                 :            :     {
    2447         [ -  + ]:     539393 :       if (node->flags & G_SIGNAL_DEPRECATED)
    2448                 :            :         {
    2449                 :          0 :           g_warning ("The signal %s::%s is deprecated and shouldn't be used "
    2450                 :            :                      "anymore. It will be removed in a future version.",
    2451                 :            :                      type_debug_name (node->itype), node->name);
    2452                 :            :         }
    2453                 :            :     }
    2454                 :     539397 : }
    2455                 :            : 
    2456                 :            : /**
    2457                 :            :  * g_signal_connect_data:
    2458                 :            :  * @instance: (type GObject.Object): the instance to connect to.
    2459                 :            :  * @detailed_signal: a string of the form "signal-name::detail".
    2460                 :            :  * @c_handler: (not nullable): the #GCallback to connect.
    2461                 :            :  * @data: (nullable) (closure c_handler): data to pass to @c_handler calls.
    2462                 :            :  * @destroy_data: (nullable) (destroy data): a #GClosureNotify for @data.
    2463                 :            :  * @connect_flags: a combination of #GConnectFlags.
    2464                 :            :  *
    2465                 :            :  * Connects a #GCallback function to a signal for a particular object. Similar
    2466                 :            :  * to g_signal_connect(), but allows to provide a #GClosureNotify for the data
    2467                 :            :  * which will be called when the signal handler is disconnected and no longer
    2468                 :            :  * used. Specify @connect_flags if you need `..._after()` or
    2469                 :            :  * `..._swapped()` variants of this function.
    2470                 :            :  *
    2471                 :            :  * This function cannot fail. If the given signal doesn’t exist, a critical
    2472                 :            :  * warning is emitted.
    2473                 :            :  *
    2474                 :            :  * Returns: the handler ID (always greater than 0)
    2475                 :            :  */
    2476                 :            : gulong
    2477                 :     539109 : g_signal_connect_data (gpointer       instance,
    2478                 :            :                        const gchar   *detailed_signal,
    2479                 :            :                        GCallback      c_handler,
    2480                 :            :                        gpointer       data,
    2481                 :            :                        GClosureNotify destroy_data,
    2482                 :            :                        GConnectFlags  connect_flags)
    2483                 :            : {
    2484                 :            :   guint signal_id;
    2485                 :     539109 :   gulong handler_seq_no = 0;
    2486                 :     539109 :   GQuark detail = 0;
    2487                 :            :   GType itype;
    2488                 :            :   gboolean swapped, after;
    2489                 :            :   
    2490                 :     539109 :   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
    2491                 :     539109 :   g_return_val_if_fail (detailed_signal != NULL, 0);
    2492                 :     539109 :   g_return_val_if_fail (c_handler != NULL, 0);
    2493                 :            : 
    2494                 :     539109 :   swapped = (connect_flags & G_CONNECT_SWAPPED) != FALSE;
    2495                 :     539109 :   after = (connect_flags & G_CONNECT_AFTER) != FALSE;
    2496                 :            : 
    2497                 :     539109 :   SIGNAL_LOCK ();
    2498                 :     539364 :   itype = G_TYPE_FROM_INSTANCE (instance);
    2499                 :     539364 :   signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
    2500         [ +  - ]:     539364 :   if (signal_id)
    2501                 :            :     {
    2502                 :     539364 :       SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id);
    2503                 :            : 
    2504                 :     539364 :       node_check_deprecated (node);
    2505                 :            : 
    2506   [ +  +  -  + ]:     539364 :       if (detail && !(node->flags & G_SIGNAL_DETAILED))
    2507                 :          0 :         g_critical ("%s: signal '%s' does not support details", G_STRLOC, detailed_signal);
    2508   [ +  +  -  + ]:     539364 :       else if (!g_type_is_a (itype, node->itype))
    2509                 :          0 :         g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
    2510                 :            :                     G_STRLOC, detailed_signal, instance, g_type_name (itype));
    2511                 :            :       else
    2512                 :            :         {
    2513                 :     539364 :           Handler *handler = handler_new (signal_id, instance, after);
    2514                 :            : 
    2515         [ +  + ]:     539364 :           if (G_TYPE_IS_OBJECT (node->itype))
    2516                 :     138901 :             _g_object_set_has_signal_handler ((GObject *) instance, signal_id);
    2517                 :            : 
    2518                 :     539364 :           handler_seq_no = handler->sequential_number;
    2519                 :     539364 :           handler->detail = detail;
    2520         [ +  + ]:     539364 :           handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data));
    2521                 :     539364 :           g_closure_sink (handler->closure);
    2522                 :     539364 :           handler_insert (signal_id, instance, handler);
    2523   [ +  -  +  - ]:     539364 :           if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
    2524                 :            :             {
    2525                 :     539364 :               g_closure_set_marshal (handler->closure, node->c_marshaller);
    2526         [ +  + ]:     539364 :               if (node->va_marshaller)
    2527                 :     539264 :                 _g_closure_set_va_marshal (handler->closure, node->va_marshaller);
    2528                 :            :             }
    2529                 :            :         }
    2530                 :            :     }
    2531                 :            :   else
    2532                 :          0 :     g_critical ("%s: signal '%s' is invalid for instance '%p' of type '%s'",
    2533                 :            :                 G_STRLOC, detailed_signal, instance, g_type_name (itype));
    2534                 :     539364 :   SIGNAL_UNLOCK ();
    2535                 :            : 
    2536                 :     539345 :   return handler_seq_no;
    2537                 :            : }
    2538                 :            : 
    2539                 :            : static void
    2540                 :            : signal_handler_block_unlocked (gpointer instance,
    2541                 :            :                                gulong   handler_id);
    2542                 :            : 
    2543                 :            : /**
    2544                 :            :  * g_signal_handler_block:
    2545                 :            :  * @instance: (type GObject.Object): The instance to block the signal handler of.
    2546                 :            :  * @handler_id: Handler id of the handler to be blocked.
    2547                 :            :  *
    2548                 :            :  * Blocks a handler of an instance so it will not be called during any
    2549                 :            :  * signal emissions unless it is unblocked again. Thus "blocking" a
    2550                 :            :  * signal handler means to temporarily deactivate it, a signal handler
    2551                 :            :  * has to be unblocked exactly the same amount of times it has been
    2552                 :            :  * blocked before to become active again.
    2553                 :            :  *
    2554                 :            :  * The @handler_id has to be a valid signal handler id, connected to a
    2555                 :            :  * signal of @instance.
    2556                 :            :  */
    2557                 :            : void
    2558                 :        186 : g_signal_handler_block (gpointer instance,
    2559                 :            :                         gulong   handler_id)
    2560                 :            : {
    2561                 :        186 :   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
    2562                 :        186 :   g_return_if_fail (handler_id > 0);
    2563                 :            :   
    2564                 :        186 :   SIGNAL_LOCK ();
    2565                 :        186 :   signal_handler_block_unlocked (instance, handler_id);
    2566                 :        186 :   SIGNAL_UNLOCK ();
    2567                 :            : }
    2568                 :            : 
    2569                 :            : static void
    2570                 :        189 : signal_handler_block_unlocked (gpointer instance,
    2571                 :            :                                gulong   handler_id)
    2572                 :            : {
    2573                 :            :   Handler *handler;
    2574                 :            : 
    2575                 :        189 :   handler = handler_lookup (instance, handler_id, NULL, NULL);
    2576         [ +  - ]:        189 :   if (handler)
    2577                 :            :     {
    2578                 :            : #ifndef G_DISABLE_CHECKS
    2579         [ -  + ]:        189 :       if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1)
    2580                 :          0 :         g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG);
    2581                 :            : #endif
    2582                 :        189 :       handler->block_count += 1;
    2583                 :            :     }
    2584                 :            :   else
    2585                 :          0 :     g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id);
    2586                 :        189 : }
    2587                 :            : 
    2588                 :            : static void
    2589                 :            : signal_handler_unblock_unlocked (gpointer instance,
    2590                 :            :                                  gulong   handler_id);
    2591                 :            : 
    2592                 :            : /**
    2593                 :            :  * g_signal_handler_unblock:
    2594                 :            :  * @instance: (type GObject.Object): The instance to unblock the signal handler of.
    2595                 :            :  * @handler_id: Handler id of the handler to be unblocked.
    2596                 :            :  *
    2597                 :            :  * Undoes the effect of a previous g_signal_handler_block() call.  A
    2598                 :            :  * blocked handler is skipped during signal emissions and will not be
    2599                 :            :  * invoked, unblocking it (for exactly the amount of times it has been
    2600                 :            :  * blocked before) reverts its "blocked" state, so the handler will be
    2601                 :            :  * recognized by the signal system and is called upon future or
    2602                 :            :  * currently ongoing signal emissions (since the order in which
    2603                 :            :  * handlers are called during signal emissions is deterministic,
    2604                 :            :  * whether the unblocked handler in question is called as part of a
    2605                 :            :  * currently ongoing emission depends on how far that emission has
    2606                 :            :  * proceeded yet).
    2607                 :            :  *
    2608                 :            :  * The @handler_id has to be a valid id of a signal handler that is
    2609                 :            :  * connected to a signal of @instance and is currently blocked.
    2610                 :            :  */
    2611                 :            : void
    2612                 :        170 : g_signal_handler_unblock (gpointer instance,
    2613                 :            :                           gulong   handler_id)
    2614                 :            : {
    2615                 :        170 :   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
    2616                 :        170 :   g_return_if_fail (handler_id > 0);
    2617                 :            :   
    2618                 :        170 :   SIGNAL_LOCK ();
    2619                 :        170 :   signal_handler_unblock_unlocked (instance, handler_id);
    2620                 :        170 :   SIGNAL_UNLOCK ();
    2621                 :            : }
    2622                 :            : 
    2623                 :            : static void
    2624                 :        173 : signal_handler_unblock_unlocked (gpointer instance,
    2625                 :            :                                  gulong   handler_id)
    2626                 :            : {
    2627                 :            :   Handler *handler;
    2628                 :            : 
    2629                 :        173 :   handler = handler_lookup (instance, handler_id, NULL, NULL);
    2630         [ +  - ]:        173 :   if (handler)
    2631                 :            :     {
    2632         [ +  - ]:        173 :       if (handler->block_count)
    2633                 :        173 :         handler->block_count -= 1;
    2634                 :            :       else
    2635                 :          0 :         g_critical (G_STRLOC ": handler '%lu' of instance '%p' is not blocked", handler_id, instance);
    2636                 :            :     }
    2637                 :            :   else
    2638                 :          0 :     g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id);
    2639                 :        173 : }
    2640                 :            : 
    2641                 :            : static void
    2642                 :            : signal_handler_disconnect_unlocked (gpointer instance,
    2643                 :            :                                     gulong   handler_id);
    2644                 :            : 
    2645                 :            : /**
    2646                 :            :  * g_signal_handler_disconnect:
    2647                 :            :  * @instance: (type GObject.Object): The instance to remove the signal handler from.
    2648                 :            :  * @handler_id: Handler id of the handler to be disconnected.
    2649                 :            :  *
    2650                 :            :  * Disconnects a handler from an instance so it will not be called during
    2651                 :            :  * any future or currently ongoing emissions of the signal it has been
    2652                 :            :  * connected to. The @handler_id becomes invalid and may be reused.
    2653                 :            :  *
    2654                 :            :  * The @handler_id has to be a valid signal handler id, connected to a
    2655                 :            :  * signal of @instance.
    2656                 :            :  */
    2657                 :            : void
    2658                 :     136739 : g_signal_handler_disconnect (gpointer instance,
    2659                 :            :                              gulong   handler_id)
    2660                 :            : {
    2661                 :     136739 :   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
    2662                 :     136739 :   g_return_if_fail (handler_id > 0);
    2663                 :            :   
    2664                 :     136739 :   SIGNAL_LOCK ();
    2665                 :     136739 :   signal_handler_disconnect_unlocked (instance, handler_id);
    2666                 :     136739 :   SIGNAL_UNLOCK ();
    2667                 :            : }
    2668                 :            : 
    2669                 :            : static void
    2670                 :     538679 : signal_handler_disconnect_unlocked (gpointer instance,
    2671                 :            :                                     gulong   handler_id)
    2672                 :            : {
    2673                 :            :   Handler *handler;
    2674                 :            : 
    2675                 :     538679 :   handler = handler_lookup (instance, handler_id, 0, 0);
    2676         [ +  + ]:     538679 :   if (handler)
    2677                 :            :     {
    2678                 :     538676 :       g_hash_table_remove (g_handlers, handler);
    2679                 :     538676 :       handler->sequential_number = 0;
    2680                 :     538676 :       handler->block_count = 1;
    2681                 :     538676 :       remove_invalid_closure_notify (handler, instance);
    2682                 :     538676 :       handler_unref_R (handler->signal_id, instance, handler);
    2683                 :            :     }
    2684                 :            :   else
    2685                 :          3 :     g_critical ("%s: instance '%p' has no handler with id '%lu'", G_STRLOC, instance, handler_id);
    2686                 :     538679 : }
    2687                 :            : 
    2688                 :            : /**
    2689                 :            :  * g_signal_handler_is_connected:
    2690                 :            :  * @instance: (type GObject.Object): The instance where a signal handler is sought.
    2691                 :            :  * @handler_id: the handler ID.
    2692                 :            :  *
    2693                 :            :  * Returns whether @handler_id is the ID of a handler connected to @instance.
    2694                 :            :  *
    2695                 :            :  * Returns: whether @handler_id identifies a handler connected to @instance.
    2696                 :            :  */
    2697                 :            : gboolean
    2698                 :         30 : g_signal_handler_is_connected (gpointer instance,
    2699                 :            :                                gulong   handler_id)
    2700                 :            : {
    2701                 :            :   Handler *handler;
    2702                 :            :   gboolean connected;
    2703                 :            : 
    2704                 :         30 :   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
    2705                 :            : 
    2706                 :         30 :   SIGNAL_LOCK ();
    2707                 :         30 :   handler = handler_lookup (instance, handler_id, NULL, NULL);
    2708                 :         30 :   connected = handler != NULL;
    2709                 :         30 :   SIGNAL_UNLOCK ();
    2710                 :            : 
    2711                 :         30 :   return connected;
    2712                 :            : }
    2713                 :            : 
    2714                 :            : /**
    2715                 :            :  * g_signal_handlers_destroy:
    2716                 :            :  * @instance: (type GObject.Object): The instance whose signal handlers are destroyed
    2717                 :            :  *
    2718                 :            :  * Destroy all signal handlers of a type instance. This function is
    2719                 :            :  * an implementation detail of the #GObject dispose implementation,
    2720                 :            :  * and should not be used outside of the type system.
    2721                 :            :  */
    2722                 :            : void
    2723                 :    7401603 : g_signal_handlers_destroy (gpointer instance)
    2724                 :            : {
    2725                 :            :   GBSearchArray *hlbsa;
    2726                 :            :   
    2727                 :    7401603 :   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
    2728                 :            :   
    2729                 :    7401603 :   SIGNAL_LOCK ();
    2730                 :    7403016 :   hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance);
    2731         [ +  + ]:    7403016 :   if (hlbsa)
    2732                 :            :     {
    2733                 :            :       guint i;
    2734                 :            :       
    2735                 :            :       /* reentrancy caution, delete instance trace first */
    2736                 :     106491 :       g_hash_table_remove (g_handler_list_bsa_ht, instance);
    2737                 :            :       
    2738         [ +  + ]:     213381 :       for (i = 0; i < hlbsa->n_nodes; i++)
    2739                 :            :         {
    2740                 :     106890 :           HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i);
    2741                 :     106890 :           Handler *handler = hlist->handlers;
    2742                 :            :           
    2743         [ +  + ]:     107586 :           while (handler)
    2744                 :            :             {
    2745                 :        696 :               Handler *tmp = handler;
    2746                 :            :               
    2747                 :        696 :               handler = tmp->next;
    2748                 :        696 :               tmp->block_count = 1;
    2749                 :            :               /* cruel unlink, this works because _all_ handlers vanish */
    2750                 :        696 :               tmp->next = NULL;
    2751                 :        696 :               tmp->prev = tmp;
    2752         [ +  - ]:        696 :               if (tmp->sequential_number)
    2753                 :            :                 {
    2754                 :        696 :                   g_hash_table_remove (g_handlers, tmp);
    2755                 :        696 :                   remove_invalid_closure_notify (tmp, instance);
    2756                 :        696 :                   tmp->sequential_number = 0;
    2757                 :        696 :                   handler_unref_R (0, NULL, tmp);
    2758                 :            :                 }
    2759                 :            :             }
    2760                 :            :         }
    2761                 :     106491 :       g_bsearch_array_free (hlbsa, &g_signal_hlbsa_bconfig);
    2762                 :            :     }
    2763                 :    7403016 :   SIGNAL_UNLOCK ();
    2764                 :            : }
    2765                 :            : 
    2766                 :            : /**
    2767                 :            :  * g_signal_handler_find:
    2768                 :            :  * @instance: (type GObject.Object): The instance owning the signal handler to be found.
    2769                 :            :  * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
    2770                 :            :  *  and/or @data the handler has to match.
    2771                 :            :  * @signal_id: Signal the handler has to be connected to.
    2772                 :            :  * @detail: Signal detail the handler has to be connected to.
    2773                 :            :  * @closure: (nullable): The closure the handler will invoke.
    2774                 :            :  * @func: The C closure callback of the handler (useless for non-C closures).
    2775                 :            :  * @data: (nullable) (closure closure): The closure data of the handler's closure.
    2776                 :            :  *
    2777                 :            :  * Finds the first signal handler that matches certain selection criteria.
    2778                 :            :  * The criteria mask is passed as an OR-ed combination of #GSignalMatchType
    2779                 :            :  * flags, and the criteria values are passed as arguments.
    2780                 :            :  * The match @mask has to be non-0 for successful matches.
    2781                 :            :  * If no handler was found, 0 is returned.
    2782                 :            :  *
    2783                 :            :  * Returns: A valid non-0 signal handler id for a successful match.
    2784                 :            :  */
    2785                 :            : gulong
    2786                 :         13 : g_signal_handler_find (gpointer         instance,
    2787                 :            :                        GSignalMatchType mask,
    2788                 :            :                        guint            signal_id,
    2789                 :            :                        GQuark           detail,
    2790                 :            :                        GClosure        *closure,
    2791                 :            :                        gpointer         func,
    2792                 :            :                        gpointer         data)
    2793                 :            : {
    2794                 :         13 :   gulong handler_seq_no = 0;
    2795                 :            :   
    2796                 :         13 :   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
    2797                 :         13 :   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
    2798                 :            :   
    2799         [ +  - ]:         13 :   if (mask & G_SIGNAL_MATCH_MASK)
    2800                 :            :     {
    2801                 :            :       HandlerMatch *mlist;
    2802                 :            :       
    2803                 :         13 :       SIGNAL_LOCK ();
    2804                 :         13 :       mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
    2805         [ +  + ]:         13 :       if (mlist)
    2806                 :            :         {
    2807                 :          2 :           handler_seq_no = mlist->handler->sequential_number;
    2808                 :          2 :           handler_match_free1_R (mlist, instance);
    2809                 :            :         }
    2810                 :         13 :       SIGNAL_UNLOCK ();
    2811                 :            :     }
    2812                 :            :   
    2813                 :         13 :   return handler_seq_no;
    2814                 :            : }
    2815                 :            : 
    2816                 :            : typedef void (*CallbackHandlerFunc) (gpointer instance, gulong handler_seq_no);
    2817                 :            : 
    2818                 :            : static guint
    2819                 :     401998 : signal_handlers_foreach_matched_unlocked_R (gpointer             instance,
    2820                 :            :                                             GSignalMatchType     mask,
    2821                 :            :                                             guint                signal_id,
    2822                 :            :                                             GQuark               detail,
    2823                 :            :                                             GClosure            *closure,
    2824                 :            :                                             gpointer             func,
    2825                 :            :                                             gpointer             data,
    2826                 :            :                                             CallbackHandlerFunc  callback)
    2827                 :            : {
    2828                 :            :   HandlerMatch *mlist;
    2829                 :     401998 :   guint n_handlers = 0;
    2830                 :            : 
    2831                 :     401998 :   mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
    2832         [ +  + ]:     803944 :   while (mlist)
    2833                 :            :     {
    2834                 :     401946 :       n_handlers++;
    2835         [ +  - ]:     401946 :       if (mlist->handler->sequential_number)
    2836                 :     401946 :         callback (instance, mlist->handler->sequential_number);
    2837                 :            : 
    2838                 :     401946 :       mlist = handler_match_free1_R (mlist, instance);
    2839                 :            :     }
    2840                 :            : 
    2841                 :     401998 :   return n_handlers;
    2842                 :            : }
    2843                 :            : 
    2844                 :            : /**
    2845                 :            :  * g_signal_handlers_block_matched:
    2846                 :            :  * @instance: (type GObject.Object): The instance to block handlers from.
    2847                 :            :  * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
    2848                 :            :  *  and/or @data the handlers have to match.
    2849                 :            :  * @signal_id: Signal the handlers have to be connected to.
    2850                 :            :  * @detail: Signal detail the handlers have to be connected to.
    2851                 :            :  * @closure: (nullable): The closure the handlers will invoke.
    2852                 :            :  * @func: The C closure callback of the handlers (useless for non-C closures).
    2853                 :            :  * @data: (nullable) (closure closure): The closure data of the handlers' closures.
    2854                 :            :  *
    2855                 :            :  * Blocks all handlers on an instance that match a certain selection criteria.
    2856                 :            :  *
    2857                 :            :  * The criteria mask is passed as a combination of #GSignalMatchType flags, and
    2858                 :            :  * the criteria values are passed as arguments. A handler must match on all
    2859                 :            :  * flags set in @mask to be blocked (i.e. the match is conjunctive).
    2860                 :            :  *
    2861                 :            :  * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE,
    2862                 :            :  * %G_SIGNAL_MATCH_FUNC
    2863                 :            :  * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches.
    2864                 :            :  * If no handlers were found, 0 is returned, the number of blocked handlers
    2865                 :            :  * otherwise.
    2866                 :            :  *
    2867                 :            :  * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78.
    2868                 :            :  *
    2869                 :            :  * Returns: The number of handlers that matched.
    2870                 :            :  */
    2871                 :            : guint
    2872                 :          5 : g_signal_handlers_block_matched (gpointer         instance,
    2873                 :            :                                  GSignalMatchType mask,
    2874                 :            :                                  guint            signal_id,
    2875                 :            :                                  GQuark           detail,
    2876                 :            :                                  GClosure        *closure,
    2877                 :            :                                  gpointer         func,
    2878                 :            :                                  gpointer         data)
    2879                 :            : {
    2880                 :          5 :   guint n_handlers = 0;
    2881                 :            :   
    2882                 :          5 :   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
    2883                 :          5 :   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
    2884                 :            :   
    2885         [ +  - ]:          5 :   if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
    2886                 :            :     {
    2887                 :          5 :       SIGNAL_LOCK ();
    2888                 :            :       n_handlers =
    2889                 :          5 :         signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail,
    2890                 :            :                                                     closure, func, data,
    2891                 :            :                                                     signal_handler_block_unlocked);
    2892                 :          5 :       SIGNAL_UNLOCK ();
    2893                 :            :     }
    2894                 :            :   
    2895                 :          5 :   return n_handlers;
    2896                 :            : }
    2897                 :            : 
    2898                 :            : /**
    2899                 :            :  * g_signal_handlers_unblock_matched:
    2900                 :            :  * @instance: (type GObject.Object): The instance to unblock handlers from.
    2901                 :            :  * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
    2902                 :            :  *  and/or @data the handlers have to match.
    2903                 :            :  * @signal_id: Signal the handlers have to be connected to.
    2904                 :            :  * @detail: Signal detail the handlers have to be connected to.
    2905                 :            :  * @closure: (nullable): The closure the handlers will invoke.
    2906                 :            :  * @func: The C closure callback of the handlers (useless for non-C closures).
    2907                 :            :  * @data: (nullable) (closure closure): The closure data of the handlers' closures.
    2908                 :            :  *
    2909                 :            :  * Unblocks all handlers on an instance that match a certain selection
    2910                 :            :  * criteria.
    2911                 :            :  *
    2912                 :            :  * The criteria mask is passed as a combination of #GSignalMatchType flags, and
    2913                 :            :  * the criteria values are passed as arguments. A handler must match on all
    2914                 :            :  * flags set in @mask to be unblocked (i.e. the match is conjunctive).
    2915                 :            :  *
    2916                 :            :  * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE,
    2917                 :            :  * %G_SIGNAL_MATCH_FUNC
    2918                 :            :  * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches.
    2919                 :            :  * If no handlers were found, 0 is returned, the number of unblocked handlers
    2920                 :            :  * otherwise. The match criteria should not apply to any handlers that are
    2921                 :            :  * not currently blocked.
    2922                 :            :  *
    2923                 :            :  * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78.
    2924                 :            :  *
    2925                 :            :  * Returns: The number of handlers that matched.
    2926                 :            :  */
    2927                 :            : guint
    2928                 :          3 : g_signal_handlers_unblock_matched (gpointer         instance,
    2929                 :            :                                    GSignalMatchType mask,
    2930                 :            :                                    guint            signal_id,
    2931                 :            :                                    GQuark           detail,
    2932                 :            :                                    GClosure        *closure,
    2933                 :            :                                    gpointer         func,
    2934                 :            :                                    gpointer         data)
    2935                 :            : {
    2936                 :          3 :   guint n_handlers = 0;
    2937                 :            :   
    2938                 :          3 :   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
    2939                 :          3 :   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
    2940                 :            :   
    2941         [ +  - ]:          3 :   if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
    2942                 :            :     {
    2943                 :          3 :       SIGNAL_LOCK ();
    2944                 :            :       n_handlers =
    2945                 :          3 :         signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail,
    2946                 :            :                                                     closure, func, data,
    2947                 :            :                                                     signal_handler_unblock_unlocked);
    2948                 :          3 :       SIGNAL_UNLOCK ();
    2949                 :            :     }
    2950                 :            :   
    2951                 :          3 :   return n_handlers;
    2952                 :            : }
    2953                 :            : 
    2954                 :            : /**
    2955                 :            :  * g_signal_handlers_disconnect_matched:
    2956                 :            :  * @instance: (type GObject.Object): The instance to remove handlers from.
    2957                 :            :  * @mask: Mask indicating which of @signal_id, @detail, @closure, @func
    2958                 :            :  *  and/or @data the handlers have to match.
    2959                 :            :  * @signal_id: Signal the handlers have to be connected to.
    2960                 :            :  * @detail: Signal detail the handlers have to be connected to.
    2961                 :            :  * @closure: (nullable): The closure the handlers will invoke.
    2962                 :            :  * @func: The C closure callback of the handlers (useless for non-C closures).
    2963                 :            :  * @data: (nullable) (closure closure): The closure data of the handlers' closures.
    2964                 :            :  *
    2965                 :            :  * Disconnects all handlers on an instance that match a certain
    2966                 :            :  * selection criteria.
    2967                 :            :  *
    2968                 :            :  * The criteria mask is passed as a combination of #GSignalMatchType flags, and
    2969                 :            :  * the criteria values are passed as arguments. A handler must match on all
    2970                 :            :  * flags set in @mask to be disconnected (i.e. the match is conjunctive).
    2971                 :            :  *
    2972                 :            :  * Passing at least one of the %G_SIGNAL_MATCH_ID, %G_SIGNAL_MATCH_CLOSURE,
    2973                 :            :  * %G_SIGNAL_MATCH_FUNC or
    2974                 :            :  * %G_SIGNAL_MATCH_DATA match flags is required for successful
    2975                 :            :  * matches.  If no handlers were found, 0 is returned, the number of
    2976                 :            :  * disconnected handlers otherwise.
    2977                 :            :  *
    2978                 :            :  * Support for %G_SIGNAL_MATCH_ID was added in GLib 2.78.
    2979                 :            :  *
    2980                 :            :  * Returns: The number of handlers that matched.
    2981                 :            :  */
    2982                 :            : guint
    2983                 :     401461 : g_signal_handlers_disconnect_matched (gpointer         instance,
    2984                 :            :                                       GSignalMatchType mask,
    2985                 :            :                                       guint            signal_id,
    2986                 :            :                                       GQuark           detail,
    2987                 :            :                                       GClosure        *closure,
    2988                 :            :                                       gpointer         func,
    2989                 :            :                                       gpointer         data)
    2990                 :            : {
    2991                 :     401461 :   guint n_handlers = 0;
    2992                 :            :   
    2993                 :     401461 :   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
    2994                 :     401461 :   g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0);
    2995                 :            :   
    2996         [ +  + ]:     401461 :   if (mask & (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
    2997                 :            :     {
    2998                 :     401153 :       SIGNAL_LOCK ();
    2999                 :            :       n_handlers =
    3000                 :     401990 :         signal_handlers_foreach_matched_unlocked_R (instance, mask, signal_id, detail,
    3001                 :            :                                                     closure, func, data,
    3002                 :            :                                                     signal_handler_disconnect_unlocked);
    3003                 :     401990 :       SIGNAL_UNLOCK ();
    3004                 :            :     }
    3005                 :            :   
    3006                 :     401740 :   return n_handlers;
    3007                 :            : }
    3008                 :            : 
    3009                 :            : /**
    3010                 :            :  * g_signal_has_handler_pending:
    3011                 :            :  * @instance: (type GObject.Object): the object whose signal handlers are sought.
    3012                 :            :  * @signal_id: the signal id.
    3013                 :            :  * @detail: the detail.
    3014                 :            :  * @may_be_blocked: whether blocked handlers should count as match.
    3015                 :            :  *
    3016                 :            :  * Returns whether there are any handlers connected to @instance for the
    3017                 :            :  * given signal id and detail.
    3018                 :            :  *
    3019                 :            :  * If @detail is 0 then it will only match handlers that were connected
    3020                 :            :  * without detail.  If @detail is non-zero then it will match handlers
    3021                 :            :  * connected both without detail and with the given detail.  This is
    3022                 :            :  * consistent with how a signal emitted with @detail would be delivered
    3023                 :            :  * to those handlers.
    3024                 :            :  *
    3025                 :            :  * Since 2.46 this also checks for a non-default class closure being
    3026                 :            :  * installed, as this is basically always what you want.
    3027                 :            :  *
    3028                 :            :  * One example of when you might use this is when the arguments to the
    3029                 :            :  * signal are difficult to compute. A class implementor may opt to not
    3030                 :            :  * emit the signal if no one is attached anyway, thus saving the cost
    3031                 :            :  * of building the arguments.
    3032                 :            :  *
    3033                 :            :  * Returns: %TRUE if a handler is connected to the signal, %FALSE
    3034                 :            :  *          otherwise.
    3035                 :            :  */
    3036                 :            : gboolean
    3037                 :        111 : g_signal_has_handler_pending (gpointer instance,
    3038                 :            :                               guint    signal_id,
    3039                 :            :                               GQuark   detail,
    3040                 :            :                               gboolean may_be_blocked)
    3041                 :            : {
    3042                 :            :   HandlerMatch *mlist;
    3043                 :            :   gboolean has_pending;
    3044                 :            :   SignalNode *node;
    3045                 :            :   
    3046                 :        111 :   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE);
    3047                 :        111 :   g_return_val_if_fail (signal_id > 0, FALSE);
    3048                 :            :   
    3049                 :        111 :   SIGNAL_LOCK ();
    3050                 :            : 
    3051                 :        111 :   node = LOOKUP_SIGNAL_NODE (signal_id);
    3052         [ -  + ]:        111 :   if (detail)
    3053                 :            :     {
    3054         [ #  # ]:          0 :       if (!(node->flags & G_SIGNAL_DETAILED))
    3055                 :            :         {
    3056                 :          0 :           g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
    3057                 :          0 :           SIGNAL_UNLOCK ();
    3058                 :          0 :           return FALSE;
    3059                 :            :         }
    3060                 :            :     }
    3061         [ +  + ]:        111 :   mlist = handlers_find (instance,
    3062                 :            :                          (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
    3063                 :            :                          signal_id, detail, NULL, NULL, NULL, TRUE);
    3064         [ +  + ]:        111 :   if (mlist)
    3065                 :            :     {
    3066                 :         67 :       has_pending = TRUE;
    3067                 :         67 :       handler_match_free1_R (mlist, instance);
    3068                 :            :     }
    3069                 :            :   else
    3070                 :            :     {
    3071                 :         44 :       ClassClosure *class_closure = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance));
    3072   [ +  +  -  + ]:         44 :       if (class_closure != NULL && class_closure->instance_type != 0)
    3073                 :          0 :         has_pending = TRUE;
    3074                 :            :       else
    3075                 :         44 :         has_pending = FALSE;
    3076                 :            :     }
    3077                 :        111 :   SIGNAL_UNLOCK ();
    3078                 :            : 
    3079                 :        111 :   return has_pending;
    3080                 :            : }
    3081                 :            : 
    3082                 :            : static void
    3083                 :            : signal_emitv_unlocked (const GValue *instance_and_params,
    3084                 :            :                        guint         signal_id,
    3085                 :            :                        GQuark        detail,
    3086                 :            :                        GValue       *return_value);
    3087                 :            : 
    3088                 :            : /**
    3089                 :            :  * g_signal_emitv:
    3090                 :            :  * @instance_and_params: (array): argument list for the signal emission.
    3091                 :            :  *  The first element in the array is a #GValue for the instance the signal
    3092                 :            :  *  is being emitted on. The rest are any arguments to be passed to the signal.
    3093                 :            :  * @signal_id: the signal id
    3094                 :            :  * @detail: the detail
    3095                 :            :  * @return_value: (inout) (optional): Location to
    3096                 :            :  * store the return value of the signal emission. This must be provided if the
    3097                 :            :  * specified signal returns a value, but may be ignored otherwise.
    3098                 :            :  *
    3099                 :            :  * Emits a signal. Signal emission is done synchronously.
    3100                 :            :  * The method will only return control after all handlers are called or signal emission was stopped.
    3101                 :            :  *
    3102                 :            :  * Note that g_signal_emitv() doesn't change @return_value if no handlers are
    3103                 :            :  * connected, in contrast to g_signal_emit() and g_signal_emit_valist().
    3104                 :            :  */
    3105                 :            : void
    3106                 :         50 : g_signal_emitv (const GValue *instance_and_params,
    3107                 :            :                 guint         signal_id,
    3108                 :            :                 GQuark        detail,
    3109                 :            :                 GValue       *return_value)
    3110                 :            : {
    3111                 :         50 :   SIGNAL_LOCK ();
    3112                 :         50 :   signal_emitv_unlocked (instance_and_params, signal_id, detail, return_value);
    3113                 :         50 :   SIGNAL_UNLOCK ();
    3114                 :         50 : }
    3115                 :            : 
    3116                 :            : static void
    3117                 :         50 : signal_emitv_unlocked (const GValue *instance_and_params,
    3118                 :            :                        guint         signal_id,
    3119                 :            :                        GQuark        detail,
    3120                 :            :                        GValue       *return_value)
    3121                 :            : {
    3122                 :            :   gpointer instance;
    3123                 :            :   SignalNode *node;
    3124                 :            : #ifdef G_ENABLE_DEBUG
    3125                 :            :   const GValue *param_values;
    3126                 :            :   guint i;
    3127                 :            : #endif
    3128                 :            :   
    3129                 :         52 :   g_return_if_fail (instance_and_params != NULL);
    3130                 :         50 :   instance = g_value_peek_pointer (instance_and_params);
    3131                 :         50 :   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
    3132                 :         50 :   g_return_if_fail (signal_id > 0);
    3133                 :            : 
    3134                 :            : #ifdef G_ENABLE_DEBUG
    3135                 :         50 :   param_values = instance_and_params + 1;
    3136                 :            : #endif
    3137                 :            : 
    3138                 :         50 :   node = LOOKUP_SIGNAL_NODE (signal_id);
    3139   [ +  -  +  +  :         50 :   if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
                   -  + ]
    3140                 :            :     {
    3141                 :          0 :       g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
    3142                 :          0 :       return;
    3143                 :            :     }
    3144                 :            : #ifdef G_ENABLE_DEBUG
    3145   [ -  +  -  - ]:         50 :   if (detail && !(node->flags & G_SIGNAL_DETAILED))
    3146                 :            :     {
    3147                 :          0 :       g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
    3148                 :          0 :       return;
    3149                 :            :     }
    3150         [ +  + ]:        219 :   for (i = 0; i < node->n_params; i++)
    3151   [ -  +  +  -  :        169 :     if (!G_TYPE_CHECK_VALUE_TYPE (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))
                   -  + ]
    3152                 :            :       {
    3153                 :          0 :         g_critical ("%s: value for '%s' parameter %u for signal \"%s\" is of type '%s'",
    3154                 :            :                     G_STRLOC,
    3155                 :            :                     type_debug_name (node->param_types[i]),
    3156                 :            :                     i,
    3157                 :            :                     node->name,
    3158                 :            :                     G_VALUE_TYPE_NAME (param_values + i));
    3159                 :          0 :         return;
    3160                 :            :       }
    3161         [ +  + ]:         50 :   if (node->return_type != G_TYPE_NONE)
    3162                 :            :     {
    3163         [ +  + ]:         39 :       if (!return_value)
    3164                 :            :         {
    3165                 :          1 :           g_critical ("%s: return value '%s' for signal \"%s\" is (NULL)",
    3166                 :            :                       G_STRLOC,
    3167                 :            :                       type_debug_name (node->return_type),
    3168                 :            :                       node->name);
    3169                 :          1 :           return;
    3170                 :            :         }
    3171   [ +  +  -  +  :         38 :       else if (!node->accumulator && !G_TYPE_CHECK_VALUE_TYPE (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE))
             +  +  +  + ]
    3172                 :            :         {
    3173                 :          1 :           g_critical ("%s: return value '%s' for signal \"%s\" is of type '%s'",
    3174                 :            :                       G_STRLOC,
    3175                 :            :                       type_debug_name (node->return_type),
    3176                 :            :                       node->name,
    3177                 :            :                       G_VALUE_TYPE_NAME (return_value));
    3178                 :          1 :           return;
    3179                 :            :         }
    3180                 :            :     }
    3181                 :            :   else
    3182                 :         11 :     return_value = NULL;
    3183                 :            : #endif  /* G_ENABLE_DEBUG */
    3184                 :            : 
    3185                 :            :   /* optimize NOP emissions */
    3186         [ +  + ]:         48 :   if (!node->single_va_closure_is_valid)
    3187                 :         34 :     node_update_single_va_closure (node);
    3188                 :            : 
    3189         [ -  + ]:         48 :   if (node->single_va_closure != NULL &&
    3190   [ #  #  #  # ]:          0 :       (node->single_va_closure == SINGLE_VA_CLOSURE_EMPTY_MAGIC ||
    3191                 :          0 :        _g_closure_is_void (node->single_va_closure, instance)))
    3192                 :            :     {
    3193                 :            :       HandlerList* hlist;
    3194                 :            : 
    3195                 :            :       /* single_va_closure is only true for GObjects, so fast path if no handler ever connected to the signal */
    3196         [ #  # ]:          0 :       if (_g_object_has_signal_handler ((GObject *)instance))
    3197                 :          0 :         hlist = handler_list_lookup (node->signal_id, instance);
    3198                 :            :       else
    3199                 :          0 :         hlist = NULL;
    3200                 :            : 
    3201   [ #  #  #  # ]:          0 :       if (hlist == NULL || hlist->handlers == NULL)
    3202                 :            :         {
    3203                 :            :           /* nothing to do to emit this signal */
    3204                 :            :           /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
    3205                 :          0 :           return;
    3206                 :            :         }
    3207                 :            :     }
    3208                 :            : 
    3209                 :            :   /* Pass a stable node pointer, whose address can't change even if the
    3210                 :            :    * g_signal_nodes array gets reallocated. */
    3211                 :         48 :   SignalNode node_copy = *node;
    3212                 :         48 :   signal_emit_unlocked_R (&node_copy, detail, instance, return_value, instance_and_params);
    3213                 :            : }
    3214                 :            : 
    3215                 :            : static inline gboolean
    3216                 :   27394870 : accumulate (GSignalInvocationHint *ihint,
    3217                 :            :             GValue                *return_accu,
    3218                 :            :             GValue                *handler_return,
    3219                 :            :             SignalAccumulator     *accumulator)
    3220                 :            : {
    3221                 :            :   gboolean continue_emission;
    3222                 :            : 
    3223         [ +  # ]:   27394870 :   if (!accumulator)
    3224                 :   27400251 :     return TRUE;
    3225                 :            : 
    3226                 :          0 :   continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data);
    3227                 :       2311 :   g_value_reset (handler_return);
    3228                 :            : 
    3229                 :       2311 :   ihint->run_type &= ~G_SIGNAL_ACCUMULATOR_FIRST_RUN;
    3230                 :            : 
    3231                 :       2311 :   return continue_emission;
    3232                 :            : }
    3233                 :            : 
    3234                 :            : static gboolean
    3235                 :            : signal_emit_valist_unlocked (gpointer instance,
    3236                 :            :                              guint    signal_id,
    3237                 :            :                              GQuark   detail,
    3238                 :            :                              va_list  var_args);
    3239                 :            : 
    3240                 :            : /**
    3241                 :            :  * g_signal_emit_valist: (skip)
    3242                 :            :  * @instance: (type GObject.TypeInstance): the instance the signal is being
    3243                 :            :  *    emitted on.
    3244                 :            :  * @signal_id: the signal id
    3245                 :            :  * @detail: the detail
    3246                 :            :  * @var_args: a list of parameters to be passed to the signal, followed by a
    3247                 :            :  *  location for the return value. If the return type of the signal
    3248                 :            :  *  is %G_TYPE_NONE, the return value location can be omitted.
    3249                 :            :  *
    3250                 :            :  * Emits a signal. Signal emission is done synchronously.
    3251                 :            :  * The method will only return control after all handlers are called or signal emission was stopped.
    3252                 :            :  *
    3253                 :            :  * Note that g_signal_emit_valist() resets the return value to the default
    3254                 :            :  * if no handlers are connected, in contrast to g_signal_emitv().
    3255                 :            :  */
    3256                 :            : void
    3257                 :   36856534 : g_signal_emit_valist (gpointer instance,
    3258                 :            :                       guint    signal_id,
    3259                 :            :                       GQuark   detail,
    3260                 :            :                       va_list  var_args)
    3261                 :            : {
    3262                 :   36856534 :   SIGNAL_LOCK ();
    3263         [ +  + ]:   36876840 :   if (signal_emit_valist_unlocked (instance, signal_id, detail, var_args))
    3264                 :   19761491 :     SIGNAL_UNLOCK ();
    3265                 :   36863738 : }
    3266                 :            : 
    3267                 :            : /*<private>
    3268                 :            :  * signal_emit_valist_unlocked:
    3269                 :            :  * @instance: The instance to emit from
    3270                 :            :  * @signal_id: Signal id to emit
    3271                 :            :  * @detail: Signal detail
    3272                 :            :  * @var_args: Call arguments
    3273                 :            :  *
    3274                 :            :  * Returns: %TRUE if the signal mutex has been left locked
    3275                 :            :  */
    3276                 :            : static gboolean
    3277                 :   36877253 : signal_emit_valist_unlocked (gpointer instance,
    3278                 :            :                              guint    signal_id,
    3279                 :            :                              GQuark   detail,
    3280                 :            :                              va_list  var_args)
    3281                 :            : {
    3282                 :            :   GValue *instance_and_params;
    3283                 :            :   GValue *param_values;
    3284                 :            :   SignalNode *node;
    3285                 :            :   guint i;
    3286                 :            : 
    3287                 :   36877253 :   g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), TRUE);
    3288                 :   36877253 :   g_return_val_if_fail (signal_id > 0, TRUE);
    3289                 :            : 
    3290                 :   36877253 :   node = LOOKUP_SIGNAL_NODE (signal_id);
    3291   [ +  -  +  +  :   36877253 :   if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
                   -  + ]
    3292                 :            :     {
    3293                 :          0 :       g_critical ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
    3294                 :          0 :       return TRUE;
    3295                 :            :     }
    3296                 :            : #ifndef G_DISABLE_CHECKS
    3297   [ +  +  -  + ]:   36877253 :   if (detail && !(node->flags & G_SIGNAL_DETAILED))
    3298                 :            :     {
    3299                 :          0 :       g_critical ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
    3300                 :          0 :       return TRUE;
    3301                 :            :     }
    3302                 :            : #endif  /* !G_DISABLE_CHECKS */
    3303                 :            : 
    3304         [ +  + ]:   36877253 :   if (!node->single_va_closure_is_valid)
    3305                 :        438 :     node_update_single_va_closure (node);
    3306                 :            : 
    3307                 :            :   /* There's no need to deep copy this, because a SignalNode instance won't
    3308                 :            :    * ever be destroyed, given that _g_signals_destroy() is not called in any
    3309                 :            :    * real program, however the SignalNode pointer could change, so just store
    3310                 :            :    * the struct contents references, so that we won't try to deference a
    3311                 :            :    * potentially invalid (or changed) pointer;
    3312                 :            :    */
    3313                 :   36877253 :   SignalNode node_copy = *node;
    3314                 :            : 
    3315         [ +  + ]:   36877253 :   if (node->single_va_closure != NULL)
    3316                 :            :     {
    3317                 :            :       HandlerList* hlist;
    3318                 :   36774690 :       Handler *fastpath_handler = NULL;
    3319                 :            :       Handler *l;
    3320                 :   36774690 :       GClosure *closure = NULL;
    3321                 :   36774690 :       gboolean fastpath = TRUE;
    3322                 :   36774690 :       GSignalFlags run_type = G_SIGNAL_RUN_FIRST;
    3323                 :            : 
    3324   [ +  +  +  + ]:   73218973 :       if (node->single_va_closure != SINGLE_VA_CLOSURE_EMPTY_MAGIC &&
    3325                 :   36444283 :           !_g_closure_is_void (node->single_va_closure, instance))
    3326                 :            :         {
    3327         [ +  + ]:    9352832 :           if (_g_closure_supports_invoke_va (node->single_va_closure))
    3328                 :            :             {
    3329                 :     141858 :               closure = node->single_va_closure;
    3330         [ +  + ]:     141858 :               if (node->single_va_closure_is_after)
    3331                 :       1859 :                 run_type = G_SIGNAL_RUN_LAST;
    3332                 :            :               else
    3333                 :     139999 :                 run_type = G_SIGNAL_RUN_FIRST;
    3334                 :            :             }
    3335                 :            :           else
    3336                 :    9210974 :             fastpath = FALSE;
    3337                 :            :         }
    3338                 :            : 
    3339                 :            :       /* single_va_closure is only true for GObjects, so fast path if no handler ever connected to the signal */
    3340         [ +  + ]:   36774690 :       if (_g_object_has_signal_handler ((GObject *)instance))
    3341                 :   12117673 :         hlist = handler_list_lookup (node->signal_id, instance);
    3342                 :            :       else
    3343                 :   24657017 :         hlist = NULL;
    3344                 :            : 
    3345   [ +  +  +  +  :   41689318 :       for (l = hlist ? hlist->handlers : NULL; fastpath && l != NULL; l = l->next)
                   +  + ]
    3346                 :            :         {
    3347         [ +  + ]:    7858607 :           if (!l->block_count &&
    3348   [ +  +  +  + ]:    7858324 :               (!l->detail || l->detail == detail))
    3349                 :            :             {
    3350   [ +  +  +  + ]:    7730562 :               if (closure != NULL || !_g_closure_supports_invoke_va (l->closure))
    3351                 :            :                 {
    3352                 :    2943979 :                   fastpath = FALSE;
    3353                 :    2943979 :                   break;
    3354                 :            :                 }
    3355                 :            :               else
    3356                 :            :                 {
    3357                 :    4786583 :                   fastpath_handler = l;
    3358                 :    4786583 :                   closure = l->closure;
    3359         [ -  + ]:    4786583 :                   if (l->after)
    3360                 :          0 :                     run_type = G_SIGNAL_RUN_LAST;
    3361                 :            :                   else
    3362                 :    4786583 :                     run_type = G_SIGNAL_RUN_FIRST;
    3363                 :            :                 }
    3364                 :            :             }
    3365                 :            :         }
    3366                 :            : 
    3367   [ +  +  +  +  :   36774690 :       if (fastpath && closure == NULL && node_copy.return_type == G_TYPE_NONE)
                   +  - ]
    3368                 :   19761648 :         return TRUE;
    3369                 :            : 
    3370                 :            :       /* Don't allow no-recurse emission as we might have to restart, which means
    3371                 :            :          we will run multiple handlers and thus must ref all arguments */
    3372   [ +  +  +  + ]:   17013042 :       if (closure != NULL && (node_copy.flags & (G_SIGNAL_NO_RECURSE)) != 0)
    3373                 :    4616971 :         fastpath = FALSE;
    3374                 :            :       
    3375         [ +  + ]:   17013042 :       if (fastpath)
    3376                 :            :         {
    3377                 :            :           Emission emission;
    3378                 :     241137 :           GValue *return_accu, accu = G_VALUE_INIT;
    3379                 :     241137 :           GType instance_type = G_TYPE_FROM_INSTANCE (instance);
    3380                 :     241137 :           GValue emission_return = G_VALUE_INIT;
    3381                 :     241137 :           GType rtype = node_copy.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
    3382                 :     241137 :           gboolean static_scope = node_copy.return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
    3383                 :            : 
    3384         [ +  + ]:     241137 :           if (rtype == G_TYPE_NONE)
    3385                 :     240255 :             return_accu = NULL;
    3386         [ +  + ]:        882 :           else if (node_copy.accumulator)
    3387                 :        867 :             return_accu = &accu;
    3388                 :            :           else
    3389                 :         15 :             return_accu = &emission_return;
    3390                 :            : 
    3391                 :     241137 :           emission.instance = instance;
    3392                 :     241137 :           emission.ihint.signal_id = signal_id;
    3393                 :     241137 :           emission.ihint.detail = detail;
    3394                 :     241137 :           emission.ihint.run_type = run_type | G_SIGNAL_ACCUMULATOR_FIRST_RUN;
    3395                 :     241137 :           emission.state = EMISSION_RUN;
    3396                 :     241137 :           emission.chain_type = instance_type;
    3397                 :     241137 :           emission_push (&emission);
    3398                 :            : 
    3399         [ +  + ]:     241137 :           if (fastpath_handler)
    3400                 :     169703 :             handler_ref (fastpath_handler);
    3401                 :            : 
    3402         [ +  - ]:     241137 :           if (closure != NULL)
    3403                 :            :             {
    3404                 :     241137 :           TRACE(GOBJECT_SIGNAL_EMIT(signal_id, detail, instance, instance_type));
    3405                 :            : 
    3406                 :     241137 :               SIGNAL_UNLOCK ();
    3407                 :            : 
    3408         [ +  + ]:     241137 :           if (rtype != G_TYPE_NONE)
    3409                 :        882 :             g_value_init (&emission_return, rtype);
    3410                 :            : 
    3411         [ +  + ]:     241137 :               if (node_copy.accumulator)
    3412                 :        867 :                 g_value_init (&accu, rtype);
    3413                 :            : 
    3414                 :            :               /*
    3415                 :            :                * Coverity doesn’t understand the paired ref/unref here and seems
    3416                 :            :                * to ignore the ref, thus reports every call to g_signal_emit()
    3417                 :            :                * as causing a double-free. That’s incorrect, but I can’t get a
    3418                 :            :                * model file to work for avoiding the false positives, so instead
    3419                 :            :                * comment out the ref/unref when doing static analysis.
    3420                 :            :                */
    3421                 :            : #ifndef __COVERITY__
    3422                 :     241137 :               g_object_ref (instance);
    3423                 :            : #endif
    3424                 :     241137 :               _g_closure_invoke_va (closure,
    3425                 :            :                                     return_accu,
    3426                 :            :                                     instance,
    3427                 :            :                                     var_args,
    3428                 :     241137 :                                     node_copy.n_params,
    3429                 :            :                                     node_copy.param_types);
    3430                 :     241135 :               accumulate (&emission.ihint, &emission_return, &accu, node_copy.accumulator);
    3431                 :            : 
    3432         [ +  + ]:     241135 :               if (node_copy.accumulator)
    3433                 :        867 :                 g_value_unset (&accu);
    3434                 :            : 
    3435                 :     241135 :               SIGNAL_LOCK ();
    3436                 :            :             }
    3437                 :            : 
    3438                 :     241135 :           emission.chain_type = G_TYPE_NONE;
    3439                 :     241135 :           emission_pop (&emission);
    3440                 :            : 
    3441         [ +  + ]:     241135 :           if (fastpath_handler)
    3442                 :     169701 :             handler_unref_R (signal_id, instance, fastpath_handler);
    3443                 :            : 
    3444                 :     241135 :           SIGNAL_UNLOCK ();
    3445                 :            : 
    3446         [ +  + ]:     241135 :           if (rtype != G_TYPE_NONE)
    3447                 :            :             {
    3448                 :        882 :               gchar *error = NULL;
    3449         [ +  + ]:       2348 :               for (i = 0; i < node_copy.n_params; i++)
    3450                 :            :                 {
    3451                 :       1466 :                   GType ptype = node_copy.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
    3452   [ +  -  -  -  :       2932 :                   G_VALUE_COLLECT_SKIP (ptype, var_args);
             +  -  +  + ]
    3453                 :            :                 }
    3454                 :            : 
    3455         [ -  + ]:        882 :               if (closure == NULL)
    3456                 :          0 :                 g_value_init (&emission_return, rtype);
    3457                 :            : 
    3458   [ -  +  -  -  :       1764 :               G_VALUE_LCOPY (&emission_return,
          -  -  +  -  +  
                      + ]
    3459                 :            :                              var_args,
    3460                 :            :                              static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
    3461                 :            :                              &error);
    3462         [ +  - ]:        882 :               if (!error)
    3463                 :        882 :                 g_value_unset (&emission_return);
    3464                 :            :               else
    3465                 :            :                 {
    3466                 :          0 :                   g_critical ("%s: %s", G_STRLOC, error);
    3467                 :          0 :                   g_free (error);
    3468                 :            :                   /* we purposely leak the value here, it might not be
    3469                 :            :                    * in a correct state if an error condition occurred
    3470                 :            :                    */
    3471                 :            :                 }
    3472                 :            :             }
    3473                 :            :           
    3474                 :     241135 :           TRACE(GOBJECT_SIGNAL_EMIT_END(signal_id, detail, instance, instance_type));
    3475                 :            : 
    3476                 :            :           /* See comment above paired ref above */
    3477                 :            : #ifndef __COVERITY__
    3478         [ +  - ]:     241135 :           if (closure != NULL)
    3479                 :     241135 :             g_object_unref (instance);
    3480                 :            : #endif
    3481                 :            : 
    3482                 :     241135 :           return FALSE;
    3483                 :            :         }
    3484                 :            :     }
    3485                 :            : 
    3486                 :   16874468 :   SIGNAL_UNLOCK ();
    3487                 :            : 
    3488         [ +  # ]:   16873543 :   instance_and_params = g_newa0 (GValue, node_copy.n_params + 1);
    3489                 :   16873543 :   param_values = instance_and_params + 1;
    3490                 :            : 
    3491         [ +  + ]:   33697048 :   for (i = 0; i < node_copy.n_params; i++)
    3492                 :            :     {
    3493                 :            :       gchar *error;
    3494                 :   16825790 :       GType ptype = node_copy.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
    3495                 :   16825790 :       gboolean static_scope = node_copy.param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
    3496                 :            : 
    3497   [ +  +  +  +  :   33650052 :       G_VALUE_COLLECT_INIT (param_values + i, ptype,
          +  +  +  -  +  
                      + ]
    3498                 :            :                             var_args,
    3499                 :            :                             static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
    3500                 :            :                             &error);
    3501         [ +  + ]:   16823671 :       if (error)
    3502                 :            :         {
    3503                 :        166 :           g_critical ("%s: %s", G_STRLOC, error);
    3504                 :          0 :           g_free (error);
    3505                 :            : 
    3506                 :            :           /* we purposely leak the value here, it might not be
    3507                 :            :            * in a correct state if an error condition occurred
    3508                 :            :            */
    3509         [ #  # ]:          0 :           while (i--)
    3510                 :          0 :             g_value_unset (param_values + i);
    3511                 :            : 
    3512                 :          0 :           return FALSE;
    3513                 :            :         }
    3514                 :            :     }
    3515                 :            : 
    3516                 :   16871258 :   g_value_init_from_instance (instance_and_params, instance);
    3517         [ +  + ]:   16870526 :   if (node_copy.return_type == G_TYPE_NONE)
    3518                 :            :     {
    3519                 :   13661656 :       SIGNAL_LOCK ();
    3520                 :   13662550 :       signal_emit_unlocked_R (&node_copy, detail, instance, NULL, instance_and_params);
    3521                 :   13662544 :       SIGNAL_UNLOCK ();
    3522                 :            :     }
    3523                 :            :   else
    3524                 :            :     {
    3525                 :    3208870 :       GValue return_value = G_VALUE_INIT;
    3526                 :    3208870 :       gchar *error = NULL;
    3527                 :    3208870 :       GType rtype = node_copy.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
    3528                 :    3208870 :       gboolean static_scope = node_copy.return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
    3529                 :            :       
    3530                 :    3208870 :       g_value_init (&return_value, rtype);
    3531                 :            : 
    3532                 :    3206053 :       SIGNAL_LOCK ();
    3533                 :    3211918 :       signal_emit_unlocked_R (&node_copy, detail, instance, &return_value, instance_and_params);
    3534                 :    3211918 :       SIGNAL_UNLOCK ();
    3535                 :            : 
    3536   [ -  +  -  -  :    6419338 :       G_VALUE_LCOPY (&return_value,
          -  -  +  -  +  
                      + ]
    3537                 :            :                      var_args,
    3538                 :            :                      static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
    3539                 :            :                      &error);
    3540         [ +  + ]:    3211146 :       if (!error)
    3541                 :    3211097 :         g_value_unset (&return_value);
    3542                 :            :       else
    3543                 :            :         {
    3544                 :         49 :           g_critical ("%s: %s", G_STRLOC, error);
    3545                 :          0 :           g_free (error);
    3546                 :            :           
    3547                 :            :           /* we purposely leak the value here, it might not be
    3548                 :            :            * in a correct state if an error condition occurred
    3549                 :            :            */
    3550                 :            :         }
    3551                 :            :     }
    3552         [ +  + ]:   33674636 :   for (i = 0; i < node_copy.n_params; i++)
    3553                 :   16818349 :     g_value_unset (param_values + i);
    3554                 :   16856287 :   g_value_unset (instance_and_params);
    3555                 :            : 
    3556                 :   16863159 :   return FALSE;
    3557                 :            : }
    3558                 :            : 
    3559                 :            : /**
    3560                 :            :  * g_signal_emit:
    3561                 :            :  * @instance: (type GObject.Object): the instance the signal is being emitted on.
    3562                 :            :  * @signal_id: the signal id
    3563                 :            :  * @detail: the detail
    3564                 :            :  * @...: parameters to be passed to the signal, followed by a
    3565                 :            :  *  location for the return value. If the return type of the signal
    3566                 :            :  *  is %G_TYPE_NONE, the return value location can be omitted.
    3567                 :            :  *
    3568                 :            :  * Emits a signal. Signal emission is done synchronously.
    3569                 :            :  * The method will only return control after all handlers are called or signal emission was stopped.
    3570                 :            :  *
    3571                 :            :  * Note that g_signal_emit() resets the return value to the default
    3572                 :            :  * if no handlers are connected, in contrast to g_signal_emitv().
    3573                 :            :  */
    3574                 :            : void
    3575                 :   36862318 : g_signal_emit (gpointer instance,
    3576                 :            :                guint    signal_id,
    3577                 :            :                GQuark   detail,
    3578                 :            :                ...)
    3579                 :            : {
    3580                 :            :   va_list var_args;
    3581                 :            : 
    3582                 :   36862318 :   va_start (var_args, detail);
    3583                 :   36862318 :   g_signal_emit_valist (instance, signal_id, detail, var_args);
    3584                 :   36862991 :   va_end (var_args);
    3585                 :   36862991 : }
    3586                 :            : 
    3587                 :            : /**
    3588                 :            :  * g_signal_emit_by_name:
    3589                 :            :  * @instance: (type GObject.Object): the instance the signal is being emitted on.
    3590                 :            :  * @detailed_signal: a string of the form "signal-name::detail".
    3591                 :            :  * @...: parameters to be passed to the signal, followed by a
    3592                 :            :  *  location for the return value. If the return type of the signal
    3593                 :            :  *  is %G_TYPE_NONE, the return value location can be omitted. The
    3594                 :            :  *  number of parameters to pass to this function is defined when creating the signal.
    3595                 :            :  *
    3596                 :            :  * Emits a signal. Signal emission is done synchronously.
    3597                 :            :  * The method will only return control after all handlers are called or signal emission was stopped.
    3598                 :            :  *
    3599                 :            :  * Note that g_signal_emit_by_name() resets the return value to the default
    3600                 :            :  * if no handlers are connected, in contrast to g_signal_emitv().
    3601                 :            :  */
    3602                 :            : void
    3603                 :        413 : g_signal_emit_by_name (gpointer     instance,
    3604                 :            :                        const gchar *detailed_signal,
    3605                 :            :                        ...)
    3606                 :            : {
    3607                 :        413 :   GQuark detail = 0;
    3608                 :            :   guint signal_id;
    3609                 :            :   GType itype;
    3610                 :            : 
    3611                 :        413 :   g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance));
    3612                 :        413 :   g_return_if_fail (detailed_signal != NULL);
    3613                 :            : 
    3614                 :        413 :   itype = G_TYPE_FROM_INSTANCE (instance);
    3615                 :            : 
    3616                 :        413 :   SIGNAL_LOCK ();
    3617                 :        413 :   signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE);
    3618                 :            : 
    3619         [ +  - ]:        413 :   if (signal_id)
    3620                 :            :     {
    3621                 :            :       va_list var_args;
    3622                 :            : 
    3623                 :        413 :       va_start (var_args, detailed_signal);
    3624         [ +  + ]:        413 :       if (signal_emit_valist_unlocked (instance, signal_id, detail, var_args))
    3625                 :        157 :         SIGNAL_UNLOCK ();
    3626                 :        413 :       va_end (var_args);
    3627                 :            :     }
    3628                 :            :   else
    3629                 :            :     {
    3630                 :          0 :       SIGNAL_UNLOCK ();
    3631                 :            : 
    3632                 :          0 :       g_critical ("%s: signal name '%s' is invalid for instance '%p' of type '%s'",
    3633                 :            :                   G_STRLOC, detailed_signal, instance, g_type_name (itype));
    3634                 :            :     }
    3635                 :            : }
    3636                 :            : 
    3637                 :            : G_ALWAYS_INLINE static inline GValue *
    3638                 :            : maybe_init_accumulator_unlocked (SignalNode *node,
    3639                 :            :                                  GValue     *emission_return,
    3640                 :            :                                  GValue     *accumulator_value)
    3641                 :            : {
    3642   [ +  +  +  +  :   27163232 :   if (node->accumulator)
             +  +  +  + ]
    3643                 :            :     {
    3644   [ -  +  +  +  :       1440 :       if (accumulator_value->g_type)
             +  +  +  - ]
    3645                 :        563 :         return accumulator_value;
    3646                 :            : 
    3647                 :        877 :       g_value_init (accumulator_value,
    3648                 :        877 :                     node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
    3649                 :        877 :       return accumulator_value;
    3650                 :            :     }
    3651                 :            : 
    3652                 :   27161792 :   return emission_return;
    3653                 :            : }
    3654                 :            : 
    3655                 :            : static gboolean
    3656                 :   16874516 : signal_emit_unlocked_R (SignalNode   *node,
    3657                 :            :                         GQuark        detail,
    3658                 :            :                         gpointer      instance,
    3659                 :            :                         GValue       *emission_return,
    3660                 :            :                         const GValue *instance_and_params)
    3661                 :            : {
    3662                 :            :   SignalAccumulator *accumulator;
    3663                 :            :   Emission emission;
    3664                 :            :   GClosure *class_closure;
    3665                 :            :   HandlerList *hlist;
    3666                 :   16874516 :   Handler *handler_list = NULL;
    3667                 :   16874516 :   GValue *return_accu, accu = G_VALUE_INIT;
    3668                 :            :   guint signal_id;
    3669                 :            :   gulong max_sequential_handler_number;
    3670                 :   16874516 :   gboolean return_value_altered = FALSE;
    3671                 :            :   guint n_params;
    3672                 :            : 
    3673                 :   16874516 :   TRACE(GOBJECT_SIGNAL_EMIT(node->signal_id, detail, instance, G_TYPE_FROM_INSTANCE (instance)));
    3674                 :            : 
    3675                 :            :   /* We expect this function to be called with a stable SignalNode pointer
    3676                 :            :    * that cannot change location, so accessing its stable members should
    3677                 :            :    * always work even after a lock/unlock.
    3678                 :            :    */
    3679                 :   16874516 :   signal_id = node->signal_id;
    3680                 :   16874516 :   n_params = node->n_params + 1;
    3681                 :            : 
    3682         [ +  + ]:   16874516 :   if (node->flags & G_SIGNAL_NO_RECURSE)
    3683                 :            :     {
    3684                 :    4616971 :       Emission *emission_node = emission_find (signal_id, detail, instance);
    3685                 :            : 
    3686         [ +  + ]:    4616971 :       if (emission_node)
    3687                 :            :         {
    3688                 :      67861 :           emission_node->state = EMISSION_RESTART;
    3689                 :      67861 :           return return_value_altered;
    3690                 :            :         }
    3691                 :            :     }
    3692                 :   16806655 :   accumulator = node->accumulator;
    3693                 :   16806655 :   emission.instance = instance;
    3694                 :   16806655 :   emission.ihint.signal_id = node->signal_id;
    3695                 :   16806655 :   emission.ihint.detail = detail;
    3696                 :   16806655 :   emission.ihint.run_type = 0;
    3697                 :   16806655 :   emission.state = 0;
    3698                 :   16806655 :   emission.chain_type = G_TYPE_NONE;
    3699                 :   16806655 :   emission_push (&emission);
    3700                 :   16806655 :   class_closure = signal_lookup_closure (node, instance);
    3701                 :            :   
    3702                 :      39291 :  EMIT_RESTART:
    3703                 :            :   
    3704         [ +  + ]:   16845946 :   if (handler_list)
    3705                 :      39291 :     handler_unref_R (signal_id, instance, handler_list);
    3706                 :   16845946 :   max_sequential_handler_number = g_handler_sequential_number;
    3707                 :   16845946 :   hlist = handler_list_lookup (signal_id, instance);
    3708         [ +  + ]:   16845946 :   handler_list = hlist ? hlist->handlers : NULL;
    3709         [ +  + ]:   16845946 :   if (handler_list)
    3710                 :   10359506 :     handler_ref (handler_list);
    3711                 :            :   
    3712                 :   16845946 :   emission.ihint.run_type = G_SIGNAL_RUN_FIRST | G_SIGNAL_ACCUMULATOR_FIRST_RUN;
    3713                 :            :   
    3714   [ +  +  +  + ]:   16845946 :   if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure)
    3715                 :            :     {
    3716                 :    4987759 :       emission.state = EMISSION_RUN;
    3717                 :            : 
    3718                 :    4987759 :       emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
    3719                 :    4987759 :       SIGNAL_UNLOCK ();
    3720                 :    4987712 :       return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
    3721                 :    4987712 :       g_closure_invoke (class_closure,
    3722                 :            :                         return_accu,
    3723                 :            :                         n_params,
    3724                 :            :                         instance_and_params,
    3725                 :            :                         &emission.ihint);
    3726         [ -  + ]:    4987707 :       if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
    3727         [ #  # ]:          0 :           emission.state == EMISSION_RUN)
    3728                 :          0 :         emission.state = EMISSION_STOP;
    3729                 :    4987680 :       SIGNAL_LOCK ();
    3730                 :    4987759 :       emission.chain_type = G_TYPE_NONE;
    3731                 :    4987759 :       return_value_altered = TRUE;
    3732                 :            :       
    3733         [ -  + ]:    4987759 :       if (emission.state == EMISSION_STOP)
    3734                 :          0 :         goto EMIT_CLEANUP;
    3735         [ +  + ]:    4987759 :       else if (emission.state == EMISSION_RESTART)
    3736                 :      17549 :         goto EMIT_RESTART;
    3737                 :            :     }
    3738                 :            : 
    3739         [ +  + ]:   16828397 :   if (node->emission_hooks)
    3740                 :            :     {
    3741                 :            :       GHook *hook;
    3742                 :            :       GHook *static_emission_hooks[3];
    3743                 :         14 :       size_t n_emission_hooks = 0;
    3744                 :         14 :       const gboolean may_recurse = TRUE;
    3745                 :            :       guint i;
    3746                 :            : 
    3747                 :         14 :       emission.state = EMISSION_HOOK;
    3748                 :            : 
    3749                 :            :       /* Quick check to determine whether any hooks match this emission,
    3750                 :            :        * before committing to the more complex work of calling those hooks.
    3751                 :            :        * We save a few of them into a static array, to try to avoid further
    3752                 :            :        * allocations.
    3753                 :            :        */
    3754                 :         14 :       hook = g_hook_first_valid (node->emission_hooks, may_recurse);
    3755         [ +  + ]:         51 :       while (hook)
    3756                 :            :         {
    3757                 :         37 :           SignalHook *signal_hook = SIGNAL_HOOK (hook);
    3758                 :            : 
    3759   [ -  +  -  - ]:         37 :           if (!signal_hook->detail || signal_hook->detail == detail)
    3760                 :            :             {
    3761         [ +  + ]:         37 :               if (n_emission_hooks < G_N_ELEMENTS (static_emission_hooks))
    3762                 :            :                 {
    3763                 :         16 :                   static_emission_hooks[n_emission_hooks] =
    3764                 :         16 :                     g_hook_ref (node->emission_hooks, hook);
    3765                 :            :                 }
    3766                 :            : 
    3767                 :         37 :               n_emission_hooks += 1;
    3768                 :            :             }
    3769                 :            : 
    3770                 :         37 :           hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse);
    3771                 :            :         }
    3772                 :            : 
    3773                 :            :       /* Re-iterate back through the matching hooks and copy them into
    3774                 :            :        * an array which won’t change when we unlock to call the
    3775                 :            :        * user-provided hook functions.
    3776                 :            :        * These functions may change hook configuration for this signal,
    3777                 :            :        * add / remove signal handlers, etc.
    3778                 :            :        */
    3779         [ +  + ]:         14 :       if G_UNLIKELY (n_emission_hooks > 0)
    3780                 :            :         {
    3781                 :            :           guint8 static_hook_returns[G_N_ELEMENTS (static_emission_hooks)];
    3782                 :         10 :           GHook **emission_hooks = NULL;
    3783                 :         10 :           guint8 *hook_returns = NULL;
    3784                 :            : 
    3785         [ +  + ]:         10 :           if G_LIKELY (n_emission_hooks <= G_N_ELEMENTS (static_emission_hooks))
    3786                 :            :             {
    3787                 :          7 :               emission_hooks = static_emission_hooks;
    3788                 :          7 :               hook_returns = static_hook_returns;
    3789                 :            :             }
    3790                 :            :           else
    3791                 :            :             {
    3792                 :          3 :               emission_hooks = g_newa (GHook *, n_emission_hooks);
    3793                 :          3 :               hook_returns = g_newa (guint8, n_emission_hooks);
    3794                 :            : 
    3795                 :            :               /* We can't just memcpy the ones we have in the static array,
    3796                 :            :                * to the alloca()'d one because otherwise we'd get an invalid
    3797                 :            :                * ID assertion during unref
    3798                 :            :                */
    3799                 :          3 :               i = 0;
    3800                 :          3 :               for (hook = g_hook_first_valid (node->emission_hooks, may_recurse);
    3801         [ +  + ]:         33 :                    hook != NULL;
    3802                 :         30 :                    hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse))
    3803                 :            :                 {
    3804                 :         30 :                   SignalHook *signal_hook = SIGNAL_HOOK (hook);
    3805                 :            : 
    3806   [ -  +  -  - ]:         30 :                   if (!signal_hook->detail || signal_hook->detail == detail)
    3807                 :            :                     {
    3808         [ +  + ]:         30 :                        if (i < G_N_ELEMENTS (static_emission_hooks))
    3809                 :            :                          {
    3810                 :          9 :                             emission_hooks[i] = g_steal_pointer (&static_emission_hooks[i]);
    3811                 :          9 :                             g_assert (emission_hooks[i] == hook);
    3812                 :            :                          }
    3813                 :            :                        else
    3814                 :            :                          {
    3815                 :         21 :                             emission_hooks[i] = g_hook_ref (node->emission_hooks, hook);
    3816                 :            :                          }
    3817                 :            : 
    3818                 :         30 :                       i += 1;
    3819                 :            :                     }
    3820                 :            :                 }
    3821                 :            : 
    3822                 :          3 :                g_assert (i == n_emission_hooks);
    3823                 :            :             }
    3824                 :            : 
    3825                 :         10 :             SIGNAL_UNLOCK ();
    3826                 :            : 
    3827         [ +  + ]:         47 :             for (i = 0; i < n_emission_hooks; ++i)
    3828                 :            :               {
    3829                 :            :                 GSignalEmissionHook hook_func;
    3830                 :            :                 gboolean need_destroy;
    3831                 :            :                 guint old_flags;
    3832                 :            : 
    3833                 :         37 :                 hook = emission_hooks[i];
    3834                 :         37 :                 hook_func = (GSignalEmissionHook) hook->func;
    3835                 :            : 
    3836                 :         37 :                 old_flags = g_atomic_int_or (&hook->flags, G_HOOK_FLAG_IN_CALL);
    3837                 :         37 :                 need_destroy = !hook_func (&emission.ihint, n_params,
    3838                 :            :                                            instance_and_params, hook->data);
    3839                 :            : 
    3840         [ +  - ]:         37 :                 if (!(old_flags & G_HOOK_FLAG_IN_CALL))
    3841                 :            :                   {
    3842                 :         37 :                     g_atomic_int_compare_and_exchange (&hook->flags,
    3843                 :            :                                                        old_flags | G_HOOK_FLAG_IN_CALL,
    3844                 :            :                                                        old_flags);
    3845                 :            :                   }
    3846                 :            : 
    3847                 :         37 :                 hook_returns[i] = !!need_destroy;
    3848                 :            :               }
    3849                 :            : 
    3850                 :         10 :             SIGNAL_LOCK ();
    3851                 :            : 
    3852         [ +  + ]:         47 :             for (i = 0; i < n_emission_hooks; i++)
    3853                 :            :               {
    3854                 :         37 :                 hook = emission_hooks[i];
    3855                 :            : 
    3856                 :         37 :                 g_hook_unref (node->emission_hooks, hook);
    3857                 :            : 
    3858         [ +  + ]:         37 :                 if (hook_returns[i])
    3859                 :         11 :                   g_hook_destroy_link (node->emission_hooks, hook);
    3860                 :            :               }
    3861                 :            :         }
    3862                 :            : 
    3863         [ -  + ]:         14 :       if (emission.state == EMISSION_RESTART)
    3864                 :          0 :         goto EMIT_RESTART;
    3865                 :            :     }
    3866                 :            :   
    3867         [ +  + ]:   16828397 :   if (handler_list)
    3868                 :            :     {
    3869                 :   10341957 :       Handler *handler = handler_list;
    3870                 :            :       
    3871                 :   10341957 :       emission.state = EMISSION_RUN;
    3872                 :   10341957 :       handler_ref (handler);
    3873                 :            :       do
    3874                 :            :         {
    3875                 :            :           Handler *tmp;
    3876                 :            :           
    3877         [ +  + ]:   10470599 :           if (handler->after)
    3878                 :            :             {
    3879                 :         24 :               handler_unref_R (signal_id, instance, handler_list);
    3880                 :         24 :               handler_list = handler;
    3881                 :         24 :               break;
    3882                 :            :             }
    3883   [ +  -  +  +  :   10470575 :           else if (!handler->block_count && (!handler->detail || handler->detail == detail) &&
                   +  + ]
    3884         [ +  + ]:   10343119 :                    handler->sequential_number < max_sequential_handler_number)
    3885                 :            :             {
    3886                 :   10343118 :               SIGNAL_UNLOCK ();
    3887                 :   10342601 :               return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
    3888                 :   10342601 :               g_closure_invoke (handler->closure,
    3889                 :            :                                 return_accu,
    3890                 :            :                                 n_params,
    3891                 :            :                                 instance_and_params,
    3892                 :            :                                 &emission.ihint);
    3893         [ +  + ]:   10342689 :               if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
    3894         [ +  - ]:        322 :                   emission.state == EMISSION_RUN)
    3895                 :        322 :                 emission.state = EMISSION_STOP;
    3896                 :   10342491 :               SIGNAL_LOCK ();
    3897                 :   10343112 :               return_value_altered = TRUE;
    3898                 :            :               
    3899         [ +  + ]:   10343112 :               tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
    3900                 :            :             }
    3901                 :            :           else
    3902                 :     127457 :             tmp = handler->next;
    3903                 :            :           
    3904         [ +  + ]:   10470569 :           if (tmp)
    3905                 :     128642 :             handler_ref (tmp);
    3906                 :   10470569 :           handler_unref_R (signal_id, instance, handler_list);
    3907                 :   10470569 :           handler_list = handler;
    3908                 :   10470569 :           handler = tmp;
    3909                 :            :         }
    3910         [ +  + ]:   10470569 :       while (handler);
    3911                 :            :       
    3912         [ +  + ]:   10341951 :       if (emission.state == EMISSION_STOP)
    3913                 :        324 :         goto EMIT_CLEANUP;
    3914         [ +  + ]:   10341627 :       else if (emission.state == EMISSION_RESTART)
    3915                 :      21742 :         goto EMIT_RESTART;
    3916                 :            :     }
    3917                 :            :   
    3918                 :   16806325 :   emission.ihint.run_type &= ~G_SIGNAL_RUN_FIRST;
    3919                 :   16806325 :   emission.ihint.run_type |= G_SIGNAL_RUN_LAST;
    3920                 :            :   
    3921   [ +  +  +  + ]:   16806325 :   if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure)
    3922                 :            :     {
    3923                 :   11838687 :       emission.state = EMISSION_RUN;
    3924                 :            :       
    3925                 :   11838687 :       emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
    3926                 :   11838687 :       SIGNAL_UNLOCK ();
    3927                 :   11832896 :       return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
    3928                 :   11832896 :       g_closure_invoke (class_closure,
    3929                 :            :                         return_accu,
    3930                 :            :                         n_params,
    3931                 :            :                         instance_and_params,
    3932                 :            :                         &emission.ihint);
    3933         [ +  + ]:   11833996 :       if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
    3934         [ +  - ]:          2 :           emission.state == EMISSION_RUN)
    3935                 :          2 :         emission.state = EMISSION_STOP;
    3936                 :   11832584 :       SIGNAL_LOCK ();
    3937                 :   11838687 :       emission.chain_type = G_TYPE_NONE;
    3938                 :   11838687 :       return_value_altered = TRUE;
    3939                 :            :       
    3940         [ +  + ]:   11838687 :       if (emission.state == EMISSION_STOP)
    3941                 :          2 :         goto EMIT_CLEANUP;
    3942         [ -  + ]:   11838685 :       else if (emission.state == EMISSION_RESTART)
    3943                 :          0 :         goto EMIT_RESTART;
    3944                 :            :     }
    3945                 :            :   
    3946         [ +  + ]:   16806323 :   if (handler_list)
    3947                 :            :     {
    3948                 :   10319884 :       Handler *handler = handler_list;
    3949                 :            :       
    3950                 :   10319884 :       emission.state = EMISSION_RUN;
    3951                 :   10319884 :       handler_ref (handler);
    3952                 :            :       do
    3953                 :            :         {
    3954                 :            :           Handler *tmp;
    3955                 :            :           
    3956   [ +  +  +  -  :   10319884 :           if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail) &&
             -  +  -  - ]
    3957         [ +  - ]:         23 :               handler->sequential_number < max_sequential_handler_number)
    3958                 :            :             {
    3959                 :         23 :               SIGNAL_UNLOCK ();
    3960                 :         23 :               return_accu = maybe_init_accumulator_unlocked (node, emission_return, &accu);
    3961                 :         23 :               g_closure_invoke (handler->closure,
    3962                 :            :                                 return_accu,
    3963                 :            :                                 n_params,
    3964                 :            :                                 instance_and_params,
    3965                 :            :                                 &emission.ihint);
    3966         [ +  + ]:         23 :               if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
    3967         [ +  - ]:          2 :                   emission.state == EMISSION_RUN)
    3968                 :          2 :                 emission.state = EMISSION_STOP;
    3969                 :         23 :               SIGNAL_LOCK ();
    3970                 :         23 :               return_value_altered = TRUE;
    3971                 :            :               
    3972         [ +  + ]:         23 :               tmp = emission.state == EMISSION_RUN ? handler->next : NULL;
    3973                 :            :             }
    3974                 :            :           else
    3975                 :   10319861 :             tmp = handler->next;
    3976                 :            :           
    3977         [ -  + ]:   10319884 :           if (tmp)
    3978                 :          0 :             handler_ref (tmp);
    3979                 :   10319884 :           handler_unref_R (signal_id, instance, handler);
    3980                 :   10319884 :           handler = tmp;
    3981                 :            :         }
    3982         [ -  + ]:   10319884 :       while (handler);
    3983                 :            :       
    3984         [ +  + ]:   10319884 :       if (emission.state == EMISSION_STOP)
    3985                 :          2 :         goto EMIT_CLEANUP;
    3986         [ +  - ]:   10319882 :       else if (emission.state == EMISSION_RESTART)
    3987                 :          0 :         goto EMIT_RESTART;
    3988                 :            :     }
    3989                 :            :   
    3990                 :   16806321 :  EMIT_CLEANUP:
    3991                 :            :   
    3992                 :   16806649 :   emission.ihint.run_type &= ~G_SIGNAL_RUN_LAST;
    3993                 :   16806649 :   emission.ihint.run_type |= G_SIGNAL_RUN_CLEANUP;
    3994                 :            :   
    3995   [ +  +  +  - ]:   16806649 :   if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure)
    3996                 :            :     {
    3997                 :          4 :       gboolean need_unset = FALSE;
    3998                 :            :       
    3999                 :          4 :       emission.state = EMISSION_STOP;
    4000                 :            :       
    4001                 :          4 :       emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
    4002                 :          4 :       SIGNAL_UNLOCK ();
    4003   [ +  -  -  + ]:          4 :       if (node->return_type != G_TYPE_NONE && !accumulator)
    4004                 :            :         {
    4005                 :          0 :           g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
    4006                 :          0 :           need_unset = TRUE;
    4007                 :            :         }
    4008                 :          4 :       g_closure_invoke (class_closure,
    4009         [ +  - ]:          4 :                         node->return_type != G_TYPE_NONE ? &accu : NULL,
    4010                 :            :                         n_params,
    4011                 :            :                         instance_and_params,
    4012                 :            :                         &emission.ihint);
    4013         [ -  + ]:          4 :       if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) &&
    4014         [ #  # ]:          0 :           emission.state == EMISSION_RUN)
    4015                 :          0 :         emission.state = EMISSION_STOP;
    4016         [ -  + ]:          4 :       if (need_unset)
    4017                 :          0 :         g_value_unset (&accu);
    4018                 :          4 :       SIGNAL_LOCK ();
    4019                 :          4 :       return_value_altered = TRUE;
    4020                 :            : 
    4021                 :          4 :       emission.chain_type = G_TYPE_NONE;
    4022                 :            :       
    4023         [ -  + ]:          4 :       if (emission.state == EMISSION_RESTART)
    4024                 :          0 :         goto EMIT_RESTART;
    4025                 :            :     }
    4026                 :            :   
    4027         [ +  + ]:   16806649 :   if (handler_list)
    4028                 :   10320209 :     handler_unref_R (signal_id, instance, handler_list);
    4029                 :            :   
    4030                 :   16806649 :   emission_pop (&emission);
    4031         [ +  + ]:   16806649 :   if (accumulator)
    4032                 :        877 :     g_value_unset (&accu);
    4033                 :            : 
    4034                 :   16806649 :   TRACE(GOBJECT_SIGNAL_EMIT_END(node->signal_id, detail, instance, G_TYPE_FROM_INSTANCE (instance)));
    4035                 :            : 
    4036                 :   16806649 :   return return_value_altered;
    4037                 :            : }
    4038                 :            : 
    4039                 :            : static void
    4040                 :        396 : add_invalid_closure_notify (Handler  *handler,
    4041                 :            :                             gpointer  instance)
    4042                 :            : {
    4043                 :        396 :   g_closure_add_invalidate_notifier (handler->closure, instance, invalid_closure_notify);
    4044                 :        396 :   handler->has_invalid_closure_notify = 1;
    4045                 :        396 : }
    4046                 :            : 
    4047                 :            : static void
    4048                 :     539372 : remove_invalid_closure_notify (Handler  *handler,
    4049                 :            :                                gpointer  instance)
    4050                 :            : {
    4051         [ +  + ]:     539372 :   if (handler->has_invalid_closure_notify)
    4052                 :            :     {
    4053                 :        339 :       g_closure_remove_invalidate_notifier (handler->closure, instance, invalid_closure_notify);
    4054                 :        339 :       handler->has_invalid_closure_notify = 0;
    4055                 :            :     }
    4056                 :     539372 : }
    4057                 :            : 
    4058                 :            : static void
    4059                 :         57 : invalid_closure_notify (gpointer  instance,
    4060                 :            :                         GClosure *closure)
    4061                 :            : {
    4062                 :            :   Handler *handler;
    4063                 :            :   guint signal_id;
    4064                 :            : 
    4065                 :         57 :   SIGNAL_LOCK ();
    4066                 :            : 
    4067                 :         57 :   handler = handler_lookup (instance, 0, closure, &signal_id);
    4068                 :            :   /* See https://bugzilla.gnome.org/show_bug.cgi?id=730296 for discussion about this... */
    4069                 :         57 :   g_assert (handler != NULL);
    4070                 :         57 :   g_assert (handler->closure == closure);
    4071                 :            : 
    4072                 :         57 :   g_hash_table_remove (g_handlers, handler);
    4073                 :         57 :   handler->sequential_number = 0;
    4074                 :         57 :   handler->block_count = 1;
    4075                 :         57 :   handler_unref_R (signal_id, instance, handler);
    4076                 :            : 
    4077                 :         57 :   SIGNAL_UNLOCK ();
    4078                 :         57 : }
    4079                 :            : 
    4080                 :            : static const gchar*
    4081                 :          2 : type_debug_name (GType type)
    4082                 :            : {
    4083         [ +  - ]:          2 :   if (type)
    4084                 :            :     {
    4085                 :          2 :       const char *name = g_type_name (type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
    4086         [ +  - ]:          2 :       return name ? name : "<unknown>";
    4087                 :            :     }
    4088                 :            :   else
    4089                 :          0 :     return "<invalid>";
    4090                 :            : }
    4091                 :            : 
    4092                 :            : /**
    4093                 :            :  * g_signal_accumulator_true_handled:
    4094                 :            :  * @ihint: standard #GSignalAccumulator parameter
    4095                 :            :  * @return_accu: standard #GSignalAccumulator parameter
    4096                 :            :  * @handler_return: standard #GSignalAccumulator parameter
    4097                 :            :  * @dummy: standard #GSignalAccumulator parameter
    4098                 :            :  *
    4099                 :            :  * A predefined #GSignalAccumulator for signals that return a
    4100                 :            :  * boolean values. The behavior that this accumulator gives is
    4101                 :            :  * that a return of %TRUE stops the signal emission: no further
    4102                 :            :  * callbacks will be invoked, while a return of %FALSE allows
    4103                 :            :  * the emission to continue. The idea here is that a %TRUE return
    4104                 :            :  * indicates that the callback handled the signal, and no further
    4105                 :            :  * handling is needed.
    4106                 :            :  *
    4107                 :            :  * Since: 2.4
    4108                 :            :  *
    4109                 :            :  * Returns: standard #GSignalAccumulator result
    4110                 :            :  */
    4111                 :            : gboolean
    4112                 :        853 : g_signal_accumulator_true_handled (GSignalInvocationHint *ihint,
    4113                 :            :                                    GValue                *return_accu,
    4114                 :            :                                    const GValue          *handler_return,
    4115                 :            :                                    gpointer               dummy)
    4116                 :            : {
    4117                 :            :   gboolean continue_emission;
    4118                 :            :   gboolean signal_handled;
    4119                 :            :   
    4120                 :        853 :   signal_handled = g_value_get_boolean (handler_return);
    4121                 :        853 :   g_value_set_boolean (return_accu, signal_handled);
    4122                 :        853 :   continue_emission = !signal_handled;
    4123                 :            :   
    4124                 :        853 :   return continue_emission;
    4125                 :            : }
    4126                 :            : 
    4127                 :            : /**
    4128                 :            :  * g_signal_accumulator_first_wins:
    4129                 :            :  * @ihint: standard #GSignalAccumulator parameter
    4130                 :            :  * @return_accu: standard #GSignalAccumulator parameter
    4131                 :            :  * @handler_return: standard #GSignalAccumulator parameter
    4132                 :            :  * @dummy: standard #GSignalAccumulator parameter
    4133                 :            :  *
    4134                 :            :  * A predefined #GSignalAccumulator for signals intended to be used as a
    4135                 :            :  * hook for application code to provide a particular value.  Usually
    4136                 :            :  * only one such value is desired and multiple handlers for the same
    4137                 :            :  * signal don't make much sense (except for the case of the default
    4138                 :            :  * handler defined in the class structure, in which case you will
    4139                 :            :  * usually want the signal connection to override the class handler).
    4140                 :            :  *
    4141                 :            :  * This accumulator will use the return value from the first signal
    4142                 :            :  * handler that is run as the return value for the signal and not run
    4143                 :            :  * any further handlers (ie: the first handler "wins").
    4144                 :            :  *
    4145                 :            :  * Returns: standard #GSignalAccumulator result
    4146                 :            :  *
    4147                 :            :  * Since: 2.28
    4148                 :            :  **/
    4149                 :            : gboolean
    4150                 :          9 : g_signal_accumulator_first_wins (GSignalInvocationHint *ihint,
    4151                 :            :                                  GValue                *return_accu,
    4152                 :            :                                  const GValue          *handler_return,
    4153                 :            :                                  gpointer               dummy)
    4154                 :            : {
    4155                 :          9 :   g_value_copy (handler_return, return_accu);
    4156                 :          9 :   return FALSE;
    4157                 :            : }
    4158                 :            : 
    4159                 :            : /**
    4160                 :            :  * g_clear_signal_handler:
    4161                 :            :  * @handler_id_ptr: A pointer to a handler ID (of type #gulong) of the handler to be disconnected.
    4162                 :            :  * @instance: (type GObject.Object): The instance to remove the signal handler from.
    4163                 :            :  *   This pointer may be %NULL or invalid, if the handler ID is zero.
    4164                 :            :  *
    4165                 :            :  * Disconnects a handler from @instance so it will not be called during
    4166                 :            :  * any future or currently ongoing emissions of the signal it has been
    4167                 :            :  * connected to. The @handler_id_ptr is then set to zero, which is never a valid handler ID value (see g_signal_connect()).
    4168                 :            :  *
    4169                 :            :  * If the handler ID is 0 then this function does nothing.
    4170                 :            :  *
    4171                 :            :  * There is also a macro version of this function so that the code
    4172                 :            :  * will be inlined.
    4173                 :            :  *
    4174                 :            :  * Since: 2.62
    4175                 :            :  */
    4176                 :            : void
    4177                 :          0 : (g_clear_signal_handler) (gulong   *handler_id_ptr,
    4178                 :            :                           gpointer  instance)
    4179                 :            : {
    4180                 :          0 :   g_return_if_fail (handler_id_ptr != NULL);
    4181                 :            : 
    4182                 :            : #ifndef g_clear_signal_handler
    4183                 :            : #error g_clear_signal_handler() macro is not defined
    4184                 :            : #endif
    4185                 :            : 
    4186                 :          0 :   g_clear_signal_handler (handler_id_ptr, instance);
    4187                 :            : }

Generated by: LCOV version 1.14