[glib: 6/9] gcancellable: Synchronize access to cancelled flag



commit f975858e866cc6420b00d29d769af0fb1ad3e7e0
Author: Tomasz Miąsko <tomasz miasko gmail com>
Date:   Mon Feb 25 00:00:00 2019 +0000

    gcancellable: Synchronize access to cancelled flag
    
    Synchronize access to cancelled flag of cancellable, which was
    previously access without synchronization in g_cancellable_is_cancelled.
    Use atomic operations instead of existing global mutex, to avoid
    serializing calls to g_cancellable_is_cancelled across all threads.

 gio/gcancellable.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)
---
diff --git a/gio/gcancellable.c b/gio/gcancellable.c
index de6d43495..32605ce02 100644
--- a/gio/gcancellable.c
+++ b/gio/gcancellable.c
@@ -43,7 +43,9 @@ enum {
 
 struct _GCancellablePrivate
 {
-  guint cancelled : 1;
+  /* Atomic so that g_cancellable_is_cancelled does not require holding the mutex. */
+  gboolean cancelled;
+  /* Access to fields below is protected by cancellable_mutex. */
   guint cancelled_running : 1;
   guint cancelled_running_waiting : 1;
 
@@ -269,12 +271,12 @@ g_cancellable_reset (GCancellable *cancellable)
       g_cond_wait (&cancellable_cond, &cancellable_mutex);
     }
 
-  if (priv->cancelled)
+  if (g_atomic_int_get (&priv->cancelled))
     {
       if (priv->wakeup)
         GLIB_PRIVATE_CALL (g_wakeup_acknowledge) (priv->wakeup);
 
-      priv->cancelled = FALSE;
+      g_atomic_int_set (&priv->cancelled, FALSE);
     }
 
   g_mutex_unlock (&cancellable_mutex);
@@ -292,7 +294,7 @@ g_cancellable_reset (GCancellable *cancellable)
 gboolean
 g_cancellable_is_cancelled (GCancellable *cancellable)
 {
-  return cancellable != NULL && cancellable->priv->cancelled;
+  return cancellable != NULL && g_atomic_int_get (&cancellable->priv->cancelled);
 }
 
 /**
@@ -404,7 +406,7 @@ g_cancellable_make_pollfd (GCancellable *cancellable, GPollFD *pollfd)
     {
       cancellable->priv->wakeup = GLIB_PRIVATE_CALL (g_wakeup_new) ();
 
-      if (cancellable->priv->cancelled)
+      if (g_atomic_int_get (&cancellable->priv->cancelled))
         GLIB_PRIVATE_CALL (g_wakeup_signal) (cancellable->priv->wakeup);
     }
 
@@ -440,11 +442,11 @@ g_cancellable_release_fd (GCancellable *cancellable)
     return;
 
   g_return_if_fail (G_IS_CANCELLABLE (cancellable));
-  g_return_if_fail (cancellable->priv->fd_refcount > 0);
 
   priv = cancellable->priv;
 
   g_mutex_lock (&cancellable_mutex);
+  g_assert (priv->fd_refcount > 0);
 
   priv->fd_refcount--;
   if (priv->fd_refcount == 0)
@@ -482,21 +484,20 @@ g_cancellable_cancel (GCancellable *cancellable)
 {
   GCancellablePrivate *priv;
 
-  if (cancellable == NULL ||
-      cancellable->priv->cancelled)
+  if (g_cancellable_is_cancelled (cancellable))
     return;
 
   priv = cancellable->priv;
 
   g_mutex_lock (&cancellable_mutex);
 
-  if (priv->cancelled)
+  if (g_atomic_int_get (&priv->cancelled))
     {
       g_mutex_unlock (&cancellable_mutex);
       return;
     }
 
-  priv->cancelled = TRUE;
+  g_atomic_int_set (&priv->cancelled, TRUE);
   priv->cancelled_running = TRUE;
 
   if (priv->wakeup)
@@ -562,7 +563,7 @@ g_cancellable_connect (GCancellable   *cancellable,
 
   g_mutex_lock (&cancellable_mutex);
 
-  if (cancellable->priv->cancelled)
+  if (g_atomic_int_get (&cancellable->priv->cancelled))
     {
       void (*_callback) (GCancellable *cancellable,
                          gpointer      user_data);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]