[gnome-photos/wip/rishi/misc-fixes: 5/7] base-item, item-manager: Age out the GEGL objects when unused



commit c30ed9eeb1060a638e2e767401ec23b0794fdc93
Author: Debarshi Ray <debarshir gnome org>
Date:   Tue Dec 15 20:35:13 2015 +0100

    base-item, item-manager: Age out the GEGL objects when unused
    
    We were never dropping the GEGL resources during the lifetime of the
    process, which is wasteful. Once a BaseItem has not been the active
    object for a certain period of time, we should drop them.

 src/photos-base-item.c    |   41 +++++++++++++++++++++++
 src/photos-base-item.h    |    4 ++
 src/photos-item-manager.c |   81 +++++++++++++++++++++++++++++++++++++++++++++
 src/photos-utils.h        |    5 +++
 4 files changed, 131 insertions(+), 0 deletions(-)
---
diff --git a/src/photos-base-item.c b/src/photos-base-item.c
index fa5bb64..63a1502 100644
--- a/src/photos-base-item.c
+++ b/src/photos-base-item.c
@@ -98,6 +98,7 @@ struct _PhotosBaseItemPrivate
   gdouble iso_speed;
   gint64 date_created;
   gint64 height;
+  gint64 last_active;
   gint64 mtime;
   gint64 width;
 };
@@ -1458,6 +1459,7 @@ photos_base_item_init (PhotosBaseItem *self)
   g_mutex_init (&priv->mutex);
 
   priv->sel_cntrlr = photos_selection_controller_dup_singleton ();
+  priv->last_active = -1;
 }
 
 
@@ -1943,6 +1945,18 @@ photos_base_item_is_favorite (PhotosBaseItem *self)
 
 
 void
