LCOV - code coverage report
Current view: top level - glib/gio - gcancellable.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 178 193 92.2 %
Date: 2024-04-16 05:15:53 Functions: 24 25 96.0 %
Branches: 60 78 76.9 %

           Branch data     Line data    Source code
       1                 :            : /* GIO - GLib Input, Output and Streaming Library
       2                 :            :  * 
       3                 :            :  * Copyright (C) 2006-2007 Red Hat, Inc.
       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                 :            :  * Author: Alexander Larsson <alexl@redhat.com>
      21                 :            :  */
      22                 :            : 
      23                 :            : #include "config.h"
      24                 :            : #include "glib.h"
      25                 :            : #include <gioerror.h>
      26                 :            : #include "glib-private.h"
      27                 :            : #include "gcancellable.h"
      28                 :            : #include "glibintl.h"
      29                 :            : 
      30                 :            : 
      31                 :            : /**
      32                 :            :  * GCancellable:
      33                 :            :  *
      34                 :            :  * `GCancellable` allows operations to be cancelled.
      35                 :            :  *
      36                 :            :  * `GCancellable` is a thread-safe operation cancellation stack used
      37                 :            :  * throughout GIO to allow for cancellation of synchronous and
      38                 :            :  * asynchronous operations.
      39                 :            :  */
      40                 :            : 
      41                 :            : enum {
      42                 :            :   CANCELLED,
      43                 :            :   LAST_SIGNAL
      44                 :            : };
      45                 :            : 
      46                 :            : struct _GCancellablePrivate
      47                 :            : {
      48                 :            :   /* Atomic so that g_cancellable_is_cancelled does not require holding the mutex. */
      49                 :            :   gboolean cancelled;
      50                 :            :   /* Access to fields below is protected by cancellable_mutex. */
      51                 :            :   guint cancelled_running : 1;
      52                 :            :   guint cancelled_running_waiting : 1;
      53                 :            :   unsigned cancelled_emissions;
      54                 :            :   unsigned cancelled_emissions_waiting : 1;
      55                 :            : 
      56                 :            :   guint fd_refcount;
      57                 :            :   GWakeup *wakeup;
      58                 :            : };
      59                 :            : 
      60                 :            : static guint signals[LAST_SIGNAL] = { 0 };
      61                 :            : 
      62   [ +  +  +  -  :     502646 : G_DEFINE_TYPE_WITH_PRIVATE (GCancellable, g_cancellable, G_TYPE_OBJECT)
                   +  + ]
      63                 :            : 
      64                 :            : static GPrivate current_cancellable;
      65                 :            : static GMutex cancellable_mutex;
      66                 :            : static GCond cancellable_cond;
      67                 :            : 
      68                 :            : static void
      69                 :     101854 : g_cancellable_finalize (GObject *object)
      70                 :            : {
      71                 :     101854 :   GCancellable *cancellable = G_CANCELLABLE (object);
      72                 :            : 
      73         [ -  + ]:     101854 :   if (cancellable->priv->wakeup)
      74                 :          0 :     GLIB_PRIVATE_CALL (g_wakeup_free) (cancellable->priv->wakeup);
      75                 :            : 
      76                 :     101854 :   G_OBJECT_CLASS (g_cancellable_parent_class)->finalize (object);
      77                 :     101854 : }
      78                 :            : 
      79                 :            : static void
      80                 :        114 : g_cancellable_class_init (GCancellableClass *klass)
      81                 :            : {
      82                 :        114 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
      83                 :            : 
      84                 :        114 :   gobject_class->finalize = g_cancellable_finalize;
      85                 :            : 
      86                 :            :   /**
      87                 :            :    * GCancellable::cancelled:
      88                 :            :    * @cancellable: a #GCancellable.
      89                 :            :    * 
      90                 :            :    * Emitted when the operation has been cancelled.
      91                 :            :    * 
      92                 :            :    * Can be used by implementations of cancellable operations. If the
      93                 :            :    * operation is cancelled from another thread, the signal will be
      94                 :            :    * emitted in the thread that cancelled the operation, not the
      95                 :            :    * thread that is running the operation.
      96                 :            :    *
      97                 :            :    * Note that disconnecting from this signal (or any signal) in a
      98                 :            :    * multi-threaded program is prone to race conditions. For instance
      99                 :            :    * it is possible that a signal handler may be invoked even after
     100                 :            :    * a call to g_signal_handler_disconnect() for that handler has
     101                 :            :    * already returned.
     102                 :            :    * 
     103                 :            :    * There is also a problem when cancellation happens right before
     104                 :            :    * connecting to the signal. If this happens the signal will
     105                 :            :    * unexpectedly not be emitted, and checking before connecting to
     106                 :            :    * the signal leaves a race condition where this is still happening.
     107                 :            :    *
     108                 :            :    * In order to make it safe and easy to connect handlers there
     109                 :            :    * are two helper functions: g_cancellable_connect() and
     110                 :            :    * g_cancellable_disconnect() which protect against problems
     111                 :            :    * like this.
     112                 :            :    *
     113                 :            :    * An example of how to us this:
     114                 :            :    * |[<!-- language="C" -->
     115                 :            :    *     // Make sure we don't do unnecessary work if already cancelled
     116                 :            :    *     if (g_cancellable_set_error_if_cancelled (cancellable, error))
     117                 :            :    *       return;
     118                 :            :    *
     119                 :            :    *     // Set up all the data needed to be able to handle cancellation
     120                 :            :    *     // of the operation
     121                 :            :    *     my_data = my_data_new (...);
     122                 :            :    *
     123                 :            :    *     id = 0;
     124                 :            :    *     if (cancellable)
     125                 :            :    *       id = g_cancellable_connect (cancellable,
     126                 :            :    *                                  G_CALLBACK (cancelled_handler)
     127                 :            :    *                                  data, NULL);
     128                 :            :    *
     129                 :            :    *     // cancellable operation here...
     130                 :            :    *
     131                 :            :    *     g_cancellable_disconnect (cancellable, id);
     132                 :            :    *
     133                 :            :    *     // cancelled_handler is never called after this, it is now safe
     134                 :            :    *     // to free the data
     135                 :            :    *     my_data_free (my_data);  
     136                 :            :    * ]|
     137                 :            :    *
     138                 :            :    * Note that the cancelled signal is emitted in the thread that
     139                 :            :    * the user cancelled from, which may be the main thread. So, the
     140                 :            :    * cancellable signal should not do something that can block.
     141                 :            :    */
     142                 :        114 :   signals[CANCELLED] =
     143                 :        114 :     g_signal_new (I_("cancelled"),
     144                 :            :                   G_TYPE_FROM_CLASS (gobject_class),
     145                 :            :                   G_SIGNAL_RUN_LAST,
     146                 :            :                   G_STRUCT_OFFSET (GCancellableClass, cancelled),
     147                 :            :                   NULL, NULL,
     148                 :            :                   NULL,
     149                 :            :                   G_TYPE_NONE, 0);
     150                 :            :   
     151                 :        114 : }
     152                 :            : 
     153                 :            : static void
     154                 :     102151 : g_cancellable_init (GCancellable *cancellable)
     155                 :            : {
     156                 :     102151 :   cancellable->priv = g_cancellable_get_instance_private (cancellable);
     157                 :     102151 : }
     158                 :            : 
     159                 :            : /**
     160                 :            :  * g_cancellable_new:
     161                 :            :  * 
     162                 :            :  * Creates a new #GCancellable object.
     163                 :            :  *
     164                 :            :  * Applications that want to start one or more operations
     165                 :            :  * that should be cancellable should create a #GCancellable
     166                 :            :  * and pass it to the operations.
     167                 :            :  *
     168                 :            :  * One #GCancellable can be used in multiple consecutive
     169                 :            :  * operations or in multiple concurrent operations.
     170                 :            :  *  
     171                 :            :  * Returns: a #GCancellable.
     172                 :            :  **/
     173                 :            : GCancellable *
     174                 :     102150 : g_cancellable_new (void)
     175                 :            : {
     176                 :     102150 :   return g_object_new (G_TYPE_CANCELLABLE, NULL);
     177                 :            : }
     178                 :            : 
     179                 :            : /**
     180                 :            :  * g_cancellable_push_current:
     181                 :            :  * @cancellable: a #GCancellable object
     182                 :            :  *
     183                 :            :  * Pushes @cancellable onto the cancellable stack. The current
     184                 :            :  * cancellable can then be received using g_cancellable_get_current().
     185                 :            :  *
     186                 :            :  * This is useful when implementing cancellable operations in
     187                 :            :  * code that does not allow you to pass down the cancellable object.
     188                 :            :  *
     189                 :            :  * This is typically called automatically by e.g. #GFile operations,
     190                 :            :  * so you rarely have to call this yourself.
     191                 :            :  **/
     192                 :            : void
     193                 :      22066 : g_cancellable_push_current (GCancellable *cancellable)
     194                 :            : {
     195                 :            :   GSList *l;
     196                 :            : 
     197                 :      22066 :   g_return_if_fail (cancellable != NULL);
     198                 :            : 
     199                 :      22066 :   l = g_private_get (&current_cancellable);
     200                 :      22068 :   l = g_slist_prepend (l, cancellable);
     201                 :      22068 :   g_private_set (&current_cancellable, l);
     202                 :            : }
     203                 :            : 
     204                 :            : /**
     205                 :            :  * g_cancellable_pop_current:
     206                 :            :  * @cancellable: a #GCancellable object
     207                 :            :  *
     208                 :            :  * Pops @cancellable off the cancellable stack (verifying that @cancellable
     209                 :            :  * is on the top of the stack).
     210                 :            :  **/
     211                 :            : void
     212                 :      22068 : g_cancellable_pop_current (GCancellable *cancellable)
     213                 :            : {
     214                 :            :   GSList *l;
     215                 :            : 
     216                 :      22068 :   l = g_private_get (&current_cancellable);
     217                 :            : 
     218                 :      22068 :   g_return_if_fail (l != NULL);
     219                 :      22068 :   g_return_if_fail (l->data == cancellable);
     220                 :            : 
     221                 :      22068 :   l = g_slist_delete_link (l, l);
     222                 :      22068 :   g_private_set (&current_cancellable, l);
     223                 :            : }
     224                 :            : 
     225                 :            : /**
     226                 :            :  * g_cancellable_get_current:
     227                 :            :  *
     228                 :            :  * Gets the top cancellable from the stack.
     229                 :            :  *
     230                 :            :  * Returns: (nullable) (transfer none): a #GCancellable from the top
     231                 :            :  * of the stack, or %NULL if the stack is empty.
     232                 :            :  **/
     233                 :            : GCancellable *
     234                 :          0 : g_cancellable_get_current  (void)
     235                 :            : {
     236                 :            :   GSList *l;
     237                 :            : 
     238                 :          0 :   l = g_private_get (&current_cancellable);
     239         [ #  # ]:          0 :   if (l == NULL)
     240                 :          0 :     return NULL;
     241                 :            : 
     242                 :          0 :   return G_CANCELLABLE (l->data);
     243                 :            : }
     244                 :            : 
     245                 :            : /**
     246                 :            :  * g_cancellable_reset:
     247                 :            :  * @cancellable: a #GCancellable object.
     248                 :            :  * 
     249                 :            :  * Resets @cancellable to its uncancelled state.
     250                 :            :  *
     251                 :            :  * If cancellable is currently in use by any cancellable operation
     252                 :            :  * then the behavior of this function is undefined.
     253                 :            :  *
     254                 :            :  * Note that it is generally not a good idea to reuse an existing
     255                 :            :  * cancellable for more operations after it has been cancelled once,
     256                 :            :  * as this function might tempt you to do. The recommended practice
     257                 :            :  * is to drop the reference to a cancellable after cancelling it,
     258                 :            :  * and let it die with the outstanding async operations. You should
     259                 :            :  * create a fresh cancellable for further async operations.
     260                 :            :  **/
     261                 :            : void 
     262                 :      20270 : g_cancellable_reset (GCancellable *cancellable)
     263                 :            : {
     264                 :            :   GCancellablePrivate *priv;
     265                 :            : 
     266                 :      20270 :   g_return_if_fail (G_IS_CANCELLABLE (cancellable));
     267                 :            : 
     268                 :      20270 :   g_mutex_lock (&cancellable_mutex);
     269                 :            : 
     270                 :      20270 :   priv = cancellable->priv;
     271                 :            : 
     272   [ +  +  -  + ]:      20270 :   while (priv->cancelled_running || priv->cancelled_emissions > 0)
     273                 :            :     {
     274         [ +  - ]:          1 :       if (priv->cancelled_running)
     275                 :          1 :         priv->cancelled_running_waiting = TRUE;
     276                 :            : 
     277         [ -  + ]:          1 :       if (priv->cancelled_emissions > 0)
     278                 :          0 :         priv->cancelled_emissions_waiting = TRUE;
     279                 :            : 
     280                 :          1 :       g_cond_wait (&cancellable_cond, &cancellable_mutex);
     281                 :            :     }
     282                 :            : 
     283         [ +  + ]:      20269 :   if (g_atomic_int_exchange (&priv->cancelled, FALSE))
     284                 :            :     {
     285         [ -  + ]:         37 :       if (priv->wakeup)
     286                 :          0 :         GLIB_PRIVATE_CALL (g_wakeup_acknowledge) (priv->wakeup);
     287                 :            :     }
     288                 :            : 
     289                 :      20269 :   g_mutex_unlock (&cancellable_mutex);
     290                 :            : }
     291                 :            : 
     292                 :            : /**
     293                 :            :  * g_cancellable_is_cancelled:
     294                 :            :  * @cancellable: (nullable): a #GCancellable or %NULL
     295                 :            :  *
     296                 :            :  * Checks if a cancellable job has been cancelled.
     297                 :            :  *
     298                 :            :  * Returns: %TRUE if @cancellable is cancelled,
     299                 :            :  * FALSE if called with %NULL or if item is not cancelled.
     300                 :            :  **/
     301                 :            : gboolean
     302                 :    1027512 : g_cancellable_is_cancelled (GCancellable *cancellable)
     303                 :            : {
     304   [ +  +  +  + ]:    1027512 :   return cancellable != NULL && g_atomic_int_get (&cancellable->priv->cancelled);
     305                 :            : }
     306                 :            : 
     307                 :            : /**
     308                 :            :  * g_cancellable_set_error_if_cancelled:
     309                 :            :  * @cancellable: (nullable): a #GCancellable or %NULL
     310                 :            :  * @error: #GError to append error state to
     311                 :            :  *
     312                 :            :  * If the @cancellable is cancelled, sets the error to notify
     313                 :            :  * that the operation was cancelled.
     314                 :            :  *
     315                 :            :  * Returns: %TRUE if @cancellable was cancelled, %FALSE if it was not
     316                 :            :  */
     317                 :            : gboolean
     318                 :     437255 : g_cancellable_set_error_if_cancelled (GCancellable  *cancellable,
     319                 :            :                                       GError       **error)
     320                 :            : {
     321         [ +  + ]:     437255 :   if (g_cancellable_is_cancelled (cancellable))
     322                 :            :     {
     323                 :       3019 :       g_set_error_literal (error,
     324                 :            :                            G_IO_ERROR,
     325                 :            :                            G_IO_ERROR_CANCELLED,
     326                 :            :                            _("Operation was cancelled"));
     327                 :       3019 :       return TRUE;
     328                 :            :     }
     329                 :            : 
     330                 :     434236 :   return FALSE;
     331                 :            : }
     332                 :            : 
     333                 :            : /**
     334                 :            :  * g_cancellable_get_fd:
     335                 :            :  * @cancellable: a #GCancellable.
     336                 :            :  * 
     337                 :            :  * Gets the file descriptor for a cancellable job. This can be used to
     338                 :            :  * implement cancellable operations on Unix systems. The returned fd will
     339                 :            :  * turn readable when @cancellable is cancelled.
     340                 :            :  *
     341                 :            :  * You are not supposed to read from the fd yourself, just check for
     342                 :            :  * readable status. Reading to unset the readable status is done
     343                 :            :  * with g_cancellable_reset().
     344                 :            :  * 
     345                 :            :  * After a successful return from this function, you should use 
     346                 :            :  * g_cancellable_release_fd() to free up resources allocated for 
     347                 :            :  * the returned file descriptor.
     348                 :            :  *
     349                 :            :  * See also g_cancellable_make_pollfd().
     350                 :            :  *
     351                 :            :  * Returns: A valid file descriptor. `-1` if the file descriptor
     352                 :            :  * is not supported, or on errors. 
     353                 :            :  **/
     354                 :            : int
     355                 :          1 : g_cancellable_get_fd (GCancellable *cancellable)
     356                 :            : {
     357                 :            :   GPollFD pollfd;
     358                 :            : #ifndef G_OS_WIN32
     359                 :            :   gboolean retval G_GNUC_UNUSED  /* when compiling with G_DISABLE_ASSERT */;
     360                 :            : #endif
     361                 :            : 
     362         [ -  + ]:          1 :   if (cancellable == NULL)
     363                 :          0 :           return -1;
     364                 :            : 
     365                 :            : #ifdef G_OS_WIN32
     366                 :            :   pollfd.fd = -1;
     367                 :            : #else
     368                 :          1 :   retval = g_cancellable_make_pollfd (cancellable, &pollfd);
     369                 :          1 :   g_assert (retval);
     370                 :            : #endif
     371                 :            : 
     372                 :          1 :   return pollfd.fd;
     373                 :            : }
     374                 :            : 
     375                 :            : /**
     376                 :            :  * g_cancellable_make_pollfd:
     377                 :            :  * @cancellable: (nullable): a #GCancellable or %NULL
     378                 :            :  * @pollfd: a pointer to a #GPollFD
     379                 :            :  * 
     380                 :            :  * Creates a #GPollFD corresponding to @cancellable; this can be passed
     381                 :            :  * to g_poll() and used to poll for cancellation. This is useful both
     382                 :            :  * for unix systems without a native poll and for portability to
     383                 :            :  * windows.
     384                 :            :  *
     385                 :            :  * When this function returns %TRUE, you should use 
     386                 :            :  * g_cancellable_release_fd() to free up resources allocated for the 
     387                 :            :  * @pollfd. After a %FALSE return, do not call g_cancellable_release_fd().
     388                 :            :  *
     389                 :            :  * If this function returns %FALSE, either no @cancellable was given or
     390                 :            :  * resource limits prevent this function from allocating the necessary 
     391                 :            :  * structures for polling. (On Linux, you will likely have reached 
     392                 :            :  * the maximum number of file descriptors.) The suggested way to handle
     393                 :            :  * these cases is to ignore the @cancellable.
     394                 :            :  *
     395                 :            :  * You are not supposed to read from the fd yourself, just check for
     396                 :            :  * readable status. Reading to unset the readable status is done
     397                 :            :  * with g_cancellable_reset().
     398                 :            :  *
     399                 :            :  * Returns: %TRUE if @pollfd was successfully initialized, %FALSE on 
     400                 :            :  *          failure to prepare the cancellable.
     401                 :            :  * 
     402                 :            :  * Since: 2.22
     403                 :            :  **/
     404                 :            : gboolean
     405                 :      65145 : g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
     406                 :            : {
     407                 :      65145 :   g_return_val_if_fail (pollfd != NULL, FALSE);
     408         [ +  + ]:      65145 :   if (cancellable == NULL)
     409                 :      43049 :     return FALSE;
     410                 :      22096 :   g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), FALSE);
     411                 :            : 
     412                 :      22096 :   g_mutex_lock (&cancellable_mutex);
     413                 :            : 
     414                 :      22100 :   cancellable->priv->fd_refcount++;
     415                 :            : 
     416         [ +  + ]:      22100 :   if (cancellable->priv->wakeup == NULL)
     417                 :            :     {
     418                 :      22073 :       cancellable->priv->wakeup = GLIB_PRIVATE_CALL (g_wakeup_new) ();
     419                 :            : 
     420         [ +  + ]:      22073 :       if (g_atomic_int_get (&cancellable->priv->cancelled))
     421                 :         76 :         GLIB_PRIVATE_CALL (g_wakeup_signal) (cancellable->priv->wakeup);
     422                 :            :     }
     423                 :            : 
     424                 :      22100 :   GLIB_PRIVATE_CALL (g_wakeup_get_pollfd) (cancellable->priv->wakeup, pollfd);
     425                 :            : 
     426                 :      22100 :   g_mutex_unlock (&cancellable_mutex);
     427                 :            : 
     428                 :      22100 :   return TRUE;
     429                 :            : }
     430                 :            : 
     431                 :            : /**
     432                 :            :  * g_cancellable_release_fd:
     433                 :            :  * @cancellable: a #GCancellable
     434                 :            :  *
     435                 :            :  * Releases a resources previously allocated by g_cancellable_get_fd()
     436                 :            :  * or g_cancellable_make_pollfd().
     437                 :            :  *
     438                 :            :  * For compatibility reasons with older releases, calling this function 
     439                 :            :  * is not strictly required, the resources will be automatically freed
     440                 :            :  * when the @cancellable is finalized. However, the @cancellable will
     441                 :            :  * block scarce file descriptors until it is finalized if this function
     442                 :            :  * is not called. This can cause the application to run out of file 
     443                 :            :  * descriptors when many #GCancellables are used at the same time.
     444                 :            :  * 
     445                 :            :  * Since: 2.22
     446                 :            :  **/
     447                 :            : void
     448                 :      22098 : g_cancellable_release_fd (GCancellable *cancellable)
     449                 :            : {
     450                 :            :   GCancellablePrivate *priv;
     451                 :            : 
     452         [ -  + ]:      22098 :   if (cancellable == NULL)
     453                 :          0 :     return;
     454                 :            : 
     455                 :      22098 :   g_return_if_fail (G_IS_CANCELLABLE (cancellable));
     456                 :            : 
     457                 :      22098 :   priv = cancellable->priv;
     458                 :            : 
     459                 :      22098 :   g_mutex_lock (&cancellable_mutex);
     460                 :      22100 :   g_assert (priv->fd_refcount > 0);
     461                 :            : 
     462                 :      22100 :   priv->fd_refcount--;
     463         [ +  + ]:      22100 :   if (priv->fd_refcount == 0)
     464                 :            :     {
     465                 :      22073 :       GLIB_PRIVATE_CALL (g_wakeup_free) (priv->wakeup);
     466                 :      22073 :       priv->wakeup = NULL;
     467                 :            :     }
     468                 :            : 
     469                 :      22100 :   g_mutex_unlock (&cancellable_mutex);
     470                 :            : }
     471                 :            : 
     472                 :            : /**
     473                 :            :  * g_cancellable_cancel:
     474                 :            :  * @cancellable: (nullable): a #GCancellable object.
     475                 :            :  * 
     476                 :            :  * Will set @cancellable to cancelled, and will emit the
     477                 :            :  * #GCancellable::cancelled signal. (However, see the warning about
     478                 :            :  * race conditions in the documentation for that signal if you are
     479                 :            :  * planning to connect to it.)
     480                 :            :  *
     481                 :            :  * This function is thread-safe. In other words, you can safely call
     482                 :            :  * it from a thread other than the one running the operation that was
     483                 :            :  * passed the @cancellable.
     484                 :            :  *
     485                 :            :  * If @cancellable is %NULL, this function returns immediately for convenience.
     486                 :            :  *
     487                 :            :  * The convention within GIO is that cancelling an asynchronous
     488                 :            :  * operation causes it to complete asynchronously. That is, if you
     489                 :            :  * cancel the operation from the same thread in which it is running,
     490                 :            :  * then the operation's #GAsyncReadyCallback will not be invoked until
     491                 :            :  * the application returns to the main loop.
     492                 :            :  **/
     493                 :            : void
     494                 :     121982 : g_cancellable_cancel (GCancellable *cancellable)
     495                 :            : {
     496                 :            :   GCancellablePrivate *priv;
     497                 :            : 
     498   [ +  +  +  + ]:     121982 :   if (cancellable == NULL || g_cancellable_is_cancelled (cancellable))
     499                 :      20139 :     return;
     500                 :            : 
     501                 :     101843 :   priv = cancellable->priv;
     502                 :            : 
     503                 :     101843 :   g_mutex_lock (&cancellable_mutex);
     504                 :            : 
     505         [ -  + ]:     101843 :   if (g_atomic_int_exchange (&priv->cancelled, TRUE))
     506                 :            :     {
     507                 :          0 :       g_mutex_unlock (&cancellable_mutex);
     508                 :          0 :       return;
     509                 :            :     }
     510                 :            : 
     511                 :     101843 :   priv->cancelled_running = TRUE;
     512                 :            : 
     513         [ +  + ]:     101843 :   if (priv->wakeup)
     514                 :          9 :     GLIB_PRIVATE_CALL (g_wakeup_signal) (priv->wakeup);
     515                 :            : 
     516                 :     101843 :   g_mutex_unlock (&cancellable_mutex);
     517                 :            : 
     518                 :     101843 :   g_object_ref (cancellable);
     519                 :     101843 :   g_signal_emit (cancellable, signals[CANCELLED], 0);
     520                 :            : 
     521                 :     101841 :   g_mutex_lock (&cancellable_mutex);
     522                 :            : 
     523                 :     101841 :   priv->cancelled_running = FALSE;
     524         [ -  + ]:     101841 :   if (priv->cancelled_running_waiting)
     525                 :          0 :     g_cond_broadcast (&cancellable_cond);
     526                 :     101841 :   priv->cancelled_running_waiting = FALSE;
     527                 :            : 
     528                 :     101841 :   g_mutex_unlock (&cancellable_mutex);
     529                 :            : 
     530                 :     101841 :   g_object_unref (cancellable);
     531                 :            : }
     532                 :            : 
     533                 :            : /**
     534                 :            :  * g_cancellable_connect:
     535                 :            :  * @cancellable: A #GCancellable.
     536                 :            :  * @callback: The #GCallback to connect.
     537                 :            :  * @data: Data to pass to @callback.
     538                 :            :  * @data_destroy_func: (nullable): Free function for @data or %NULL.
     539                 :            :  *
     540                 :            :  * Convenience function to connect to the #GCancellable::cancelled
     541                 :            :  * signal. Also handles the race condition that may happen
     542                 :            :  * if the cancellable is cancelled right before connecting.
     543                 :            :  *
     544                 :            :  * @callback is called at most once, either directly at the
     545                 :            :  * time of the connect if @cancellable is already cancelled,
     546                 :            :  * or when @cancellable is cancelled in some thread.
     547                 :            :  *
     548                 :            :  * @data_destroy_func will be called when the handler is
     549                 :            :  * disconnected, or immediately if the cancellable is already
     550                 :            :  * cancelled.
     551                 :            :  *
     552                 :            :  * See #GCancellable::cancelled for details on how to use this.
     553                 :            :  *
     554                 :            :  * Since GLib 2.40, the lock protecting @cancellable is not held when
     555                 :            :  * @callback is invoked.  This lifts a restriction in place for
     556                 :            :  * earlier GLib versions which now makes it easier to write cleanup
     557                 :            :  * code that unconditionally invokes e.g. g_cancellable_cancel().
     558                 :            :  *
     559                 :            :  * Returns: The id of the signal handler or 0 if @cancellable has already
     560                 :            :  *          been cancelled.
     561                 :            :  *
     562                 :            :  * Since: 2.22
     563                 :            :  */
     564                 :            : gulong
     565                 :      10025 : g_cancellable_connect (GCancellable   *cancellable,
     566                 :            :                        GCallback       callback,
     567                 :            :                        gpointer        data,
     568                 :            :                        GDestroyNotify  data_destroy_func)
     569                 :            : {
     570                 :            :   gulong id;
     571                 :            : 
     572                 :      10025 :   g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), 0);
     573                 :            : 
     574                 :      10025 :   g_mutex_lock (&cancellable_mutex);
     575                 :            : 
     576         [ +  + ]:      10025 :   if (g_atomic_int_get (&cancellable->priv->cancelled))
     577                 :            :     {
     578                 :            :       void (*_callback) (GCancellable *cancellable,
     579                 :            :                          gpointer      user_data);
     580                 :            : 
     581                 :      10001 :       _callback = (void *)callback;
     582                 :      10001 :       id = 0;
     583                 :            : 
     584                 :      10001 :       cancellable->priv->cancelled_emissions++;
     585                 :            : 
     586                 :      10001 :       g_mutex_unlock (&cancellable_mutex);
     587                 :            : 
     588                 :      10001 :       _callback (cancellable, data);
     589                 :            : 
     590         [ +  + ]:      10001 :       if (data_destroy_func)
     591                 :          1 :         data_destroy_func (data);
     592                 :            : 
     593                 :      10001 :       g_mutex_lock (&cancellable_mutex);
     594                 :            : 
     595         [ -  + ]:      10001 :       if (cancellable->priv->cancelled_emissions_waiting)
     596                 :          0 :         g_cond_broadcast (&cancellable_cond);
     597                 :            : 
     598                 :      10001 :       cancellable->priv->cancelled_emissions--;
     599                 :            : 
     600                 :      10001 :       g_mutex_unlock (&cancellable_mutex);
     601                 :            :     }
     602                 :            :   else
     603                 :            :     {
     604                 :         24 :       id = g_signal_connect_data (cancellable, "cancelled",
     605                 :            :                                   callback, data,
     606                 :            :                                   (GClosureNotify) data_destroy_func,
     607                 :            :                                   G_CONNECT_DEFAULT);
     608                 :            : 
     609                 :         24 :       g_mutex_unlock (&cancellable_mutex);
     610                 :            :     }
     611                 :            : 
     612                 :            : 
     613                 :      10025 :   return id;
     614                 :            : }
     615                 :            : 
     616                 :            : /**
     617                 :            :  * g_cancellable_disconnect:
     618                 :            :  * @cancellable: (nullable): A #GCancellable or %NULL.
     619                 :            :  * @handler_id: Handler id of the handler to be disconnected, or `0`.
     620                 :            :  *
     621                 :            :  * Disconnects a handler from a cancellable instance similar to
     622                 :            :  * g_signal_handler_disconnect().  Additionally, in the event that a
     623                 :            :  * signal handler is currently running, this call will block until the
     624                 :            :  * handler has finished.  Calling this function from a
     625                 :            :  * #GCancellable::cancelled signal handler will therefore result in a
     626                 :            :  * deadlock.
     627                 :            :  *
     628                 :            :  * This avoids a race condition where a thread cancels at the
     629                 :            :  * same time as the cancellable operation is finished and the
     630                 :            :  * signal handler is removed. See #GCancellable::cancelled for
     631                 :            :  * details on how to use this.
     632                 :            :  *
     633                 :            :  * If @cancellable is %NULL or @handler_id is `0` this function does
     634                 :            :  * nothing.
     635                 :            :  *
     636                 :            :  * Since: 2.22
     637                 :            :  */
     638                 :            : void
     639                 :      10054 : g_cancellable_disconnect (GCancellable  *cancellable,
     640                 :            :                           gulong         handler_id)
     641                 :            : {
     642                 :            :   GCancellablePrivate *priv;
     643                 :            : 
     644   [ +  +  -  + ]:      10054 :   if (handler_id == 0 ||  cancellable == NULL)
     645                 :      10039 :     return;
     646                 :            : 
     647                 :         15 :   g_mutex_lock (&cancellable_mutex);
     648                 :            : 
     649                 :         15 :   priv = cancellable->priv;
     650                 :            : 
     651   [ +  +  -  + ]:         15 :   while (priv->cancelled_running || priv->cancelled_emissions)
     652                 :            :     {
     653         [ +  - ]:          1 :       if (priv->cancelled_running)
     654                 :          1 :         priv->cancelled_running_waiting = TRUE;
     655                 :            : 
     656         [ -  + ]:          1 :       if (priv->cancelled_emissions)
     657                 :          0 :         priv->cancelled_emissions_waiting = TRUE;
     658                 :            : 
     659                 :          1 :       g_cond_wait (&cancellable_cond, &cancellable_mutex);
     660                 :            :     }
     661                 :            : 
     662                 :         14 :   g_signal_handler_disconnect (cancellable, handler_id);
     663                 :            : 
     664                 :         14 :   g_mutex_unlock (&cancellable_mutex);
     665                 :            : }
     666                 :            : 
     667                 :            : typedef struct {
     668                 :            :   GSource       source;
     669                 :            : 
     670                 :            :   GCancellable *cancellable;
     671                 :            :   gulong        cancelled_handler;
     672                 :            :   /* Protected by cancellable_mutex: */
     673                 :            :   gboolean      resurrected_during_cancellation;
     674                 :            : } GCancellableSource;
     675                 :            : 
     676                 :            : /*
     677                 :            :  * The reference count of the GSource might be 0 at this point but it is not
     678                 :            :  * finalized yet and its dispose function did not run yet, or otherwise we
     679                 :            :  * would have disconnected the signal handler already and due to the signal
     680                 :            :  * emission lock it would be impossible to call the signal handler at that
     681                 :            :  * point. That is: at this point we either have a fully valid GSource, or
     682                 :            :  * it's not disposed or finalized yet and we can still resurrect it as needed.
     683                 :            :  *
     684                 :            :  * As such we first ensure that we have a strong reference to the GSource in
     685                 :            :  * here before calling any other GSource API.
     686                 :            :  */
     687                 :            : static void
     688                 :      96820 : cancellable_source_cancelled (GCancellable *cancellable,
     689                 :            :                               gpointer      user_data)
     690                 :            : {
     691                 :      96820 :   GSource *source = user_data;
     692                 :      96820 :   GCancellableSource *cancellable_source = (GCancellableSource *) source;
     693                 :            : 
     694                 :      96820 :   g_mutex_lock (&cancellable_mutex);
     695                 :            : 
     696                 :            :   /* Drop the reference added in cancellable_source_dispose(); see the comment there.
     697                 :            :    * The reference must be dropped after unlocking @cancellable_mutex since
     698                 :            :    * it could be the final reference, and the dispose function takes
     699                 :            :    * @cancellable_mutex. */
     700         [ +  + ]:      96820 :   if (cancellable_source->resurrected_during_cancellation)
     701                 :            :     {
     702                 :         60 :       cancellable_source->resurrected_during_cancellation = FALSE;
     703                 :         60 :       g_mutex_unlock (&cancellable_mutex);
     704                 :         60 :       g_source_unref (source);
     705                 :         60 :       return;
     706                 :            :     }
     707                 :            : 
     708                 :      96760 :   g_source_ref (source);
     709                 :      96760 :   g_mutex_unlock (&cancellable_mutex);
     710                 :      96760 :   g_source_set_ready_time (source, 0);
     711                 :      96760 :   g_source_unref (source);
     712                 :            : }
     713                 :            : 
     714                 :            : static gboolean
     715                 :       1467 : cancellable_source_dispatch (GSource     *source,
     716                 :            :                              GSourceFunc  callback,
     717                 :            :                              gpointer     user_data)
     718                 :            : {
     719                 :       1467 :   GCancellableSourceFunc func = (GCancellableSourceFunc)callback;
     720                 :       1467 :   GCancellableSource *cancellable_source = (GCancellableSource *)source;
     721                 :            : 
     722                 :       1467 :   g_source_set_ready_time (source, -1);
     723                 :       1467 :   return (*func) (cancellable_source->cancellable, user_data);
     724                 :            : }
     725                 :            : 
     726                 :            : static void
     727                 :     123043 : cancellable_source_dispose (GSource *source)
     728                 :            : {
     729                 :     123043 :   GCancellableSource *cancellable_source = (GCancellableSource *)source;
     730                 :            : 
     731                 :     123043 :   g_mutex_lock (&cancellable_mutex);
     732                 :            : 
     733         [ +  + ]:     123043 :   if (cancellable_source->cancellable)
     734                 :            :     {
     735         [ +  + ]:     122983 :       if (cancellable_source->cancellable->priv->cancelled_running)
     736                 :            :         {
     737                 :            :           /* There can be a race here: if thread A has called
     738                 :            :            * g_cancellable_cancel() and has got as far as committing to call
     739                 :            :            * cancellable_source_cancelled(), then thread B drops the final
     740                 :            :            * ref on the GCancellableSource before g_source_ref() is called in
     741                 :            :            * cancellable_source_cancelled(), then cancellable_source_dispose()
     742                 :            :            * will run through and the GCancellableSource will be finalised
     743                 :            :            * before cancellable_source_cancelled() gets to g_source_ref(). It
     744                 :            :            * will then be left in a state where it’s committed to using a
     745                 :            :            * dangling GCancellableSource pointer.
     746                 :            :            *
     747                 :            :            * Eliminate that race by resurrecting the #GSource temporarily, and
     748                 :            :            * then dropping that reference in cancellable_source_cancelled(),
     749                 :            :            * which should be guaranteed to fire because we’re inside a
     750                 :            :            * @cancelled_running block.
     751                 :            :            */
     752                 :        116 :           g_source_ref (source);
     753                 :        116 :           cancellable_source->resurrected_during_cancellation = TRUE;
     754                 :            :         }
     755                 :            : 
     756                 :     122983 :       g_clear_signal_handler (&cancellable_source->cancelled_handler,
     757                 :            :                               cancellable_source->cancellable);
     758                 :     122983 :       g_clear_object (&cancellable_source->cancellable);
     759                 :            :     }
     760                 :            : 
     761                 :     123043 :   g_mutex_unlock (&cancellable_mutex);
     762                 :     123043 : }
     763                 :            : 
     764                 :            : static gboolean
     765                 :       1443 : cancellable_source_closure_callback (GCancellable *cancellable,
     766                 :            :                                      gpointer      data)
     767                 :            : {
     768                 :       1443 :   GClosure *closure = data;
     769                 :            : 
     770                 :       1443 :   GValue params = G_VALUE_INIT;
     771                 :       1443 :   GValue result_value = G_VALUE_INIT;
     772                 :            :   gboolean result;
     773                 :            : 
     774                 :       1443 :   g_value_init (&result_value, G_TYPE_BOOLEAN);
     775                 :            : 
     776                 :       1443 :   g_value_init (&params, G_TYPE_CANCELLABLE);
     777                 :       1443 :   g_value_set_object (&params, cancellable);
     778                 :            : 
     779                 :       1443 :   g_closure_invoke (closure, &result_value, 1, &params, NULL);
     780                 :            : 
     781                 :       1443 :   result = g_value_get_boolean (&result_value);
     782                 :       1443 :   g_value_unset (&result_value);
     783                 :       1443 :   g_value_unset (&params);
     784                 :            : 
     785                 :       1443 :   return result;
     786                 :            : }
     787                 :            : 
     788                 :            : static GSourceFuncs cancellable_source_funcs =
     789                 :            : {
     790                 :            :   NULL,
     791                 :            :   NULL,
     792                 :            :   cancellable_source_dispatch,
     793                 :            :   NULL,
     794                 :            :   (GSourceFunc)cancellable_source_closure_callback,
     795                 :            :   NULL,
     796                 :            : };
     797                 :            : 
     798                 :            : /**
     799                 :            :  * g_cancellable_source_new:
     800                 :            :  * @cancellable: (nullable): a #GCancellable, or %NULL
     801                 :            :  *
     802                 :            :  * Creates a source that triggers if @cancellable is cancelled and
     803                 :            :  * calls its callback of type #GCancellableSourceFunc. This is
     804                 :            :  * primarily useful for attaching to another (non-cancellable) source
     805                 :            :  * with g_source_add_child_source() to add cancellability to it.
     806                 :            :  *
     807                 :            :  * For convenience, you can call this with a %NULL #GCancellable,
     808                 :            :  * in which case the source will never trigger.
     809                 :            :  *
     810                 :            :  * The new #GSource will hold a reference to the #GCancellable.
     811                 :            :  *
     812                 :            :  * Returns: (transfer full): the new #GSource.
     813                 :            :  *
     814                 :            :  * Since: 2.28
     815                 :            :  */
     816                 :            : GSource *
     817                 :     123058 : g_cancellable_source_new (GCancellable *cancellable)
     818                 :            : {
     819                 :            :   GSource *source;
     820                 :            :   GCancellableSource *cancellable_source;
     821                 :            : 
     822                 :     123058 :   source = g_source_new (&cancellable_source_funcs, sizeof (GCancellableSource));
     823                 :     123058 :   g_source_set_static_name (source, "GCancellable");
     824                 :     123058 :   g_source_set_dispose_function (source, cancellable_source_dispose);
     825                 :     123058 :   cancellable_source = (GCancellableSource *)source;
     826                 :            : 
     827         [ +  - ]:     123058 :   if (cancellable)
     828                 :            :     {
     829                 :     123058 :       cancellable_source->cancellable = g_object_ref (cancellable);
     830                 :            : 
     831                 :            :       /* We intentionally don't use g_cancellable_connect() here,
     832                 :            :        * because we don't want the "at most once" behavior.
     833                 :            :        */
     834                 :     123058 :       cancellable_source->cancelled_handler =
     835                 :     123058 :         g_signal_connect (cancellable, "cancelled",
     836                 :            :                           G_CALLBACK (cancellable_source_cancelled),
     837                 :            :                           source);
     838         [ +  + ]:     123058 :       if (g_cancellable_is_cancelled (cancellable))
     839                 :         27 :         g_source_set_ready_time (source, 0);
     840                 :            :     }
     841                 :            : 
     842                 :     123058 :   return source;
     843                 :            : }

Generated by: LCOV version 1.14