LCOV - code coverage report
Current view: top level - gobject - gclosure.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 79.1 % 611 483
Test Date: 2024-11-26 05:23:01 Functions: 91.2 % 34 31
Branches: - 0 0

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

Generated by: LCOV version 2.0-1