+photos_base_item_last_active_update (PhotosBaseItem *self)
+{
+  PhotosBaseItemPrivate *priv = self->priv;
+
+  if (priv->collection)
+    return;
+
+  priv->last_active = g_get_monotonic_time ();
+}
+
+
+void
 photos_base_item_load_async (PhotosBaseItem *self,
                              GCancellable *cancellable,
                              GAsyncReadyCallback callback,
@@ -1959,6 +1973,8 @@ photos_base_item_load_async (PhotosBaseItem *self,
   task = g_task_new (self, cancellable, callback, user_data);
   g_task_set_source_tag (task, photos_base_item_load_async);
 
+  priv->last_active = 0;
+
   if (priv->pipeline != NULL)
     {
       GeglNode *graph;
@@ -2338,3 +2354,28 @@ photos_base_item_trash (PhotosBaseItem *self)
   photos_delete_item_job_run (job, NULL, NULL);
   g_object_unref (job);
 }
+
+
+void
+photos_base_item_unload (PhotosBaseItem *self)
+{
+  PhotosBaseItemPrivate *priv = self->priv;
+  gint64 now;
+
+  if (priv->last_active <= 0)
+    return;
+
+  now = g_get_monotonic_time ();
+  if (now - priv->last_active < PHOTOS_ITEM_UNLOAD_TIMEOUT * 1000000)
+    return;
+
+  priv->last_active = -1;
+
+  priv->buffer_sink = NULL;
+  priv->buffer_source = NULL;
+  priv->load = NULL;
+  g_clear_object (&priv->edit_graph);
+  g_clear_object (&priv->load_graph);
+  g_clear_object (&priv->pipeline);
+  g_clear_object (&priv->processor);
+}
diff --git a/src/photos-base-item.h b/src/photos-base-item.h
index 922fb51..4b20668 100644
--- a/src/photos-base-item.h
+++ b/src/photos-base-item.h
@@ -172,6 +172,8 @@ gboolean            photos_base_item_is_collection           (PhotosBaseItem *se
 
 gboolean            photos_base_item_is_favorite             (PhotosBaseItem *self);
 
+void                photos_base_item_last_active_update      (PhotosBaseItem *self);
+
 void                photos_base_item_load_async              (PhotosBaseItem *self,
                                                               GCancellable *cancellable,
                                                               GAsyncReadyCallback callback,
@@ -251,6 +253,8 @@ void                photos_base_item_thumbnailing_stop       (void);
 
 void                photos_base_item_trash                   (PhotosBaseItem *self);
 
+void                photos_base_item_unload                  (PhotosBaseItem *self);
+
 G_END_DECLS
 
 #endif /* PHOTOS_BASE_ITEM_H */
diff --git a/src/photos-item-manager.c b/src/photos-item-manager.c
index 4f4010a..11276cb 100644
--- a/src/photos-item-manager.c
+++ b/src/photos-item-manager.c
@@ -56,6 +56,8 @@ struct _PhotosItemManager
   PhotosTrackerChangeMonitor *monitor;
   PhotosWindowMode mode;
   gboolean fullscreen;
+  gboolean unload_queue_again;
+  guint unload_timeout_id;
 };
 
 struct _PhotosItemManagerClass
@@ -89,6 +91,9 @@ G_DEFINE_TYPE (PhotosItemManager, photos_item_manager, PHOTOS_TYPE_BASE_MANAGER)
 EGG_DEFINE_COUNTER (instances, "PhotosItemManager", "Instances", "Number of PhotosItemManager instances");
 
 
+static void photos_item_manager_unload_queue (PhotosItemManager *self);
+
+
 static void
 photos_item_manager_add_object (PhotosBaseManager *mngr, GObject *object)
 {
@@ -269,6 +274,19 @@ photos_item_manager_item_load (GObject *source_object, GAsyncResult *res, gpoint
 
 
 static void
+photos_item_manager_last_active_update (PhotosItemManager *self)
+{
+  PhotosBaseItem *item;
+
+  item = PHOTOS_BASE_ITEM (photos_base_manager_get_active_object (PHOTOS_BASE_MANAGER (self)));
+  if (item == NULL)
+    return;
+
+  photos_base_item_last_active_update (item);
+}
+
+
+static void
 photos_item_manager_remove_object_by_id (PhotosBaseManager *mngr, const gchar *id)
 {
   PhotosItemManager *self = PHOTOS_ITEM_MANAGER (mngr);
@@ -288,6 +306,46 @@ photos_item_manager_remove_object_by_id (PhotosBaseManager *mngr, const gchar *i
 }
 
 
+static gboolean
+photos_item_manager_unload_timeout (gpointer user_data)
+{
+  PhotosItemManager *self = PHOTOS_ITEM_MANAGER (user_data);
+  GHashTable *items;
+  GHashTableIter iter;
+  PhotosBaseItem *item;
+
+  self->unload_timeout_id = 0;
+
+  items = photos_base_manager_get_objects (PHOTOS_BASE_MANAGER (self));
+  g_hash_table_iter_init (&iter, items);
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &item))
+    photos_base_item_unload (item);
+
+  if (self->unload_queue_again)
+    {
+      self->unload_queue_again = FALSE;
+      photos_item_manager_unload_queue (self);
+    }
+
+  return G_SOURCE_REMOVE;
+}
+
+
+static void
+photos_item_manager_unload_queue (PhotosItemManager *self)
+{
+  if (self->unload_timeout_id != 0)
+    {
+      self->unload_queue_again = TRUE;
+      return;
+    }
+
+  self->unload_timeout_id = g_timeout_add_seconds (PHOTOS_ITEM_UNLOAD_TIMEOUT,
+                                                   photos_item_manager_unload_timeout,
+                                                   self);
+}
+
+
 static void
 photos_item_manager_update_fullscreen (PhotosItemManager *self)
 {
@@ -366,6 +424,8 @@ photos_item_manager_set_active_object (PhotosBaseManager *manager, GObject *obje
       start_loading = TRUE;
     }
 
+  photos_item_manager_last_active_update (self);
+
   ret_val = PHOTOS_BASE_MANAGER_CLASS (photos_item_manager_parent_class)->set_active_object (manager, 
object);
   /* We have already eliminated the possibility of failure. */
   g_assert (ret_val == TRUE);
@@ -402,6 +462,8 @@ photos_item_manager_set_active_object (PhotosBaseManager *manager, GObject *obje
       g_assert (active_item != (GObject *) self->active_collection);
     }
 
+  photos_item_manager_unload_queue (self);
+
  out:
   return ret_val;
 }
@@ -420,6 +482,12 @@ photos_item_manager_dispose (GObject *object)
       self->collection_path = NULL;
     }
 
+  if (self->unload_timeout_id != 0)
+    {
+      g_source_remove (self->unload_timeout_id);
+      self->unload_timeout_id = 0;
+    }
+
   g_clear_pointer (&self->collections, (GDestroyNotify) g_hash_table_unref);
   g_clear_object (&self->loader_cancellable);
   g_clear_object (&self->active_collection);
@@ -575,9 +643,12 @@ photos_item_manager_activate_previous_collection (PhotosItemManager *self)
     g_object_ref (collection);
   self->active_collection = PHOTOS_BASE_ITEM (collection);
 
+  photos_item_manager_last_active_update (self);
+
   PHOTOS_BASE_MANAGER_CLASS (photos_item_manager_parent_class)
     ->set_active_object (PHOTOS_BASE_MANAGER (self), (GObject *) collection);
 
+  photos_item_manager_unload_queue (self);
   g_signal_emit (self, signals[ACTIVE_COLLECTION_CHANGED], 0, self->active_collection);
 
   g_clear_object (&collection);
@@ -740,8 +811,12 @@ photos_mode_controller_go_back (PhotosModeController *self)
   if (old_mode == PHOTOS_WINDOW_MODE_PREVIEW)
     {
       self->load_state = PHOTOS_LOAD_STATE_NONE;
+      photos_item_manager_last_active_update (self);
+
       PHOTOS_BASE_MANAGER_CLASS (photos_item_manager_parent_class)
         ->set_active_object (PHOTOS_BASE_MANAGER (self), (GObject *) self->active_collection);
+
+      photos_item_manager_unload_queue (self);
     }
   else if (old_mode != PHOTOS_WINDOW_MODE_EDIT)
     {
@@ -750,10 +825,12 @@ photos_mode_controller_go_back (PhotosModeController *self)
 
       g_clear_object (&self->active_collection);
       self->load_state = PHOTOS_LOAD_STATE_NONE;
+      photos_item_manager_last_active_update (self);
 
       PHOTOS_BASE_MANAGER_CLASS (photos_item_manager_parent_class)
         ->set_active_object (PHOTOS_BASE_MANAGER (self), NULL);
 
+      photos_item_manager_unload_queue (self);
       g_signal_emit (self, signals[ACTIVE_COLLECTION_CHANGED], 0, self->active_collection);
     }
 
@@ -816,9 +893,13 @@ photos_mode_controller_set_window_mode (PhotosModeController *self, PhotosWindow
           active_collection_changed = TRUE;
         }
 
+      photos_item_manager_last_active_update (self);
+
       PHOTOS_BASE_MANAGER_CLASS (photos_item_manager_parent_class)
         ->set_active_object (PHOTOS_BASE_MANAGER (self), NULL);
 
+      photos_item_manager_unload_queue (self);
+
       if (active_collection_changed)
         g_signal_emit (self, signals[ACTIVE_COLLECTION_CHANGED], 0, self->active_collection);
     }
diff --git a/src/photos-utils.h b/src/photos-utils.h
index cc63745..487521d 100644
--- a/src/photos-utils.h
+++ b/src/photos-utils.h
@@ -57,6 +57,11 @@ G_BEGIN_DECLS
   "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#image-category-screenshot";
 #define PHOTOS_EXPORT_SUBPATH "Exports"
 
+enum
+{
+  PHOTOS_ITEM_UNLOAD_TIMEOUT = 10 /* s */
+};
+
 void             photos_utils_border_pixbuf               (GdkPixbuf *pixbuf);
 
 void             photos_utils_buffer_zoom_async           (GeglBuffer *buffer,


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