[gnome-builder] progress: make IdeProgress thread-safe



commit b0cc8852979e7722364bc62d421bcea5d4dbaa81
Author: Christian Hergert <chergert redhat com>
Date:   Wed Feb 15 14:44:23 2017 -0800

    progress: make IdeProgress thread-safe
    
    This is useful so that we can use an IdeProgress from a thread (such as
    a GTask worker) and have UI updates happen in the Gtk thread. This means
    we need to change the ownership of ide_progress_get_message() to always
    return a copy.
    
    Additionally, we proxy our property notifications to the main thread.

 libide/util/ide-progress.c       |   52 ++++++++++++++++++++++++++++++++------
 libide/util/ide-progress.h       |   24 ++++++++++-------
 libidemm/src/libide_methods.defs |    2 +-
 3 files changed, 59 insertions(+), 19 deletions(-)
---
diff --git a/libide/util/ide-progress.c b/libide/util/ide-progress.c
index a80e547..d546359 100644
--- a/libide/util/ide-progress.c
+++ b/libide/util/ide-progress.c
@@ -20,12 +20,14 @@
 
 #include <glib/gi18n.h>
 
+#include "ide-object.h"
 #include "ide-progress.h"
 
 struct _IdeProgress
 {
   GObject  parent_instance;
 
+  GMutex   mutex;
   gchar   *message;
   gdouble  fraction;
   guint    completed : 1;
@@ -57,19 +59,27 @@ ide_progress_set_completed (IdeProgress *self,
 {
   g_return_if_fail (IDE_IS_PROGRESS (self));
 
+  g_mutex_lock (&self->mutex);
   if (self->completed != completed)
     {
       self->completed = completed;
-      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_COMPLETED]);
+      ide_object_notify_in_main (G_OBJECT (self), properties [PROP_COMPLETED]);
     }
+  g_mutex_unlock (&self->mutex);
 }
 
 gdouble
 ide_progress_get_fraction (IdeProgress *self)
 {
+  gdouble ret;
+
   g_return_val_if_fail (IDE_IS_PROGRESS (self), 0.0);
 
-  return self->fraction;
+  g_mutex_lock (&self->mutex);
+  ret = self->fraction;
+  g_mutex_unlock (&self->mutex);
+
+  return ret;
 }
 
 void
@@ -80,21 +90,29 @@ ide_progress_set_fraction (IdeProgress *self,
   g_return_if_fail (fraction >= 0.0);
   g_return_if_fail (fraction <= 1.0);
 
+  g_mutex_lock (&self->mutex);
   if (self->fraction != fraction)
     {
       self->fraction = fraction;
       if (fraction == 1.0)
         ide_progress_set_completed (self, TRUE);
-      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FRACTION]);
+      ide_object_notify_in_main (G_OBJECT (self), properties [PROP_FRACTION]);
     }
+  g_mutex_unlock (&self->mutex);
 }
 
-const gchar *
+gchar *
 ide_progress_get_message (IdeProgress *self)
 {
+  gchar *ret;
+
   g_return_val_if_fail (IDE_IS_PROGRESS (self), NULL);
 
-  return self->message;
+  g_mutex_lock (&self->mutex);
+  ret = g_strdup (self->message);
+  g_mutex_unlock (&self->mutex);
+
+  return ret;
 }
 
 void
@@ -103,12 +121,28 @@ ide_progress_set_message (IdeProgress *self,
 {
   g_return_if_fail (IDE_IS_PROGRESS (self));
 
-  if (self->message != message)
+  g_mutex_lock (&self->mutex);
+  if (g_strcmp0 (self->message, message) != 0)
     {
       g_free (self->message);
       self->message = g_strdup (message);
-      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_MESSAGE]);
+      ide_object_notify_in_main (G_OBJECT (self), properties [PROP_MESSAGE]);
     }
+  g_mutex_unlock (&self->mutex);
+}
+
+void
+ide_progress_flatpak_progress_callback (const char *status,
+                                        guint       progress,
+                                        gboolean    estimating,
+                                        gpointer    user_data)
+{
+  IdeProgress *self = user_data;
+
+  g_return_if_fail (IDE_IS_PROGRESS (self));
+
+  ide_progress_set_message (self, status);
+  ide_progress_set_fraction (self, (gdouble)progress / 100.0);
 }
 
 /**
@@ -142,6 +176,7 @@ ide_progress_finalize (GObject *object)
   IdeProgress *self = (IdeProgress *)object;
 
   g_clear_pointer (&self->message, g_free);
+  g_mutex_clear (&self->mutex);
 
   G_OBJECT_CLASS (ide_progress_parent_class)->finalize (object);
 }
@@ -165,7 +200,7 @@ ide_progress_get_property (GObject    *object,
       break;
 
     case PROP_MESSAGE:
-      g_value_set_string (value, ide_progress_get_message (self));
+      g_value_take_string (value, ide_progress_get_message (self));
       break;
 
     default:
@@ -234,6 +269,7 @@ ide_progress_class_init (IdeProgressClass *klass)
 static void
 ide_progress_init (IdeProgress *self)
 {
+  g_mutex_init (&self->mutex);
 }
 
 IdeProgress *
diff --git a/libide/util/ide-progress.h b/libide/util/ide-progress.h
index 1064b73..e4cbb91 100644
--- a/libide/util/ide-progress.h
+++ b/libide/util/ide-progress.h
@@ -27,16 +27,20 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (IdeProgress, ide_progress, IDE, PROGRESS, GObject)
 
-IdeProgress *ide_progress_new                    (void);
-gdouble      ide_progress_get_fraction           (IdeProgress *self);
-const gchar *ide_progress_get_message            (IdeProgress *self);
-void         ide_progress_set_fraction           (IdeProgress *self,
-                                                  gdouble      fraction);
-void         ide_progress_set_message            (IdeProgress *self,
-                                                  const gchar *message);
-void         ide_progress_file_progress_callback (goffset      current_num_bytes,
-                                                  goffset      total_num_bytes,
-                                                  gpointer     user_data);
+IdeProgress *ide_progress_new                       (void);
+gdouble      ide_progress_get_fraction              (IdeProgress *self);
+gchar       *ide_progress_get_message               (IdeProgress *self);
+void         ide_progress_set_fraction              (IdeProgress *self,
+                                                     gdouble      fraction);
+void         ide_progress_set_message               (IdeProgress *self,
+                                                     const gchar *message);
+void         ide_progress_flatpak_progress_callback (const char  *status,
+                                                     guint        progress,
+                                                     gboolean     estimating,
+                                                     gpointer     user_data);
+void         ide_progress_file_progress_callback    (goffset      current_num_bytes,
+                                                     goffset      total_num_bytes,
+                                                     gpointer     user_data);
 
 G_END_DECLS
 
diff --git a/libidemm/src/libide_methods.defs b/libidemm/src/libide_methods.defs
index 7aacbc6..d4949e6 100644
--- a/libidemm/src/libide_methods.defs
+++ b/libidemm/src/libide_methods.defs
@@ -3618,7 +3618,7 @@
 (define-method get_message
   (of-object "IdeProgress")
   (c-name "ide_progress_get_message")
-  (return-type "const-gchar*")
+  (return-type "gchar*")
 )
 
 (define-method set_fraction


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