LCOV - code coverage report
Current view: top level - glib/gobject - gclosure.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 480 608 78.9 %
Date: 2024-04-23 05:16:05 Functions: 30 33 90.9 %
Branches: 189 298 63.4 %

           Branch data     Line data    Source code
       1                 :            : /* GObject - GLib Type, Object, Parameter and Signal Library
       2                 :            :  * Copyright (C) 2000-2001 Red Hat, Inc.
       3                 :            :  * Copyright (C) 2005 Imendio AB
       4                 :            :  *
       5                 :            :  * SPDX-License-Identifier: LGPL-2.1-or-later
       6                 :            :  *
       7                 :            :  * This library is free software; you can redistribute it and/or
       8                 :            :  * modify it under the terms of the GNU Lesser General Public
       9                 :            :  * License as published by the Free Software Foundation; either
      10                 :            :  * version 2.1 of the License, or (at your option) any later version.
      11                 :            :  *
      12                 :            :  * This library is distributed in the hope that it will be useful,
      13                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :            :  * Lesser General Public License for more details.
      16                 :            :  *
      17                 :            :  * You should have received a copy of the GNU Lesser General
      18                 :            :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19                 :            :  */
      20                 :            : 
      21                 :            : /*
      22                 :            :  * MT safe with regards to reference counting.
      23                 :            :  */
      24                 :            : 
      25                 :            : #include "config.h"
      26                 :            : 
      27                 :            : #include "../glib/gvalgrind.h"
      28                 :            : #include <string.h>
      29                 :            : 
      30                 :            : #include <ffi.h>
      31                 :            : 
      32                 :            : #include "gclosure.h"
      33                 :            : #include "gboxed.h"
      34                 :            : #include "gobject.h"
      35                 :            : #include "genums.h"
      36                 :            : #include "gvalue.h"
      37                 :            : #include "gvaluetypes.h"
      38                 :            : #include "gtype-private.h"
      39                 :            : 
      40                 :            : 
      41                 :            : /**
      42                 :            :  * GClosure:
      43                 :            :  * @in_marshal: Indicates whether the closure is currently being invoked with
      44                 :            :  *   g_closure_invoke()
      45                 :            :  * @is_invalid: Indicates whether the closure has been invalidated by
      46                 :            :  *   g_closure_invalidate()
      47                 :            :  *
      48                 :            :  * A `GClosure` represents a callback supplied by the programmer.
      49                 :            :  *
      50                 :            :  * It will generally comprise a function of some kind and a marshaller
      51                 :            :  * used to call it. It is the responsibility of the marshaller to
      52                 :            :  * convert the arguments for the invocation from #GValues into
      53                 :            :  * a suitable form, perform the callback on the converted arguments,
      54                 :            :  * and transform the return value back into a #GValue.
      55                 :            :  *
      56                 :            :  * In the case of C programs, a closure usually just holds a pointer
      57                 :            :  * to a function and maybe a data argument, and the marshaller
      58                 :            :  * converts between #GValue and native C types. The GObject
      59                 :            :  * library provides the #GCClosure type for this purpose. Bindings for
      60                 :            :  * other languages need marshallers which convert between #GValues
      61                 :            :  * and suitable representations in the runtime of the language in
      62                 :            :  * order to use functions written in that language as callbacks. Use
      63                 :            :  * g_closure_set_marshal() to set the marshaller on such a custom
      64                 :            :  * closure implementation.
      65                 :            :  *
      66                 :            :  * Within GObject, closures play an important role in the
      67                 :            :  * implementation of signals. When a signal is registered, the
      68                 :            :  * @c_marshaller argument to g_signal_new() specifies the default C
      69                 :            :  * marshaller for any closure which is connected to this
      70                 :            :  * signal. GObject provides a number of C marshallers for this
      71                 :            :  * purpose, see the g_cclosure_marshal_*() functions. Additional C
      72                 :            :  * marshallers can be generated with the [glib-genmarshal][glib-genmarshal]
      73                 :            :  * utility.  Closures can be explicitly connected to signals with
      74                 :            :  * g_signal_connect_closure(), but it usually more convenient to let
      75                 :            :  * GObject create a closure automatically by using one of the
      76                 :            :  * g_signal_connect_*() functions which take a callback function/user
      77                 :            :  * data pair.
      78                 :            :  *
      79                 :            :  * Using closures has a number of important advantages over a simple
      80                 :            :  * callback function/data pointer combination:
      81                 :            :  *
      82                 :            :  * - Closures allow the callee to get the types of the callback parameters,
      83                 :            :  *   which means that language bindings don't have to write individual glue
      84                 :            :  *   for each callback type.
      85                 :            :  *
      86                 :            :  * - The reference counting of #GClosure makes it easy to handle reentrancy
      87                 :            :  *   right; if a callback is removed while it is being invoked, the closure
      88                 :            :  *   and its parameters won't be freed until the invocation finishes.
      89                 :            :  *
      90                 :            :  * - g_closure_invalidate() and invalidation notifiers allow callbacks to be
      91                 :            :  *   automatically removed when the objects they point to go away.
      92                 :            :  */
      93                 :            : 
      94                 :            : #define CLOSURE_MAX_REF_COUNT           ((1 << 15) - 1)
      95                 :            : #define CLOSURE_MAX_N_GUARDS            ((1 << 1) - 1)
      96                 :            : #define CLOSURE_MAX_N_FNOTIFIERS        ((1 << 2) - 1)
      97                 :            : #define CLOSURE_MAX_N_INOTIFIERS        ((1 << 8) - 1)
      98                 :            : #define CLOSURE_N_MFUNCS(cl)            (((cl)->n_guards << 1L))
      99                 :            : /* same as G_CLOSURE_N_NOTIFIERS() (keep in sync) */
     100                 :            : #define CLOSURE_N_NOTIFIERS(cl)         (CLOSURE_N_MFUNCS (cl) + \
     101                 :            :                                          (cl)->n_fnotifiers + \
     102                 :            :                                          (cl)->n_inotifiers)
     103                 :            : 
     104                 :            : typedef union {
     105                 :            :   GClosure closure;
     106                 :            :   gint vint;
     107                 :            : } ClosureInt;
     108                 :            : 
     109                 :            : #define CHANGE_FIELD(_closure, _field, _OP, _value, _must_set, _SET_OLD, _SET_NEW)      \
     110                 :            : G_STMT_START {                                                                          \
     111                 :            :   ClosureInt *cunion = (ClosureInt*) _closure;                                          \
     112                 :            :   gint new_int, old_int, success;                                                       \
     113                 :            :   do                                                                                    \
     114                 :            :     {                                                                                   \
     115                 :            :       ClosureInt tmp;                                                                   \
     116                 :            :       tmp.vint = old_int = cunion->vint;                                             \
     117                 :            :       _SET_OLD tmp.closure._field;                                                      \
     118                 :            :       tmp.closure._field _OP _value;                                                    \
     119                 :            :       _SET_NEW tmp.closure._field;                                                      \
     120                 :            :       new_int = tmp.vint;                                                               \
     121                 :            :       success = g_atomic_int_compare_and_exchange (&cunion->vint, old_int, new_int);    \
     122                 :            :     }                                                                                   \
     123                 :            :   while (!success && _must_set);                                                        \
     124                 :            : } G_STMT_END
     125                 :            : 
     126                 :            : #define SWAP(_closure, _field, _value, _oldv)   CHANGE_FIELD (_closure, _field, =, _value, TRUE, *(_oldv) =,     (void) )
     127                 :            : #define SET(_closure, _field, _value)           CHANGE_FIELD (_closure, _field, =, _value, TRUE,     (void),     (void) )
     128                 :            : #define INC(_closure, _field)                   CHANGE_FIELD (_closure, _field, +=,     1, TRUE,     (void),     (void) )
     129                 :            : #define INC_ASSIGN(_closure, _field, _newv)     CHANGE_FIELD (_closure, _field, +=,     1, TRUE,     (void), *(_newv) = )
     130                 :            : #define DEC(_closure, _field)                   CHANGE_FIELD (_closure, _field, -=,     1, TRUE,     (void),     (void) )
     131                 :            : #define DEC_ASSIGN(_closure, _field, _newv)     CHANGE_FIELD (_closure, _field, -=,     1, TRUE,     (void), *(_newv) = )
     132                 :            : 
     133                 :            : #if 0   /* for non-thread-safe closures */
     134                 :            : #define SWAP(cl,f,v,o)     (void) (*(o) = cl->f, cl->f = v)
     135                 :            : #define SET(cl,f,v)        (void) (cl->f = v)
     136                 :            : #define INC(cl,f)          (void) (cl->f += 1)
     137                 :            : #define INC_ASSIGN(cl,f,n) (void) (cl->f += 1, *(n) = cl->f)
     138                 :            : #define DEC(cl,f)          (void) (cl->f -= 1)
     139                 :            : #define DEC_ASSIGN(cl,f,n) (void) (cl->f -= 1, *(n) = cl->f)
     140                 :            : #endif
     141                 :            : 
     142                 :            : enum {
     143                 :            :   FNOTIFY,
     144                 :            :   INOTIFY,
     145                 :            :   PRE_NOTIFY,
     146                 :            :   POST_NOTIFY
     147                 :            : };
     148                 :            : 
     149                 :            : 
     150                 :            : /* --- functions --- */
     151                 :            : /**
     152                 :            :  * g_closure_new_simple:
     153                 :            :  * @sizeof_closure: the size of the structure to allocate, must be at least
     154                 :            :  *                  `sizeof (GClosure)`
     155                 :            :  * @data: data to store in the @data field of the newly allocated #GClosure
     156                 :            :  *
     157                 :            :  * Allocates a struct of the given size and initializes the initial
     158                 :            :  * part as a #GClosure.
     159                 :            :  *
     160                 :            :  * This function is mainly useful when implementing new types of closures:
     161                 :            :  *
     162                 :            :  * |[<!-- language="C" --> 
     163                 :            :  * typedef struct _MyClosure MyClosure;
     164                 :            :  * struct _MyClosure
     165                 :            :  * {
     166                 :            :  *   GClosure closure;
     167                 :            :  *   // extra data goes here
     168                 :            :  * };
     169                 :            :  *
     170                 :            :  * static void
     171                 :            :  * my_closure_finalize (gpointer  notify_data,
     172                 :            :  *                      GClosure *closure)
     173                 :            :  * {
     174                 :            :  *   MyClosure *my_closure = (MyClosure *)closure;
     175                 :            :  *
     176                 :            :  *   // free extra data here
     177                 :            :  * }
     178                 :            :  *
     179                 :            :  * MyClosure *my_closure_new (gpointer data)
     180                 :            :  * {
     181                 :            :  *   GClosure *closure;
     182                 :            :  *   MyClosure *my_closure;
     183                 :            :  *
     184                 :            :  *   closure = g_closure_new_simple (sizeof (MyClosure), data);
     185                 :            :  *   my_closure = (MyClosure *) closure;
     186                 :            :  *
     187                 :            :  *   // initialize extra data here
     188                 :            :  *
     189                 :            :  *   g_closure_add_finalize_notifier (closure, notify_data,
     190                 :            :  *                                    my_closure_finalize);
     191                 :            :  *   return my_closure;
     192                 :            :  * }
     193                 :            :  * ]|
     194                 :            :  *
     195                 :            :  * Returns: (transfer floating): a floating reference to a new #GClosure
     196                 :            :  */
     197                 :            : GClosure*
     198                 :     579169 : g_closure_new_simple (guint           sizeof_closure,
     199                 :            :                       gpointer        data)
     200                 :            : {
     201                 :            :   GClosure *closure;
     202                 :            :   gint private_size;
     203                 :            :   gchar *allocated;
     204                 :            : 
     205                 :     579169 :   g_return_val_if_fail (sizeof_closure >= sizeof (GClosure), NULL);
     206                 :            : 
     207                 :     579169 :   private_size = sizeof (GRealClosure) - sizeof (GClosure);
     208                 :            : 
     209                 :            : #ifdef ENABLE_VALGRIND
     210                 :            :   /* See comments in gtype.c about what's going on here... */
     211         [ -  + ]:     579169 :   if (RUNNING_ON_VALGRIND)
     212                 :            :     {
     213                 :          0 :       private_size += sizeof (gpointer);
     214                 :            : 
     215                 :          0 :       allocated = g_malloc0 (private_size + sizeof_closure + sizeof (gpointer));
     216                 :            : 
     217                 :          0 :       *(gpointer *) (allocated + private_size + sizeof_closure) = allocated + sizeof (gpointer);
     218                 :            : 
     219                 :          0 :       VALGRIND_MALLOCLIKE_BLOCK (allocated + private_size, sizeof_closure + sizeof (gpointer), 0, TRUE);
     220                 :          0 :       VALGRIND_MALLOCLIKE_BLOCK (allocated + sizeof (gpointer), private_size - sizeof (gpointer), 0, TRUE);
     221                 :            :     }
     222                 :            :   else
     223                 :            : #endif
     224                 :     579169 :     allocated = g_malloc0 (private_size + sizeof_closure);
     225                 :            : 
     226                 :     579169 :   closure = (GClosure *) (allocated + private_size);
     227                 :            : 
     228         [ -  + ]:     579169 :   SET (closure, ref_count, 1);
     229         [ -  + ]:     579169 :   SET (closure, floating, TRUE);
     230                 :     579169 :   closure->data = data;
     231                 :            : 
     232                 :     579169 :   return closure;
     233                 :            : }
     234                 :            : 
     235                 :            : static inline void
     236                 :   38071078 : closure_invoke_notifiers (GClosure *closure,
     237                 :            :                           guint     notify_type)
     238                 :            : {
     239                 :            :   /* notifier layout:
     240                 :            :    *     n_guards    n_guards     n_fnotif.  n_inotifiers
     241                 :            :    * ->[[pre_guards][post_guards][fnotifiers][inotifiers]]
     242                 :            :    *
     243                 :            :    * CLOSURE_N_MFUNCS(cl)    = n_guards + n_guards;
     244                 :            :    * CLOSURE_N_NOTIFIERS(cl) = CLOSURE_N_MFUNCS(cl) + n_fnotifiers + n_inotifiers
     245                 :            :    *
     246                 :            :    * constrains/catches:
     247                 :            :    * - closure->notifiers may be reloacted during callback
     248                 :            :    * - closure->n_fnotifiers and closure->n_inotifiers may change during callback
     249                 :            :    * - i.e. callbacks can be removed/added during invocation
     250                 :            :    * - must prepare for callback removal during FNOTIFY and INOTIFY (done via ->marshal= & ->data=)
     251                 :            :    * - must distinguish (->marshal= & ->data=) for INOTIFY vs. FNOTIFY (via ->in_inotify)
     252                 :            :    * + closure->n_guards is const during PRE_NOTIFY & POST_NOTIFY
     253                 :            :    * + none of the callbacks can cause recursion
     254                 :            :    * + closure->n_inotifiers is const 0 during FNOTIFY
     255                 :            :    */
     256   [ +  +  +  +  :   38071078 :   switch (notify_type)
                      # ]
     257                 :            :     {
     258                 :            :       GClosureNotifyData *ndata;
     259                 :            :       guint i, offs;
     260                 :     576737 :     case FNOTIFY:
     261         [ +  + ]:     578750 :       while (closure->n_fnotifiers)
     262                 :            :         {
     263                 :            :           guint n;
     264         [ -  + ]:       2014 :           DEC_ASSIGN (closure, n_fnotifiers, &n);
     265                 :            : 
     266                 :       2014 :           ndata = closure->notifiers + CLOSURE_N_MFUNCS (closure) + n;
     267                 :       2014 :           closure->marshal = (GClosureMarshal) ndata->notify;
     268                 :       2014 :           closure->data = ndata->data;
     269                 :       2014 :           ndata->notify (ndata->data, closure);
     270                 :            :         }
     271                 :     576736 :       closure->marshal = NULL;
     272                 :     576736 :       closure->data = NULL;
     273                 :     576736 :       break;
     274                 :     576800 :     case INOTIFY:
     275         [ -  + ]:     576800 :       SET (closure, in_inotify, TRUE);
     276         [ +  + ]:     614455 :       while (closure->n_inotifiers)
     277                 :            :         {
     278                 :            :           guint n;
     279         [ -  + ]:      37655 :           DEC_ASSIGN (closure, n_inotifiers, &n);
     280                 :            : 
     281                 :      37655 :           ndata = closure->notifiers + CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers + n;
     282                 :      37655 :           closure->marshal = (GClosureMarshal) ndata->notify;
     283                 :      37655 :           closure->data = ndata->data;
     284                 :      37655 :           ndata->notify (ndata->data, closure);
     285                 :            :         }
     286                 :     576800 :       closure->marshal = NULL;
     287                 :     576800 :       closure->data = NULL;
     288         [ -  + ]:     576800 :       SET (closure, in_inotify, FALSE);
     289                 :     576800 :       break;
     290                 :   18460547 :     case PRE_NOTIFY:
     291                 :   18460547 :       i = closure->n_guards;
     292                 :   18460547 :       offs = 0;
     293         [ +  + ]:   18460529 :       while (i--)
     294                 :            :         {
     295                 :         39 :           ndata = closure->notifiers + offs + i;
     296                 :         39 :           ndata->notify (ndata->data, closure);
     297                 :            :         }
     298                 :   18460490 :       break;
     299                 :   18460338 :     case POST_NOTIFY:
     300                 :   18460338 :       i = closure->n_guards;
     301                 :   18460338 :       offs = i;
     302         [ +  + ]:   18460333 :       while (i--)
     303                 :            :         {
     304                 :         39 :           ndata = closure->notifiers + offs + i;
     305                 :         39 :           ndata->notify (ndata->data, closure);
     306                 :            :         }
     307                 :   18460294 :       break;
     308                 :            :     }
     309                 :   38070976 : }
     310                 :            : 
     311                 :            : static void
     312                 :       1723 : g_closure_set_meta_va_marshal (GClosure       *closure,
     313                 :            :                                GVaClosureMarshal va_meta_marshal)
     314                 :            : {
     315                 :            :   GRealClosure *real_closure;
     316                 :            : 
     317                 :       1723 :   g_return_if_fail (closure != NULL);
     318                 :       1723 :   g_return_if_fail (va_meta_marshal != NULL);
     319                 :       1723 :   g_return_if_fail (closure->is_invalid == FALSE);
     320                 :       1723 :   g_return_if_fail (closure->in_marshal == FALSE);
     321                 :            : 
     322                 :       1723 :   real_closure = G_REAL_CLOSURE (closure);
     323                 :            : 
     324                 :       1723 :   g_return_if_fail (real_closure->meta_marshal != NULL);
     325                 :            : 
     326                 :       1723 :   real_closure->va_meta_marshal = va_meta_marshal;
     327                 :            : }
     328                 :            : 
     329                 :            : /**
     330                 :            :  * g_closure_set_meta_marshal: (skip)
     331                 :            :  * @closure: a #GClosure
     332                 :            :  * @marshal_data: (closure meta_marshal): context-dependent data to pass
     333                 :            :  *  to @meta_marshal
     334                 :            :  * @meta_marshal: a #GClosureMarshal function
     335                 :            :  *
     336                 :            :  * Sets the meta marshaller of @closure.
     337                 :            :  *
     338                 :            :  * A meta marshaller wraps the @closure's marshal and modifies the way
     339                 :            :  * it is called in some fashion. The most common use of this facility
     340                 :            :  * is for C callbacks.
     341                 :            :  *
     342                 :            :  * The same marshallers (generated by [glib-genmarshal][glib-genmarshal]),
     343                 :            :  * are used everywhere, but the way that we get the callback function
     344                 :            :  * differs. In most cases we want to use the @closure's callback, but in
     345                 :            :  * other cases we want to use some different technique to retrieve the
     346                 :            :  * callback function.
     347                 :            :  *
     348                 :            :  * For example, class closures for signals (see
     349                 :            :  * g_signal_type_cclosure_new()) retrieve the callback function from a
     350                 :            :  * fixed offset in the class structure.  The meta marshaller retrieves
     351                 :            :  * the right callback and passes it to the marshaller as the
     352                 :            :  * @marshal_data argument.
     353                 :            :  */
     354                 :            : void
     355                 :      39375 : g_closure_set_meta_marshal (GClosure       *closure,
     356                 :            :                             gpointer        marshal_data,
     357                 :            :                             GClosureMarshal meta_marshal)
     358                 :            : {
     359                 :            :   GRealClosure *real_closure;
     360                 :            : 
     361                 :      39375 :   g_return_if_fail (closure != NULL);
     362                 :      39375 :   g_return_if_fail (meta_marshal != NULL);
     363                 :      39375 :   g_return_if_fail (closure->is_invalid == FALSE);
     364                 :      39375 :   g_return_if_fail (closure->in_marshal == FALSE);
     365                 :            : 
     366                 :      39375 :   real_closure = G_REAL_CLOSURE (closure);
     367                 :            : 
     368                 :      39375 :   g_return_if_fail (real_closure->meta_marshal == NULL);
     369                 :            : 
     370                 :      39375 :   real_closure->meta_marshal = meta_marshal;
     371                 :      39375 :   real_closure->meta_marshal_data = marshal_data;
     372                 :            : }
     373                 :            : 
     374                 :            : /**
     375                 :            :  * g_closure_add_marshal_guards: (skip)
     376                 :            :  * @closure: a #GClosure
     377                 :            :  * @pre_marshal_data: (closure pre_marshal_notify): data to pass
     378                 :            :  *  to @pre_marshal_notify
     379                 :            :  * @pre_marshal_notify: a function to call before the closure callback
     380                 :            :  * @post_marshal_data: (closure post_marshal_notify): data to pass
     381                 :            :  *  to @post_marshal_notify
     382                 :            :  * @post_marshal_notify: a function to call after the closure callback
     383                 :            :  *
     384                 :            :  * Adds a pair of notifiers which get invoked before and after the
     385                 :            :  * closure callback, respectively.
     386                 :            :  *
     387                 :            :  * This is typically used to protect the extra arguments for the
     388                 :            :  * duration of the callback. See g_object_watch_closure() for an
     389                 :            :  * example of marshal guards.
     390                 :            :  */
     391                 :            : void
     392                 :         60 : g_closure_add_marshal_guards (GClosure      *closure,
     393                 :            :                               gpointer       pre_marshal_data,
     394                 :            :                               GClosureNotify pre_marshal_notify,
     395                 :            :                               gpointer       post_marshal_data,
     396                 :            :                               GClosureNotify post_marshal_notify)
     397                 :            : {
     398                 :            :   guint i;
     399                 :            : 
     400                 :         60 :   g_return_if_fail (closure != NULL);
     401                 :         60 :   g_return_if_fail (pre_marshal_notify != NULL);
     402                 :         60 :   g_return_if_fail (post_marshal_notify != NULL);
     403                 :         60 :   g_return_if_fail (closure->is_invalid == FALSE);
     404                 :         60 :   g_return_if_fail (closure->in_marshal == FALSE);
     405                 :         60 :   g_return_if_fail (closure->n_guards < CLOSURE_MAX_N_GUARDS);
     406                 :            : 
     407                 :         60 :   closure->notifiers = g_renew (GClosureNotifyData, closure->notifiers, CLOSURE_N_NOTIFIERS (closure) + 2);
     408         [ +  - ]:         60 :   if (closure->n_inotifiers)
     409                 :         60 :     closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
     410                 :         60 :                         closure->n_fnotifiers +
     411                 :         60 :                         closure->n_inotifiers + 1)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
     412                 :         60 :                                                                           closure->n_fnotifiers + 0)];
     413         [ -  + ]:         60 :   if (closure->n_inotifiers > 1)
     414                 :          0 :     closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
     415                 :          0 :                         closure->n_fnotifiers +
     416                 :          0 :                         closure->n_inotifiers)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
     417                 :          0 :                                                                       closure->n_fnotifiers + 1)];
     418         [ -  + ]:         60 :   if (closure->n_fnotifiers)
     419                 :          0 :     closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
     420                 :          0 :                         closure->n_fnotifiers + 1)] = closure->notifiers[CLOSURE_N_MFUNCS (closure) + 0];
     421         [ -  + ]:         60 :   if (closure->n_fnotifiers > 1)
     422                 :          0 :     closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
     423                 :          0 :                         closure->n_fnotifiers)] = closure->notifiers[CLOSURE_N_MFUNCS (closure) + 1];
     424         [ -  + ]:         60 :   if (closure->n_guards)
     425                 :          0 :     closure->notifiers[(closure->n_guards +
     426                 :          0 :                         closure->n_guards + 1)] = closure->notifiers[closure->n_guards];
     427                 :         60 :   i = closure->n_guards;
     428                 :         60 :   closure->notifiers[i].data = pre_marshal_data;
     429                 :         60 :   closure->notifiers[i].notify = pre_marshal_notify;
     430                 :         60 :   closure->notifiers[i + 1].data = post_marshal_data;
     431                 :         60 :   closure->notifiers[i + 1].notify = post_marshal_notify;
     432         [ -  + ]:         60 :   INC (closure, n_guards);
     433                 :            : }
     434                 :            : 
     435                 :            : /**
     436                 :            :  * g_closure_add_finalize_notifier: (skip)
     437                 :            :  * @closure: a #GClosure
     438                 :            :  * @notify_data: (closure notify_func): data to pass to @notify_func
     439                 :            :  * @notify_func: the callback function to register
     440                 :            :  *
     441                 :            :  * Registers a finalization notifier which will be called when the
     442                 :            :  * reference count of @closure goes down to 0.
     443                 :            :  *
     444                 :            :  * Multiple finalization notifiers on a single closure are invoked in
     445                 :            :  * unspecified order. If a single call to g_closure_unref() results in
     446                 :            :  * the closure being both invalidated and finalized, then the invalidate
     447                 :            :  * notifiers will be run before the finalize notifiers.
     448                 :            :  */
     449                 :            : void
     450                 :       2212 : g_closure_add_finalize_notifier (GClosure      *closure,
     451                 :            :                                  gpointer       notify_data,
     452                 :            :                                  GClosureNotify notify_func)
     453                 :            : {
     454                 :            :   guint i;
     455                 :            : 
     456                 :       2212 :   g_return_if_fail (closure != NULL);
     457                 :       2212 :   g_return_if_fail (notify_func != NULL);
     458                 :       2212 :   g_return_if_fail (closure->n_fnotifiers < CLOSURE_MAX_N_FNOTIFIERS);
     459                 :            : 
     460                 :       2212 :   closure->notifiers = g_renew (GClosureNotifyData, closure->notifiers, CLOSURE_N_NOTIFIERS (closure) + 1);
     461         [ -  + ]:       2212 :   if (closure->n_inotifiers)
     462                 :          0 :     closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
     463                 :          0 :                         closure->n_fnotifiers +
     464                 :          0 :                         closure->n_inotifiers)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
     465                 :          0 :                                                                       closure->n_fnotifiers + 0)];
     466                 :       2212 :   i = CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers;
     467                 :       2212 :   closure->notifiers[i].data = notify_data;
     468                 :       2212 :   closure->notifiers[i].notify = notify_func;
     469         [ -  + ]:       2212 :   INC (closure, n_fnotifiers);
     470                 :            : }
     471                 :            : 
     472                 :            : /**
     473                 :            :  * g_closure_add_invalidate_notifier: (skip)
     474                 :            :  * @closure: a #GClosure
     475                 :            :  * @notify_data: (closure notify_func): data to pass to @notify_func
     476                 :            :  * @notify_func: the callback function to register
     477                 :            :  *
     478                 :            :  * Registers an invalidation notifier which will be called when the
     479                 :            :  * @closure is invalidated with g_closure_invalidate().
     480                 :            :  *
     481                 :            :  * Invalidation notifiers are invoked before finalization notifiers,
     482                 :            :  * in an unspecified order.
     483                 :            :  */
     484                 :            : void
     485                 :      38114 : g_closure_add_invalidate_notifier (GClosure      *closure,
     486                 :            :                                    gpointer       notify_data,
     487                 :            :                                    GClosureNotify notify_func)
     488                 :            : {
     489                 :            :   guint i;
     490                 :            : 
     491                 :      38114 :   g_return_if_fail (closure != NULL);
     492                 :      38114 :   g_return_if_fail (notify_func != NULL);
     493                 :      38114 :   g_return_if_fail (closure->is_invalid == FALSE);
     494                 :      38114 :   g_return_if_fail (closure->n_inotifiers < CLOSURE_MAX_N_INOTIFIERS);
     495                 :            : 
     496                 :      38114 :   closure->notifiers = g_renew (GClosureNotifyData, closure->notifiers, CLOSURE_N_NOTIFIERS (closure) + 1);
     497                 :      38114 :   i = CLOSURE_N_MFUNCS (closure) + closure->n_fnotifiers + closure->n_inotifiers;
     498                 :      38114 :   closure->notifiers[i].data = notify_data;
     499                 :      38114 :   closure->notifiers[i].notify = notify_func;
     500         [ -  + ]:      38114 :   INC (closure, n_inotifiers);
     501                 :            : }
     502                 :            : 
     503                 :            : static inline gboolean
     504                 :        396 : closure_try_remove_inotify (GClosure       *closure,
     505                 :            :                             gpointer       notify_data,
     506                 :            :                             GClosureNotify notify_func)
     507                 :            : {
     508                 :            :   GClosureNotifyData *ndata, *nlast;
     509                 :            : 
     510                 :        396 :   nlast = closure->notifiers + CLOSURE_N_NOTIFIERS (closure) - 1;
     511         [ +  - ]:        401 :   for (ndata = nlast + 1 - closure->n_inotifiers; ndata <= nlast; ndata++)
     512   [ +  +  +  - ]:        401 :     if (ndata->notify == notify_func && ndata->data == notify_data)
     513                 :            :       {
     514         [ -  + ]:        396 :         DEC (closure, n_inotifiers);
     515         [ +  + ]:        396 :         if (ndata < nlast)
     516                 :         58 :           *ndata = *nlast;
     517                 :            : 
     518                 :        396 :         return TRUE;
     519                 :            :       }
     520                 :          0 :   return FALSE;
     521                 :            : }
     522                 :            : 
     523                 :            : static inline gboolean
     524                 :          0 : closure_try_remove_fnotify (GClosure       *closure,
     525                 :            :                             gpointer       notify_data,
     526                 :            :                             GClosureNotify notify_func)
     527                 :            : {
     528                 :            :   GClosureNotifyData *ndata, *nlast;
     529                 :            : 
     530                 :          0 :   nlast = closure->notifiers + CLOSURE_N_NOTIFIERS (closure) - closure->n_inotifiers - 1;
     531         [ #  # ]:          0 :   for (ndata = nlast + 1 - closure->n_fnotifiers; ndata <= nlast; ndata++)
     532   [ #  #  #  # ]:          0 :     if (ndata->notify == notify_func && ndata->data == notify_data)
     533                 :            :       {
     534         [ #  # ]:          0 :         DEC (closure, n_fnotifiers);
     535         [ #  # ]:          0 :         if (ndata < nlast)
     536                 :          0 :           *ndata = *nlast;
     537         [ #  # ]:          0 :         if (closure->n_inotifiers)
     538                 :          0 :           closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
     539                 :          0 :                               closure->n_fnotifiers)] = closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
     540                 :          0 :                                                                             closure->n_fnotifiers +
     541                 :          0 :                                                                             closure->n_inotifiers)];
     542                 :          0 :         return TRUE;
     543                 :            :       }
     544                 :          0 :   return FALSE;
     545                 :            : }
     546                 :            : 
     547                 :            : /**
     548                 :            :  * g_closure_ref:
     549                 :            :  * @closure: #GClosure to increment the reference count on
     550                 :            :  *
     551                 :            :  * Increments the reference count on a closure to force it staying
     552                 :            :  * alive while the caller holds a pointer to it.
     553                 :            :  *
     554                 :            :  * Returns: (transfer none): The @closure passed in, for convenience
     555                 :            :  */
     556                 :            : GClosure*
     557                 :   59840484 : g_closure_ref (GClosure *closure)
     558                 :            : {
     559                 :            :   guint new_ref_count;
     560                 :   59840484 :   g_return_val_if_fail (closure != NULL, NULL);
     561                 :   59840484 :   g_return_val_if_fail (closure->ref_count > 0, NULL);
     562                 :   59840484 :   g_return_val_if_fail (closure->ref_count < CLOSURE_MAX_REF_COUNT, NULL);
     563                 :            : 
     564         [ +  + ]:   67374090 :   INC_ASSIGN (closure, ref_count, &new_ref_count);
     565                 :   59840484 :   g_return_val_if_fail (new_ref_count > 1, NULL);
     566                 :            : 
     567                 :   59840484 :   return closure;
     568                 :            : }
     569                 :            : 
     570                 :            : /**
     571                 :            :  * g_closure_invalidate:
     572                 :            :  * @closure: #GClosure to invalidate
     573                 :            :  *
     574                 :            :  * Sets a flag on the closure to indicate that its calling
     575                 :            :  * environment has become invalid, and thus causes any future
     576                 :            :  * invocations of g_closure_invoke() on this @closure to be
     577                 :            :  * ignored.
     578                 :            :  *
     579                 :            :  * Also, invalidation notifiers installed on the closure will
     580                 :            :  * be called at this point. Note that unless you are holding a
     581                 :            :  * reference to the closure yourself, the invalidation notifiers may
     582                 :            :  * unref the closure and cause it to be destroyed, so if you need to
     583                 :            :  * access the closure after calling g_closure_invalidate(), make sure
     584                 :            :  * that you've previously called g_closure_ref().
     585                 :            :  *
     586                 :            :  * Note that g_closure_invalidate() will also be called when the
     587                 :            :  * reference count of a closure drops to zero (unless it has already
     588                 :            :  * been invalidated before).
     589                 :            :  */
     590                 :            : void
     591                 :     576876 : g_closure_invalidate (GClosure *closure)
     592                 :            : {
     593                 :     576876 :   g_return_if_fail (closure != NULL);
     594                 :            : 
     595         [ +  + ]:     576876 :   if (!closure->is_invalid)
     596                 :            :     {
     597                 :            :       gboolean was_invalid;
     598                 :     576795 :       g_closure_ref (closure);           /* preserve floating flag */
     599         [ -  + ]:     576997 :       SWAP (closure, is_invalid, TRUE, &was_invalid);
     600                 :            :       /* invalidate only once */
     601         [ +  + ]:     576997 :       if (!was_invalid)
     602                 :     576892 :         closure_invoke_notifiers (closure, INOTIFY);
     603                 :     577067 :       g_closure_unref (closure);
     604                 :            :     }
     605                 :            : }
     606                 :            : 
     607                 :            : /**
     608                 :            :  * g_closure_unref:
     609                 :            :  * @closure: #GClosure to decrement the reference count on
     610                 :            :  *
     611                 :            :  * Decrements the reference count of a closure after it was previously
     612                 :            :  * incremented by the same caller.
     613                 :            :  *
     614                 :            :  * If no other callers are using the closure, then the closure will be
     615                 :            :  * destroyed and freed.
     616                 :            :  */
     617                 :            : void
     618                 :   60283533 : g_closure_unref (GClosure *closure)
     619                 :            : {
     620                 :            :   guint new_ref_count;
     621                 :            : 
     622                 :   60283533 :   g_return_if_fail (closure != NULL);
     623                 :   60283533 :   g_return_if_fail (closure->ref_count > 0);
     624                 :            : 
     625         [ +  + ]:   60283533 :   if (closure->ref_count == 1)       /* last unref, invalidate first */
     626                 :     576815 :     g_closure_invalidate (closure);
     627                 :            : 
     628         [ +  + ]:   68043002 :   DEC_ASSIGN (closure, ref_count, &new_ref_count);
     629                 :            : 
     630         [ +  + ]:   60439617 :   if (new_ref_count == 0)
     631                 :            :     {
     632                 :     576784 :       closure_invoke_notifiers (closure, FNOTIFY);
     633                 :     576730 :       g_free (closure->notifiers);
     634                 :            : 
     635                 :            : #ifdef ENABLE_VALGRIND
     636                 :            :       /* See comments in gtype.c about what's going on here... */
     637         [ -  + ]:     576878 :       if (RUNNING_ON_VALGRIND)
     638                 :            :         {
     639                 :            :           gchar *allocated;
     640                 :            : 
     641                 :          0 :           allocated = (gchar *) G_REAL_CLOSURE (closure);
     642                 :          0 :           allocated -= sizeof (gpointer);
     643                 :            : 
     644                 :          0 :           g_free (allocated);
     645                 :            : 
     646                 :          0 :           VALGRIND_FREELIKE_BLOCK (allocated + sizeof (gpointer), 0);
     647                 :          0 :           VALGRIND_FREELIKE_BLOCK (closure, 0);
     648                 :            :         }
     649                 :            :       else
     650                 :            : #endif
     651                 :     576845 :         g_free (G_REAL_CLOSURE (closure));
     652                 :            :     }
     653                 :            : }
     654                 :            : 
     655                 :            : /**
     656                 :            :  * g_closure_sink:
     657                 :            :  * @closure: #GClosure to decrement the initial reference count on, if it's
     658                 :            :  *           still being held
     659                 :            :  *
     660                 :            :  * Takes over the initial ownership of a closure.
     661                 :            :  *
     662                 :            :  * Each closure is initially created in a "floating" state, which means
     663                 :            :  * that the initial reference count is not owned by any caller.
     664                 :            :  *
     665                 :            :  * This function checks to see if the object is still floating, and if so,
     666                 :            :  * unsets the floating state and decreases the reference count. If the
     667                 :            :  * closure is not floating, g_closure_sink() does nothing.
     668                 :            :  *
     669                 :            :  * The reason for the existence of the floating state is to prevent
     670                 :            :  * cumbersome code sequences like:
     671                 :            :  *
     672                 :            :  * |[<!-- language="C" --> 
     673                 :            :  * closure = g_cclosure_new (cb_func, cb_data);
     674                 :            :  * g_source_set_closure (source, closure);
     675                 :            :  * g_closure_unref (closure); // GObject doesn't really need this
     676                 :            :  * ]|
     677                 :            :  *
     678                 :            :  * Because g_source_set_closure() (and similar functions) take ownership of the
     679                 :            :  * initial reference count, if it is unowned, we instead can write:
     680                 :            :  *
     681                 :            :  * |[<!-- language="C" --> 
     682                 :            :  * g_source_set_closure (source, g_cclosure_new (cb_func, cb_data));
     683                 :            :  * ]|
     684                 :            :  *
     685                 :            :  * Generally, this function is used together with g_closure_ref(). An example
     686                 :            :  * of storing a closure for later notification looks like:
     687                 :            :  *
     688                 :            :  * |[<!-- language="C" --> 
     689                 :            :  * static GClosure *notify_closure = NULL;
     690                 :            :  * void
     691                 :            :  * foo_notify_set_closure (GClosure *closure)
     692                 :            :  * {
     693                 :            :  *   if (notify_closure)
     694                 :            :  *     g_closure_unref (notify_closure);
     695                 :            :  *   notify_closure = closure;
     696                 :            :  *   if (notify_closure)
     697                 :            :  *     {
     698                 :            :  *       g_closure_ref (notify_closure);
     699                 :            :  *       g_closure_sink (notify_closure);
     700                 :            :  *     }
     701                 :            :  * }
     702                 :            :  * ]|
     703                 :            :  *
     704                 :            :  * Because g_closure_sink() may decrement the reference count of a closure
     705                 :            :  * (if it hasn't been called on @closure yet) just like g_closure_unref(),
     706                 :            :  * g_closure_ref() should be called prior to this function.
     707                 :            :  */
     708                 :            : void
     709                 :     901609 : g_closure_sink (GClosure *closure)
     710                 :            : {
     711                 :     901609 :   g_return_if_fail (closure != NULL);
     712                 :     901609 :   g_return_if_fail (closure->ref_count > 0);
     713                 :            : 
     714                 :            :   /* floating is basically a kludge to avoid creating closures
     715                 :            :    * with a ref_count of 0. so the initial ref_count a closure has
     716                 :            :    * is unowned. with invoking g_closure_sink() code may
     717                 :            :    * indicate that it takes over that initial ref_count.
     718                 :            :    */
     719         [ +  + ]:     901609 :   if (closure->floating)
     720                 :            :     {
     721                 :            :       gboolean was_floating;
     722         [ -  + ]:     579166 :       SWAP (closure, floating, FALSE, &was_floating);
     723                 :            :       /* unref floating flag only once */
     724         [ +  - ]:     579166 :       if (was_floating)
     725                 :     579166 :         g_closure_unref (closure);
     726                 :            :     }
     727                 :            : }
     728                 :            : 
     729                 :            : /**
     730                 :            :  * g_closure_remove_invalidate_notifier: (skip)
     731                 :            :  * @closure: a #GClosure
     732                 :            :  * @notify_data: data which was passed to g_closure_add_invalidate_notifier()
     733                 :            :  *               when registering @notify_func
     734                 :            :  * @notify_func: the callback function to remove
     735                 :            :  *
     736                 :            :  * Removes an invalidation notifier.
     737                 :            :  *
     738                 :            :  * Notice that notifiers are automatically removed after they are run.
     739                 :            :  */
     740                 :            : void
     741                 :        396 : g_closure_remove_invalidate_notifier (GClosure      *closure,
     742                 :            :                                       gpointer       notify_data,
     743                 :            :                                       GClosureNotify notify_func)
     744                 :            : {
     745                 :        396 :   g_return_if_fail (closure != NULL);
     746                 :        396 :   g_return_if_fail (notify_func != NULL);
     747                 :            : 
     748   [ -  +  -  - ]:        396 :   if (closure->is_invalid && closure->in_inotify && /* account removal of notify_func() while it's called */
     749         [ #  # ]:          0 :       ((gpointer) closure->marshal) == ((gpointer) notify_func) &&
     750         [ #  # ]:          0 :       closure->data == notify_data)
     751                 :          0 :     closure->marshal = NULL;
     752         [ -  + ]:        396 :   else if (!closure_try_remove_inotify (closure, notify_data, notify_func))
     753                 :          0 :     g_critical (G_STRLOC ": unable to remove uninstalled invalidation notifier: %p (%p)",
     754                 :            :                 notify_func, notify_data);
     755                 :            : }
     756                 :            : 
     757                 :            : /**
     758                 :            :  * g_closure_remove_finalize_notifier: (skip)
     759                 :            :  * @closure: a #GClosure
     760                 :            :  * @notify_data: data which was passed to g_closure_add_finalize_notifier()
     761                 :            :  *  when registering @notify_func
     762                 :            :  * @notify_func: the callback function to remove
     763                 :            :  *
     764                 :            :  * Removes a finalization notifier.
     765                 :            :  *
     766                 :            :  * Notice that notifiers are automatically removed after they are run.
     767                 :            :  */
     768                 :            : void
     769                 :          0 : g_closure_remove_finalize_notifier (GClosure      *closure,
     770                 :            :                                     gpointer       notify_data,
     771                 :            :                                     GClosureNotify notify_func)
     772                 :            : {
     773                 :          0 :   g_return_if_fail (closure != NULL);
     774                 :          0 :   g_return_if_fail (notify_func != NULL);
     775                 :            : 
     776   [ #  #  #  # ]:          0 :   if (closure->is_invalid && !closure->in_inotify && /* account removal of notify_func() while it's called */
     777         [ #  # ]:          0 :       ((gpointer) closure->marshal) == ((gpointer) notify_func) &&
     778         [ #  # ]:          0 :       closure->data == notify_data)
     779                 :          0 :     closure->marshal = NULL;
     780         [ #  # ]:          0 :   else if (!closure_try_remove_fnotify (closure, notify_data, notify_func))
     781                 :          0 :     g_critical (G_STRLOC ": unable to remove uninstalled finalization notifier: %p (%p)",
     782                 :            :                 notify_func, notify_data);
     783                 :            : }
     784                 :            : 
     785                 :            : /**
     786                 :            :  * g_closure_invoke:
     787                 :            :  * @closure: a #GClosure
     788                 :            :  * @return_value: (optional) (out): a #GValue to store the return
     789                 :            :  *                value. May be %NULL if the callback of @closure
     790                 :            :  *                doesn't return a value.
     791                 :            :  * @n_param_values: the length of the @param_values array
     792                 :            :  * @param_values: (array length=n_param_values): an array of
     793                 :            :  *                #GValues holding the arguments on which to
     794                 :            :  *                invoke the callback of @closure
     795                 :            :  * @invocation_hint: (nullable): a context-dependent invocation hint
     796                 :            :  *
     797                 :            :  * Invokes the closure, i.e. executes the callback represented by the @closure.
     798                 :            :  */
     799                 :            : void
     800                 :   27178675 : g_closure_invoke (GClosure       *closure,
     801                 :            :                   GValue /*out*/ *return_value,
     802                 :            :                   guint           n_param_values,
     803                 :            :                   const GValue   *param_values,
     804                 :            :                   gpointer        invocation_hint)
     805                 :            : {
     806                 :            :   GRealClosure *real_closure;
     807                 :            : 
     808                 :   27178675 :   g_return_if_fail (closure != NULL);
     809                 :            : 
     810                 :   27178675 :   real_closure = G_REAL_CLOSURE (closure);
     811                 :            : 
     812                 :   27178675 :   g_closure_ref (closure);      /* preserve floating flag */
     813         [ +  + ]:   27182328 :   if (!closure->is_invalid)
     814                 :            :     {
     815                 :            :       GClosureMarshal marshal;
     816                 :            :       gpointer marshal_data;
     817                 :   27181436 :       gboolean in_marshal = closure->in_marshal;
     818                 :            : 
     819                 :   27181436 :       g_return_if_fail (closure->marshal || real_closure->meta_marshal);
     820                 :            : 
     821         [ +  + ]:   28117751 :       SET (closure, in_marshal, TRUE);
     822         [ +  + ]:   27181436 :       if (real_closure->meta_marshal)
     823                 :            :         {
     824                 :   16840684 :           marshal_data = real_closure->meta_marshal_data;
     825                 :   16840684 :           marshal = real_closure->meta_marshal;
     826                 :            :         }
     827                 :            :       else
     828                 :            :         {
     829                 :   10340752 :           marshal_data = NULL;
     830                 :   10340752 :           marshal = closure->marshal;
     831                 :            :         }
     832         [ +  + ]:   27181436 :       if (!in_marshal)
     833                 :   18219375 :         closure_invoke_notifiers (closure, PRE_NOTIFY);
     834                 :   27181398 :       marshal (closure,
     835                 :            :                return_value,
     836                 :            :                n_param_values, param_values,
     837                 :            :                invocation_hint,
     838                 :            :                marshal_data);
     839         [ +  + ]:   27177771 :       if (!in_marshal)
     840                 :   18219301 :         closure_invoke_notifiers (closure, POST_NOTIFY);
     841         [ +  + ]:   28281646 :       SET (closure, in_marshal, in_marshal);
     842                 :            :     }
     843                 :   27178127 :   g_closure_unref (closure);
     844                 :            : }
     845                 :            : 
     846                 :            : gboolean
     847                 :   17013042 : _g_closure_supports_invoke_va (GClosure       *closure)
     848                 :            : {
     849                 :            :   GRealClosure *real_closure;
     850                 :            : 
     851                 :   17013042 :   g_return_val_if_fail (closure != NULL, FALSE);
     852                 :            : 
     853                 :   17013042 :   real_closure = G_REAL_CLOSURE (closure);
     854                 :            : 
     855                 :            :   return
     856         [ +  + ]:   21941483 :     real_closure->va_marshal != NULL &&
     857         [ +  + ]:    4928441 :     (real_closure->meta_marshal == NULL ||
     858         [ +  - ]:     141858 :      real_closure->va_meta_marshal != NULL);
     859                 :            : }
     860                 :            : 
     861                 :            : void
     862                 :     241137 : _g_closure_invoke_va (GClosure       *closure,
     863                 :            :                       GValue /*out*/ *return_value,
     864                 :            :                       gpointer        instance,
     865                 :            :                       va_list         args,
     866                 :            :                       int             n_params,
     867                 :            :                       GType          *param_types)
     868                 :            : {
     869                 :            :   GRealClosure *real_closure;
     870                 :            : 
     871                 :     241137 :   g_return_if_fail (closure != NULL);
     872                 :            : 
     873                 :     241137 :   real_closure = G_REAL_CLOSURE (closure);
     874                 :            : 
     875                 :     241137 :   g_closure_ref (closure);      /* preserve floating flag */
     876         [ +  - ]:     241137 :   if (!closure->is_invalid)
     877                 :            :     {
     878                 :            :       GVaClosureMarshal marshal;
     879                 :            :       gpointer marshal_data;
     880                 :     241137 :       gboolean in_marshal = closure->in_marshal;
     881                 :            : 
     882                 :     241137 :       g_return_if_fail (closure->marshal || real_closure->meta_marshal);
     883                 :            : 
     884         [ -  + ]:     241137 :       SET (closure, in_marshal, TRUE);
     885         [ +  + ]:     241137 :       if (real_closure->va_meta_marshal)
     886                 :            :         {
     887                 :      71434 :           marshal_data = real_closure->meta_marshal_data;
     888                 :      71434 :           marshal = real_closure->va_meta_marshal;
     889                 :            :         }
     890                 :            :       else
     891                 :            :         {
     892                 :     169703 :           marshal_data = NULL;
     893                 :     169703 :           marshal = real_closure->va_marshal;
     894                 :            :         }
     895         [ +  + ]:     241137 :       if (!in_marshal)
     896                 :     241136 :         closure_invoke_notifiers (closure, PRE_NOTIFY);
     897                 :     241137 :       marshal (closure,
     898                 :            :                return_value,
     899                 :            :                instance, args,
     900                 :            :                marshal_data,
     901                 :            :                n_params, param_types);
     902         [ +  + ]:     241135 :       if (!in_marshal)
     903                 :     241134 :         closure_invoke_notifiers (closure, POST_NOTIFY);
     904         [ -  + ]:     241135 :       SET (closure, in_marshal, in_marshal);
     905                 :            :     }
     906                 :     241135 :   g_closure_unref (closure);
     907                 :            : }
     908                 :            : 
     909                 :            : 
     910                 :            : /**
     911                 :            :  * g_closure_set_marshal: (skip)
     912                 :            :  * @closure: a #GClosure
     913                 :            :  * @marshal: a #GClosureMarshal function
     914                 :            :  *
     915                 :            :  * Sets the marshaller of @closure.
     916                 :            :  *
     917                 :            :  * The `marshal_data` of @marshal provides a way for a meta marshaller to
     918                 :            :  * provide additional information to the marshaller.
     919                 :            :  *
     920                 :            :  * For GObject's C predefined marshallers (the `g_cclosure_marshal_*()`
     921                 :            :  * functions), what it provides is a callback function to use instead of
     922                 :            :  * @closure->callback.
     923                 :            :  *
     924                 :            :  * See also: g_closure_set_meta_marshal()
     925                 :            :  */
     926                 :            : void
     927                 :     579161 : g_closure_set_marshal (GClosure       *closure,
     928                 :            :                        GClosureMarshal marshal)
     929                 :            : {
     930                 :     579161 :   g_return_if_fail (closure != NULL);
     931                 :     579161 :   g_return_if_fail (marshal != NULL);
     932                 :            : 
     933   [ -  +  -  - ]:     579161 :   if (closure->marshal && closure->marshal != marshal)
     934                 :          0 :     g_critical ("attempt to override closure->marshal (%p) with new marshal (%p)",
     935                 :            :                 closure->marshal, marshal);
     936                 :            :   else
     937                 :     579161 :     closure->marshal = marshal;
     938                 :            : }
     939                 :            : 
     940                 :            : void
     941                 :     541255 : _g_closure_set_va_marshal (GClosure       *closure,
     942                 :            :                            GVaClosureMarshal marshal)
     943                 :            : {
     944                 :            :   GRealClosure *real_closure;
     945                 :            : 
     946                 :     541255 :   g_return_if_fail (closure != NULL);
     947                 :     541255 :   g_return_if_fail (marshal != NULL);
     948                 :            : 
     949                 :     541255 :   real_closure = G_REAL_CLOSURE (closure);
     950                 :            : 
     951   [ -  +  -  - ]:     541255 :   if (real_closure->va_marshal && real_closure->va_marshal != marshal)
     952                 :          0 :     g_critical ("attempt to override closure->va_marshal (%p) with new marshal (%p)",
     953                 :            :                 real_closure->va_marshal, marshal);
     954                 :            :   else
     955                 :     541255 :     real_closure->va_marshal = marshal;
     956                 :            : }
     957                 :            : 
     958                 :            : /**
     959                 :            :  * g_cclosure_new: (skip)
     960                 :            :  * @callback_func: the function to invoke
     961                 :            :  * @user_data: (closure callback_func): user data to pass to @callback_func
     962                 :            :  * @destroy_data: destroy notify to be called when @user_data is no longer used
     963                 :            :  *
     964                 :            :  * Creates a new closure which invokes @callback_func with @user_data as
     965                 :            :  * the last parameter.
     966                 :            :  *
     967                 :            :  * @destroy_data will be called as a finalize notifier on the #GClosure.
     968                 :            :  *
     969                 :            :  * Returns: (transfer floating): a floating reference to a new #GCClosure
     970                 :            :  */
     971                 :            : GClosure*
     972                 :     539574 : g_cclosure_new (GCallback      callback_func,
     973                 :            :                 gpointer       user_data,
     974                 :            :                 GClosureNotify destroy_data)
     975                 :            : {
     976                 :            :   GClosure *closure;
     977                 :            :   
     978                 :     539574 :   g_return_val_if_fail (callback_func != NULL, NULL);
     979                 :            :   
     980                 :     539574 :   closure = g_closure_new_simple (sizeof (GCClosure), user_data);
     981         [ +  + ]:     539574 :   if (destroy_data)
     982                 :       2212 :     g_closure_add_finalize_notifier (closure, user_data, destroy_data);
     983                 :     539574 :   ((GCClosure*) closure)->callback = (gpointer) callback_func;
     984                 :            :   
     985                 :     539574 :   return closure;
     986                 :            : }
     987                 :            : 
     988                 :            : /**
     989                 :            :  * g_cclosure_new_swap: (skip)
     990                 :            :  * @callback_func: the function to invoke
     991                 :            :  * @user_data: (closure callback_func): user data to pass to @callback_func
     992                 :            :  * @destroy_data: destroy notify to be called when @user_data is no longer used
     993                 :            :  *
     994                 :            :  * Creates a new closure which invokes @callback_func with @user_data as
     995                 :            :  * the first parameter.
     996                 :            :  *
     997                 :            :  * @destroy_data will be called as a finalize notifier on the #GClosure.
     998                 :            :  *
     999                 :            :  * Returns: (transfer floating): a floating reference to a new #GCClosure
    1000                 :            :  */
    1001                 :            : GClosure*
    1002                 :        220 : g_cclosure_new_swap (GCallback      callback_func,
    1003                 :            :                      gpointer       user_data,
    1004                 :            :                      GClosureNotify destroy_data)
    1005                 :            : {
    1006                 :            :   GClosure *closure;
    1007                 :            :   
    1008                 :        220 :   g_return_val_if_fail (callback_func != NULL, NULL);
    1009                 :            :   
    1010                 :        220 :   closure = g_closure_new_simple (sizeof (GCClosure), user_data);
    1011         [ -  + ]:        220 :   if (destroy_data)
    1012                 :          0 :     g_closure_add_finalize_notifier (closure, user_data, destroy_data);
    1013                 :        220 :   ((GCClosure*) closure)->callback = (gpointer) callback_func;
    1014         [ -  + ]:        220 :   SET (closure, derivative_flag, TRUE);
    1015                 :            :   
    1016                 :        220 :   return closure;
    1017                 :            : }
    1018                 :            : 
    1019                 :            : static void
    1020                 :   16723065 : g_type_class_meta_marshal (GClosure       *closure,
    1021                 :            :                            GValue /*out*/ *return_value,
    1022                 :            :                            guint           n_param_values,
    1023                 :            :                            const GValue   *param_values,
    1024                 :            :                            gpointer        invocation_hint,
    1025                 :            :                            gpointer        marshal_data)
    1026                 :            : {
    1027                 :            :   GTypeClass *class;
    1028                 :            :   gpointer callback;
    1029                 :            :   /* GType itype = (GType) closure->data; */
    1030                 :   16723065 :   guint offset = GPOINTER_TO_UINT (marshal_data);
    1031                 :            :   
    1032                 :   16723065 :   class = G_TYPE_INSTANCE_GET_CLASS (g_value_peek_pointer (param_values + 0), itype, GTypeClass);
    1033                 :   16720284 :   callback = G_STRUCT_MEMBER (gpointer, class, offset);
    1034         [ +  + ]:   16720284 :   if (callback)
    1035                 :    9275422 :     closure->marshal (closure,
    1036                 :            :                       return_value,
    1037                 :            :                       n_param_values, param_values,
    1038                 :            :                       invocation_hint,
    1039                 :            :                       callback);
    1040                 :   16721143 : }
    1041                 :            : 
    1042                 :            : static void
    1043                 :      71434 : g_type_class_meta_marshalv (GClosure *closure,
    1044                 :            :                             GValue   *return_value,
    1045                 :            :                             gpointer  instance,
    1046                 :            :                             va_list   args,
    1047                 :            :                             gpointer  marshal_data,
    1048                 :            :                             int       n_params,
    1049                 :            :                             GType    *param_types)
    1050                 :            : {
    1051                 :            :   GRealClosure *real_closure;
    1052                 :            :   GTypeClass *class;
    1053                 :            :   gpointer callback;
    1054                 :            :   /* GType itype = (GType) closure->data; */
    1055                 :      71434 :   guint offset = GPOINTER_TO_UINT (marshal_data);
    1056                 :            : 
    1057                 :      71434 :   real_closure = G_REAL_CLOSURE (closure);
    1058                 :            : 
    1059                 :      71434 :   class = G_TYPE_INSTANCE_GET_CLASS (instance, itype, GTypeClass);
    1060                 :      71434 :   callback = G_STRUCT_MEMBER (gpointer, class, offset);
    1061         [ +  - ]:      71434 :   if (callback)
    1062                 :      71434 :     real_closure->va_marshal (closure,
    1063                 :            :                               return_value,
    1064                 :            :                               instance, args,
    1065                 :            :                               callback,
    1066                 :            :                               n_params,
    1067                 :            :                               param_types);
    1068                 :      71434 : }
    1069                 :            : 
    1070                 :            : static void
    1071                 :     100255 : g_type_iface_meta_marshal (GClosure       *closure,
    1072                 :            :                            GValue /*out*/ *return_value,
    1073                 :            :                            guint           n_param_values,
    1074                 :            :                            const GValue   *param_values,
    1075                 :            :                            gpointer        invocation_hint,
    1076                 :            :                            gpointer        marshal_data)
    1077                 :            : {
    1078                 :            :   GTypeClass *class;
    1079                 :            :   gpointer callback;
    1080                 :     100255 :   GType itype = (GType) closure->data;
    1081                 :     100255 :   guint offset = GPOINTER_TO_UINT (marshal_data);
    1082                 :            :   
    1083                 :     100255 :   class = G_TYPE_INSTANCE_GET_INTERFACE (g_value_peek_pointer (param_values + 0), itype, GTypeClass);
    1084                 :     100139 :   callback = G_STRUCT_MEMBER (gpointer, class, offset);
    1085         [ +  + ]:     100139 :   if (callback)
    1086                 :         78 :     closure->marshal (closure,
    1087                 :            :                       return_value,
    1088                 :            :                       n_param_values, param_values,
    1089                 :            :                       invocation_hint,
    1090                 :            :                       callback);
    1091                 :     100139 : }
    1092                 :            : 
    1093                 :            : gboolean
    1094                 :   36444283 : _g_closure_is_void (GClosure *closure,
    1095                 :            :                     gpointer instance)
    1096                 :            : {
    1097                 :            :   GRealClosure *real_closure;
    1098                 :            :   GTypeClass *class;
    1099                 :            :   gpointer callback;
    1100                 :            :   GType itype;
    1101                 :            :   guint offset;
    1102                 :            : 
    1103         [ -  + ]:   36444283 :   if (closure->is_invalid)
    1104                 :          0 :     return TRUE;
    1105                 :            : 
    1106                 :   36444283 :   real_closure = G_REAL_CLOSURE (closure);
    1107                 :            : 
    1108         [ -  + ]:   36444283 :   if (real_closure->meta_marshal == g_type_iface_meta_marshal)
    1109                 :            :     {
    1110                 :          0 :       itype = (GType) closure->data;
    1111                 :          0 :       offset = GPOINTER_TO_UINT (real_closure->meta_marshal_data);
    1112                 :            : 
    1113                 :          0 :       class = G_TYPE_INSTANCE_GET_INTERFACE (instance, itype, GTypeClass);
    1114                 :          0 :       callback = G_STRUCT_MEMBER (gpointer, class, offset);
    1115                 :          0 :       return callback == NULL;
    1116                 :            :     }
    1117         [ +  + ]:   36444283 :   else if (real_closure->meta_marshal == g_type_class_meta_marshal)
    1118                 :            :     {
    1119                 :   36444282 :       offset = GPOINTER_TO_UINT (real_closure->meta_marshal_data);
    1120                 :            : 
    1121                 :   36444282 :       class = G_TYPE_INSTANCE_GET_CLASS (instance, itype, GTypeClass);
    1122                 :   36444282 :       callback = G_STRUCT_MEMBER (gpointer, class, offset);
    1123                 :   36444282 :       return callback == NULL;
    1124                 :            :     }
    1125                 :            : 
    1126                 :          1 :   return FALSE;
    1127                 :            : }
    1128                 :            : 
    1129                 :            : static void
    1130                 :          0 : g_type_iface_meta_marshalv (GClosure *closure,
    1131                 :            :                             GValue   *return_value,
    1132                 :            :                             gpointer  instance,
    1133                 :            :                             va_list   args,
    1134                 :            :                             gpointer  marshal_data,
    1135                 :            :                             int       n_params,
    1136                 :            :                             GType    *param_types)
    1137                 :            : {
    1138                 :            :   GRealClosure *real_closure;
    1139                 :            :   GTypeClass *class;
    1140                 :            :   gpointer callback;
    1141                 :          0 :   GType itype = (GType) closure->data;
    1142                 :          0 :   guint offset = GPOINTER_TO_UINT (marshal_data);
    1143                 :            : 
    1144                 :          0 :   real_closure = G_REAL_CLOSURE (closure);
    1145                 :            : 
    1146                 :          0 :   class = G_TYPE_INSTANCE_GET_INTERFACE (instance, itype, GTypeClass);
    1147                 :          0 :   callback = G_STRUCT_MEMBER (gpointer, class, offset);
    1148         [ #  # ]:          0 :   if (callback)
    1149                 :          0 :     real_closure->va_marshal (closure,
    1150                 :            :                               return_value,
    1151                 :            :                               instance, args,
    1152                 :            :                               callback,
    1153                 :            :                               n_params,
    1154                 :            :                               param_types);
    1155                 :          0 : }
    1156                 :            : 
    1157                 :            : /**
    1158                 :            :  * g_signal_type_cclosure_new:
    1159                 :            :  * @itype: the #GType identifier of an interface or classed type
    1160                 :            :  * @struct_offset: the offset of the member function of @itype's class
    1161                 :            :  *  structure which is to be invoked by the new closure
    1162                 :            :  *
    1163                 :            :  * Creates a new closure which invokes the function found at the offset
    1164                 :            :  * @struct_offset in the class structure of the interface or classed type
    1165                 :            :  * identified by @itype.
    1166                 :            :  *
    1167                 :            :  * Returns: (transfer floating): a floating reference to a new #GCClosure
    1168                 :            :  */
    1169                 :            : GClosure*
    1170                 :       1723 : g_signal_type_cclosure_new (GType    itype,
    1171                 :            :                             guint    struct_offset)
    1172                 :            : {
    1173                 :            :   GClosure *closure;
    1174                 :            :   
    1175                 :       1723 :   g_return_val_if_fail (G_TYPE_IS_CLASSED (itype) || G_TYPE_IS_INTERFACE (itype), NULL);
    1176                 :       1723 :   g_return_val_if_fail (struct_offset >= sizeof (GTypeClass), NULL);
    1177                 :            :   
    1178                 :       1723 :   closure = g_closure_new_simple (sizeof (GClosure), GTYPE_TO_POINTER (itype));
    1179         [ +  + ]:       1723 :   if (G_TYPE_IS_INTERFACE (itype))
    1180                 :            :     {
    1181                 :        206 :       g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (struct_offset), g_type_iface_meta_marshal);
    1182                 :        206 :       g_closure_set_meta_va_marshal (closure, g_type_iface_meta_marshalv);
    1183                 :            :     }
    1184                 :            :   else
    1185                 :            :     {
    1186                 :       1517 :       g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (struct_offset), g_type_class_meta_marshal);
    1187                 :       1517 :       g_closure_set_meta_va_marshal (closure, g_type_class_meta_marshalv);
    1188                 :            :     }
    1189                 :       1723 :   return closure;
    1190                 :            : }
    1191                 :            : 
    1192                 :            : #include <ffi.h>
    1193                 :            : static ffi_type *
    1194                 :    9569589 : value_to_ffi_type (const GValue *gvalue,
    1195                 :            :                    gpointer *value,
    1196                 :            :                    gint *enum_tmpval,
    1197                 :            :                    gboolean *tmpval_used)
    1198                 :            : {
    1199                 :    9569589 :   ffi_type *rettype = NULL;
    1200                 :    9569589 :   GType type = g_type_fundamental (G_VALUE_TYPE (gvalue));
    1201                 :    9570995 :   g_assert (type != G_TYPE_INVALID);
    1202                 :            : 
    1203         [ +  + ]:    9588982 :   if (enum_tmpval)
    1204                 :            :     {
    1205                 :    9572476 :       g_assert (tmpval_used != NULL);
    1206                 :    9572476 :       *tmpval_used = FALSE;
    1207                 :            :     }
    1208                 :            : 
    1209   [ +  +  +  +  :    9588982 :   switch (type)
          +  +  +  +  +  
                +  +  - ]
    1210                 :            :     {
    1211                 :    3198036 :     case G_TYPE_BOOLEAN:
    1212                 :            :     case G_TYPE_CHAR:
    1213                 :            :     case G_TYPE_INT:
    1214                 :    3198036 :       rettype = &ffi_type_sint;
    1215                 :    3198036 :       *value = (gpointer)&(gvalue->data[0].v_int);
    1216                 :    3198036 :       break;
    1217                 :          9 :     case G_TYPE_ENUM:
    1218                 :            :       /* enums are stored in v_long even though they are integers, which makes
    1219                 :            :        * marshalling through libffi somewhat complicated.  They need to be
    1220                 :            :        * marshalled as signed ints, but we need to use a temporary int sized
    1221                 :            :        * value to pass to libffi otherwise it'll pull the wrong value on
    1222                 :            :        * BE machines with 32-bit integers when treating v_long as 32-bit int.
    1223                 :            :        */
    1224                 :          9 :       g_assert (enum_tmpval != NULL);
    1225                 :          9 :       rettype = &ffi_type_sint;
    1226                 :          9 :       *enum_tmpval = g_value_get_enum (gvalue);
    1227                 :          9 :       *value = enum_tmpval;
    1228                 :          9 :       *tmpval_used = TRUE;
    1229                 :          9 :       break;
    1230                 :          7 :     case G_TYPE_FLAGS:
    1231                 :          7 :       g_assert (enum_tmpval != NULL);
    1232                 :          7 :       rettype = &ffi_type_uint;
    1233                 :          7 :       *enum_tmpval = g_value_get_flags (gvalue);
    1234                 :          7 :       *value = enum_tmpval;
    1235                 :          7 :       *tmpval_used = TRUE;
    1236                 :          7 :       break;
    1237                 :         12 :     case G_TYPE_UCHAR:
    1238                 :            :     case G_TYPE_UINT:
    1239                 :         12 :       rettype = &ffi_type_uint;
    1240                 :         12 :       *value = (gpointer)&(gvalue->data[0].v_uint);
    1241                 :         12 :       break;
    1242                 :    6390883 :     case G_TYPE_STRING:
    1243                 :            :     case G_TYPE_OBJECT:
    1244                 :            :     case G_TYPE_BOXED:
    1245                 :            :     case G_TYPE_PARAM:
    1246                 :            :     case G_TYPE_POINTER:
    1247                 :            :     case G_TYPE_INTERFACE:
    1248                 :            :     case G_TYPE_VARIANT:
    1249                 :    6390883 :       rettype = &ffi_type_pointer;
    1250                 :    6390883 :       *value = (gpointer)&(gvalue->data[0].v_pointer);
    1251                 :    6390883 :       break;
    1252                 :          5 :     case G_TYPE_FLOAT:
    1253                 :          5 :       rettype = &ffi_type_float;
    1254                 :          5 :       *value = (gpointer)&(gvalue->data[0].v_float);
    1255                 :          5 :       break;
    1256                 :          5 :     case G_TYPE_DOUBLE:
    1257                 :          5 :       rettype = &ffi_type_double;
    1258                 :          5 :       *value = (gpointer)&(gvalue->data[0].v_double);
    1259                 :          5 :       break;
    1260                 :          5 :     case G_TYPE_LONG:
    1261                 :          5 :       rettype = &ffi_type_slong;
    1262                 :          5 :       *value = (gpointer)&(gvalue->data[0].v_long);
    1263                 :          5 :       break;
    1264                 :          6 :     case G_TYPE_ULONG:
    1265                 :          6 :       rettype = &ffi_type_ulong;
    1266                 :          6 :       *value = (gpointer)&(gvalue->data[0].v_ulong);
    1267                 :          6 :       break;
    1268                 :          9 :     case G_TYPE_INT64:
    1269                 :          9 :       rettype = &ffi_type_sint64;
    1270                 :          9 :       *value = (gpointer)&(gvalue->data[0].v_int64);
    1271                 :          9 :       break;
    1272                 :          5 :     case G_TYPE_UINT64:
    1273                 :          5 :       rettype = &ffi_type_uint64;
    1274                 :          5 :       *value = (gpointer)&(gvalue->data[0].v_uint64);
    1275                 :          5 :       break;
    1276                 :          0 :     default:
    1277                 :          0 :       rettype = &ffi_type_pointer;
    1278                 :          0 :       *value = NULL;
    1279                 :          0 :       g_critical ("value_to_ffi_type: Unsupported fundamental type: %s", g_type_name (type));
    1280                 :          0 :       break;
    1281                 :            :     }
    1282                 :    9571562 :   return rettype;
    1283                 :            : }
    1284                 :            : 
    1285                 :            : static void
    1286                 :    3210043 : value_from_ffi_type (GValue *gvalue, gpointer *value)
    1287                 :            : {
    1288                 :    3210043 :   ffi_arg *int_val = (ffi_arg*) value;
    1289                 :            :   GType type;
    1290                 :            : 
    1291                 :    3210043 :   type = G_VALUE_TYPE (gvalue);
    1292                 :            : 
    1293                 :    3210044 : restart:
    1294   [ +  -  -  +  :    3210044 :   switch (g_type_fundamental (type))
          +  -  -  +  -  
          -  -  -  -  -  
          +  -  -  +  +  
                   +  + ]
    1295                 :            :     {
    1296                 :          7 :     case G_TYPE_INT:
    1297                 :          7 :       g_value_set_int (gvalue, (gint) *int_val);
    1298                 :          7 :       break;
    1299                 :          0 :     case G_TYPE_FLOAT:
    1300                 :          0 :       g_value_set_float (gvalue, *(gfloat*)value);
    1301                 :          0 :       break;
    1302                 :          0 :     case G_TYPE_DOUBLE:
    1303                 :          0 :       g_value_set_double (gvalue, *(gdouble*)value);
    1304                 :          0 :       break;
    1305                 :         25 :     case G_TYPE_BOOLEAN:
    1306                 :         25 :       g_value_set_boolean (gvalue, (gboolean) *int_val);
    1307                 :         25 :       break;
    1308                 :    3208339 :     case G_TYPE_STRING:
    1309                 :    3208339 :       g_value_take_string (gvalue, *(gchar**)value);
    1310                 :    3208283 :       break;
    1311                 :          0 :     case G_TYPE_CHAR:
    1312                 :          0 :       g_value_set_schar (gvalue, (gint8) *int_val);
    1313                 :          0 :       break;
    1314                 :          0 :     case G_TYPE_UCHAR:
    1315                 :          0 :       g_value_set_uchar (gvalue, (guchar) *int_val);
    1316                 :          0 :       break;
    1317                 :          2 :     case G_TYPE_UINT:
    1318                 :          2 :       g_value_set_uint (gvalue, (guint) *int_val);
    1319                 :          2 :       break;
    1320                 :          0 :     case G_TYPE_POINTER:
    1321                 :          0 :       g_value_set_pointer (gvalue, *(gpointer*)value);
    1322                 :          0 :       break;
    1323                 :          0 :     case G_TYPE_LONG:
    1324                 :          0 :       g_value_set_long (gvalue, (glong) *int_val);
    1325                 :          0 :       break;
    1326                 :          0 :     case G_TYPE_ULONG:
    1327                 :          0 :       g_value_set_ulong (gvalue, (gulong) *int_val);
    1328                 :          0 :       break;
    1329                 :          0 :     case G_TYPE_INT64:
    1330                 :          0 :       g_value_set_int64 (gvalue, (gint64) *int_val);
    1331                 :          0 :       break;
    1332                 :          0 :     case G_TYPE_UINT64:
    1333                 :          0 :       g_value_set_uint64 (gvalue, (guint64) *int_val);
    1334                 :          0 :       break;
    1335                 :          0 :     case G_TYPE_BOXED:
    1336                 :          0 :       g_value_take_boxed (gvalue, *(gpointer*)value);
    1337                 :          0 :       break;
    1338                 :          4 :     case G_TYPE_ENUM:
    1339                 :          4 :       g_value_set_enum (gvalue, (gint) *int_val);
    1340                 :          4 :       break;
    1341                 :          0 :     case G_TYPE_FLAGS:
    1342                 :          0 :       g_value_set_flags (gvalue, (guint) *int_val);
    1343                 :          0 :       break;
    1344                 :          0 :     case G_TYPE_PARAM:
    1345                 :          0 :       g_value_take_param (gvalue, *(gpointer*)value);
    1346                 :          0 :       break;
    1347                 :          1 :     case G_TYPE_OBJECT:
    1348                 :          1 :       g_value_take_object (gvalue, *(gpointer*)value);
    1349                 :          1 :       break;
    1350                 :          7 :     case G_TYPE_VARIANT:
    1351                 :          7 :       g_value_take_variant (gvalue, *(gpointer*)value);
    1352                 :          7 :       break;
    1353                 :          1 :     case G_TYPE_INTERFACE:
    1354                 :          1 :       type = g_type_interface_instantiatable_prerequisite (type);
    1355         [ +  - ]:          1 :       if (type)
    1356                 :          1 :         goto restart;
    1357                 :            :       G_GNUC_FALLTHROUGH;
    1358                 :            :     default:
    1359                 :        355 :       g_critical ("value_from_ffi_type: Unsupported fundamental type %s for type %s",
    1360                 :            :                   g_type_name (g_type_fundamental (G_VALUE_TYPE (gvalue))),
    1361                 :            :                   g_type_name (G_VALUE_TYPE (gvalue)));
    1362                 :            :     }
    1363                 :    3208329 : }
    1364                 :            : 
    1365                 :            : typedef union {
    1366                 :            :   gpointer _gpointer;
    1367                 :            :   float _float;
    1368                 :            :   double _double;
    1369                 :            :   gint _gint;
    1370                 :            :   guint _guint;
    1371                 :            :   glong _glong;
    1372                 :            :   gulong _gulong;
    1373                 :            :   gint64 _gint64;
    1374                 :            :   guint64 _guint64;
    1375                 :            : } va_arg_storage;
    1376                 :            : 
    1377                 :            : static ffi_type *
    1378                 :         31 : va_to_ffi_type (GType gtype,
    1379                 :            :                 va_list *va,
    1380                 :            :                 va_arg_storage *storage)
    1381                 :            : {
    1382                 :         31 :   ffi_type *rettype = NULL;
    1383                 :         31 :   GType type = g_type_fundamental (gtype);
    1384                 :         31 :   g_assert (type != G_TYPE_INVALID);
    1385                 :            : 
    1386   [ +  +  +  +  :         31 :   switch (type)
          +  +  +  +  +  
                      - ]
    1387                 :            :     {
    1388                 :         11 :     case G_TYPE_BOOLEAN:
    1389                 :            :     case G_TYPE_CHAR:
    1390                 :            :     case G_TYPE_INT:
    1391                 :            :     case G_TYPE_ENUM:
    1392                 :         11 :       rettype = &ffi_type_sint;
    1393                 :         11 :       storage->_gint = va_arg (*va, gint);
    1394                 :         11 :       break;
    1395                 :          4 :     case G_TYPE_UCHAR:
    1396                 :            :     case G_TYPE_UINT:
    1397                 :            :     case G_TYPE_FLAGS:
    1398                 :          4 :       rettype = &ffi_type_uint;
    1399                 :          4 :       storage->_guint = va_arg (*va, guint);
    1400                 :          4 :       break;
    1401                 :          7 :     case G_TYPE_STRING:
    1402                 :            :     case G_TYPE_OBJECT:
    1403                 :            :     case G_TYPE_BOXED:
    1404                 :            :     case G_TYPE_PARAM:
    1405                 :            :     case G_TYPE_POINTER:
    1406                 :            :     case G_TYPE_INTERFACE:
    1407                 :            :     case G_TYPE_VARIANT:
    1408                 :          7 :       rettype = &ffi_type_pointer;
    1409                 :          7 :       storage->_gpointer = va_arg (*va, gpointer);
    1410                 :          7 :       break;
    1411                 :          2 :     case G_TYPE_FLOAT:
    1412                 :            :       /* Float args are passed as doubles in varargs */
    1413                 :          2 :       rettype = &ffi_type_float;
    1414                 :          2 :       storage->_float = (float)va_arg (*va, double);
    1415                 :          2 :       break;
    1416                 :          2 :     case G_TYPE_DOUBLE:
    1417                 :          2 :       rettype = &ffi_type_double;
    1418                 :          2 :       storage->_double = va_arg (*va, double);
    1419                 :          2 :       break;
    1420                 :          2 :     case G_TYPE_LONG:
    1421                 :          2 :       rettype = &ffi_type_slong;
    1422                 :          2 :       storage->_glong = va_arg (*va, glong);
    1423                 :          2 :       break;
    1424                 :          1 :     case G_TYPE_ULONG:
    1425                 :          1 :       rettype = &ffi_type_ulong;
    1426                 :          1 :       storage->_gulong = va_arg (*va, gulong);
    1427                 :          1 :       break;
    1428                 :          1 :     case G_TYPE_INT64:
    1429                 :          1 :       rettype = &ffi_type_sint64;
    1430                 :          1 :       storage->_gint64 = va_arg (*va, gint64);
    1431                 :          1 :       break;
    1432                 :          1 :     case G_TYPE_UINT64:
    1433                 :          1 :       rettype = &ffi_type_uint64;
    1434                 :          1 :       storage->_guint64 = va_arg (*va, guint64);
    1435                 :          1 :       break;
    1436                 :          0 :     default:
    1437                 :          0 :       rettype = &ffi_type_pointer;
    1438                 :          0 :       storage->_guint64  = 0;
    1439                 :          0 :       g_critical ("va_to_ffi_type: Unsupported fundamental type: %s", g_type_name (type));
    1440                 :          0 :       break;
    1441                 :            :     }
    1442                 :         31 :   return rettype;
    1443                 :            : }
    1444                 :            : 
    1445                 :            : /**
    1446                 :            :  * g_cclosure_marshal_generic:
    1447                 :            :  * @closure: A #GClosure.
    1448                 :            :  * @return_gvalue: A #GValue to store the return value. May be %NULL
    1449                 :            :  *   if the callback of closure doesn't return a value.
    1450                 :            :  * @n_param_values: The length of the @param_values array.
    1451                 :            :  * @param_values: An array of #GValues holding the arguments
    1452                 :            :  *   on which to invoke the callback of closure.
    1453                 :            :  * @invocation_hint: The invocation hint given as the last argument to
    1454                 :            :  *   g_closure_invoke().
    1455                 :            :  * @marshal_data: Additional data specified when registering the
    1456                 :            :  *   marshaller, see g_closure_set_marshal() and
    1457                 :            :  *   g_closure_set_meta_marshal()
    1458                 :            :  *
    1459                 :            :  * A generic marshaller function implemented via
    1460                 :            :  * [libffi](http://sourceware.org/libffi/).
    1461                 :            :  *
    1462                 :            :  * Normally this function is not passed explicitly to g_signal_new(),
    1463                 :            :  * but used automatically by GLib when specifying a %NULL marshaller.
    1464                 :            :  *
    1465                 :            :  * Since: 2.30
    1466                 :            :  */
    1467                 :            : void
    1468                 :    3205882 : g_cclosure_marshal_generic (GClosure     *closure,
    1469                 :            :                             GValue       *return_gvalue,
    1470                 :            :                             guint         n_param_values,
    1471                 :            :                             const GValue *param_values,
    1472                 :            :                             gpointer      invocation_hint,
    1473                 :            :                             gpointer      marshal_data)
    1474                 :            : {
    1475                 :            :   ffi_type *rtype;
    1476                 :            :   void *rvalue;
    1477                 :            :   int n_args;
    1478                 :            :   ffi_type **atypes;
    1479                 :            :   void **args;
    1480                 :            :   int i;
    1481                 :            :   ffi_cif cif;
    1482                 :    3205882 :   GCClosure *cc = (GCClosure*) closure;
    1483                 :            :   gint *enum_tmpval;
    1484                 :    3205882 :   gboolean tmpval_used = FALSE;
    1485                 :            : 
    1486                 :    3205882 :   enum_tmpval = g_alloca (sizeof (gint));
    1487   [ +  #  +  # ]:    3205882 :   if (return_gvalue && G_VALUE_TYPE (return_gvalue))
    1488                 :            :     {
    1489                 :    3206004 :       rtype = value_to_ffi_type (return_gvalue, &rvalue, enum_tmpval, &tmpval_used);
    1490                 :            :     }
    1491                 :            :   else
    1492                 :            :     {
    1493                 :          0 :       rtype = &ffi_type_void;
    1494                 :            :     }
    1495                 :            : 
    1496                 :    3202530 :   rvalue = g_alloca (MAX (rtype->size, sizeof (ffi_arg)));
    1497                 :            : 
    1498                 :    3202530 :   n_args = n_param_values + 1;
    1499                 :    3202530 :   atypes = g_alloca (sizeof (ffi_type *) * n_args);
    1500                 :    3202530 :   args =  g_alloca (sizeof (gpointer) * n_args);
    1501                 :            : 
    1502         [ -  + ]:    3202530 :   if (tmpval_used)
    1503                 :          0 :     enum_tmpval = g_alloca (sizeof (gint));
    1504                 :            : 
    1505         [ -  + ]:    3202530 :   if (G_CCLOSURE_SWAP_DATA (closure))
    1506                 :            :     {
    1507                 :          0 :       atypes[n_args-1] = value_to_ffi_type (param_values + 0,
    1508                 :          0 :                                             &args[n_args-1],
    1509                 :            :                                             enum_tmpval,
    1510                 :            :                                             &tmpval_used);
    1511                 :          0 :       atypes[0] = &ffi_type_pointer;
    1512                 :          0 :       args[0] = &closure->data;
    1513                 :            :     }
    1514                 :            :   else
    1515                 :            :     {
    1516                 :    3202530 :       atypes[0] = value_to_ffi_type (param_values + 0,
    1517                 :            :                                      &args[0],
    1518                 :            :                                      enum_tmpval,
    1519                 :            :                                      &tmpval_used);
    1520                 :    3199653 :       atypes[n_args-1] = &ffi_type_pointer;
    1521                 :    3199653 :       args[n_args-1] = &closure->data;
    1522                 :            :     }
    1523                 :            : 
    1524         [ +  + ]:    6397643 :   for (i = 1; i < n_args - 1; i++)
    1525                 :            :     {
    1526         [ +  + ]:    3199502 :       if (tmpval_used)
    1527                 :         10 :         enum_tmpval = g_alloca (sizeof (gint));
    1528                 :            : 
    1529                 :    3197990 :       atypes[i] = value_to_ffi_type (param_values + i,
    1530                 :    3199502 :                                      &args[i],
    1531                 :            :                                      enum_tmpval,
    1532                 :            :                                      &tmpval_used);
    1533                 :            :     }
    1534                 :            : 
    1535         [ -  + ]:    3198141 :   if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args, rtype, atypes) != FFI_OK)
    1536                 :          0 :     return;
    1537                 :            : 
    1538         [ +  + ]:    3206134 :   ffi_call (&cif, marshal_data ? marshal_data : cc->callback, rvalue, args);
    1539                 :            : 
    1540   [ +  #  +  # ]:    3210487 :   if (return_gvalue && G_VALUE_TYPE (return_gvalue))
    1541                 :    3210493 :     value_from_ffi_type (return_gvalue, rvalue);
    1542                 :            : }
    1543                 :            : 
    1544                 :            : /**
    1545                 :            :  * g_cclosure_marshal_generic_va:
    1546                 :            :  * @closure: the #GClosure to which the marshaller belongs
    1547                 :            :  * @return_value: (nullable): a #GValue to store the return
    1548                 :            :  *  value. May be %NULL if the callback of @closure doesn't return a
    1549                 :            :  *  value.
    1550                 :            :  * @instance: (type GObject.TypeInstance): the instance on which the closure is
    1551                 :            :  *  invoked.
    1552                 :            :  * @args_list: va_list of arguments to be passed to the closure.
    1553                 :            :  * @marshal_data: (nullable): additional data specified when
    1554                 :            :  *  registering the marshaller, see g_closure_set_marshal() and
    1555                 :            :  *  g_closure_set_meta_marshal()
    1556                 :            :  * @n_params: the length of the @param_types array
    1557                 :            :  * @param_types: (array length=n_params): the #GType of each argument from
    1558                 :            :  *  @args_list.
    1559                 :            :  *
    1560                 :            :  * A generic #GVaClosureMarshal function implemented via
    1561                 :            :  * [libffi](http://sourceware.org/libffi/).
    1562                 :            :  *
    1563                 :            :  * Since: 2.30
    1564                 :            :  */
    1565                 :            : void
    1566                 :         13 : g_cclosure_marshal_generic_va (GClosure *closure,
    1567                 :            :                                GValue   *return_value,
    1568                 :            :                                gpointer  instance,
    1569                 :            :                                va_list   args_list,
    1570                 :            :                                gpointer  marshal_data,
    1571                 :            :                                int       n_params,
    1572                 :            :                                GType    *param_types)
    1573                 :            : {
    1574                 :            :   ffi_type *rtype;
    1575                 :            :   void *rvalue;
    1576                 :            :   int n_args;
    1577                 :            :   ffi_type **atypes;
    1578                 :            :   void **args;
    1579                 :            :   va_arg_storage *storage;
    1580                 :            :   int i;
    1581                 :            :   ffi_cif cif;
    1582                 :         13 :   GCClosure *cc = (GCClosure*) closure;
    1583                 :            :   gint *enum_tmpval;
    1584                 :         13 :   gboolean tmpval_used = FALSE;
    1585                 :            :   va_list args_copy;
    1586                 :            : 
    1587                 :         13 :   enum_tmpval = g_alloca (sizeof (gint));
    1588   [ +  +  +  - ]:         13 :   if (return_value && G_VALUE_TYPE (return_value))
    1589                 :            :     {
    1590                 :         10 :       rtype = value_to_ffi_type (return_value, &rvalue, enum_tmpval, &tmpval_used);
    1591                 :            :     }
    1592                 :            :   else
    1593                 :            :     {
    1594                 :          3 :       rtype = &ffi_type_void;
    1595                 :            :     }
    1596                 :            : 
    1597                 :         13 :   rvalue = g_alloca (MAX (rtype->size, sizeof (ffi_arg)));
    1598                 :            : 
    1599                 :         13 :   n_args = n_params + 2;
    1600                 :         13 :   atypes = g_alloca (sizeof (ffi_type *) * n_args);
    1601                 :         13 :   args =  g_alloca (sizeof (gpointer) * n_args);
    1602                 :         13 :   storage = g_alloca (sizeof (va_arg_storage) * n_params);
    1603                 :            : 
    1604         [ -  + ]:         13 :   if (G_CCLOSURE_SWAP_DATA (closure))
    1605                 :            :     {
    1606                 :          0 :       atypes[n_args-1] = &ffi_type_pointer;
    1607                 :          0 :       args[n_args-1] = &instance;
    1608                 :          0 :       atypes[0] = &ffi_type_pointer;
    1609                 :          0 :       args[0] = &closure->data;
    1610                 :            :     }
    1611                 :            :   else
    1612                 :            :     {
    1613                 :         13 :       atypes[0] = &ffi_type_pointer;
    1614                 :         13 :       args[0] = &instance;
    1615                 :         13 :       atypes[n_args-1] = &ffi_type_pointer;
    1616                 :         13 :       args[n_args-1] = &closure->data;
    1617                 :            :     }
    1618                 :            : 
    1619                 :         13 :   va_copy (args_copy, args_list);
    1620                 :            : 
    1621                 :            :   /* Box non-primitive arguments */
    1622         [ +  + ]:         44 :   for (i = 0; i < n_params; i++)
    1623                 :            :     {
    1624                 :         31 :       GType type = param_types[i]  & ~G_SIGNAL_TYPE_STATIC_SCOPE;
    1625                 :         31 :       GType fundamental = G_TYPE_FUNDAMENTAL (type);
    1626                 :            : 
    1627                 :         62 :       atypes[i+1] = va_to_ffi_type (type,
    1628                 :            :                                     &args_copy,
    1629                 :         31 :                                     &storage[i]);
    1630                 :         31 :       args[i+1] = &storage[i];
    1631                 :            : 
    1632         [ +  - ]:         31 :       if ((param_types[i]  & G_SIGNAL_TYPE_STATIC_SCOPE) == 0)
    1633                 :            :         {
    1634   [ +  +  +  - ]:         31 :           if (fundamental == G_TYPE_STRING && storage[i]._gpointer != NULL)
    1635                 :          2 :             storage[i]._gpointer = g_strdup (storage[i]._gpointer);
    1636   [ +  +  +  - ]:         30 :           else if (fundamental == G_TYPE_PARAM && storage[i]._gpointer != NULL)
    1637                 :          1 :             storage[i]._gpointer = g_param_spec_ref (storage[i]._gpointer);
    1638   [ +  +  +  - ]:         29 :           else if (fundamental == G_TYPE_BOXED && storage[i]._gpointer != NULL)
    1639                 :          1 :             storage[i]._gpointer = g_boxed_copy (type, storage[i]._gpointer);
    1640   [ +  +  +  - ]:         28 :           else if (fundamental == G_TYPE_VARIANT && storage[i]._gpointer != NULL)
    1641                 :          1 :             storage[i]._gpointer = g_variant_ref_sink (storage[i]._gpointer);
    1642                 :            :         }
    1643   [ +  +  +  - ]:         31 :       if (fundamental == G_TYPE_OBJECT && storage[i]._gpointer != NULL)
    1644                 :          1 :         storage[i]._gpointer = g_object_ref (storage[i]._gpointer);
    1645                 :            :     }
    1646                 :            : 
    1647                 :         13 :   va_end (args_copy);
    1648                 :            :   
    1649         [ -  + ]:         13 :   if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args, rtype, atypes) != FFI_OK)
    1650                 :          0 :     return;
    1651                 :            : 
    1652         [ +  + ]:         13 :   ffi_call (&cif, marshal_data ? marshal_data : cc->callback, rvalue, args);
    1653                 :            : 
    1654                 :            :   /* Unbox non-primitive arguments */
    1655         [ +  + ]:         44 :   for (i = 0; i < n_params; i++)
    1656                 :            :     {
    1657                 :         31 :       GType type = param_types[i]  & ~G_SIGNAL_TYPE_STATIC_SCOPE;
    1658                 :         31 :       GType fundamental = G_TYPE_FUNDAMENTAL (type);
    1659                 :            : 
    1660         [ +  - ]:         31 :       if ((param_types[i]  & G_SIGNAL_TYPE_STATIC_SCOPE) == 0)
    1661                 :            :         {
    1662   [ +  +  +  - ]:         31 :           if (fundamental == G_TYPE_STRING && storage[i]._gpointer != NULL)
    1663                 :          1 :             g_free (storage[i]._gpointer);
    1664   [ +  +  +  - ]:         30 :           else if (fundamental == G_TYPE_PARAM && storage[i]._gpointer != NULL)
    1665                 :          1 :             g_param_spec_unref (storage[i]._gpointer);
    1666   [ +  +  +  - ]:         29 :           else if (fundamental == G_TYPE_BOXED && storage[i]._gpointer != NULL)
    1667                 :          1 :             g_boxed_free (type, storage[i]._gpointer);
    1668   [ +  +  +  - ]:         28 :           else if (fundamental == G_TYPE_VARIANT && storage[i]._gpointer != NULL)
    1669                 :          1 :             g_variant_unref (storage[i]._gpointer);
    1670                 :            :         }
    1671   [ +  +  +  - ]:         31 :       if (fundamental == G_TYPE_OBJECT && storage[i]._gpointer != NULL)
    1672                 :          1 :         g_object_unref (storage[i]._gpointer);
    1673                 :            :     }
    1674                 :            :   
    1675   [ +  +  +  - ]:         13 :   if (return_value && G_VALUE_TYPE (return_value))
    1676                 :         10 :     value_from_ffi_type (return_value, rvalue);
    1677                 :            : }

Generated by: LCOV version 1.14