LCOV - code coverage report
Current view: top level - gio - gcancellable.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 92.7 % 178 165
Test Date: 2024-11-26 05:23:01 Functions: 96.2 % 26 25
Branches: - 0 0

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

Generated by: LCOV version 2.0-1