[Xfce4-commits] <thunar:master> Cache pixmaps on the ThunarFile and drop ring buffer.

Nick Schermer noreply at xfce.org
Tue Oct 30 22:06:12 CET 2012


Updating branch refs/heads/master
         to 0fcc2f2dff3303f34d4a80dd691f67efa118e1e3 (commit)
       from 2d8c5db66116b8e72dacdf222fd2c1df65cac330 (commit)

commit 0fcc2f2dff3303f34d4a80dd691f67efa118e1e3
Author: Nick Schermer <nick at xfce.org>
Date:   Tue Oct 30 21:22:51 2012 +0100

    Cache pixmaps on the ThunarFile and drop ring buffer.
    
    This is far more efficient since it also works for
    thumbnails. When the theme changes, the data is automatically
    removed and reloaded.

 thunar/thunar-icon-factory.c |  147 +++++++++++++++++++++---------------------
 1 files changed, 74 insertions(+), 73 deletions(-)

diff --git a/thunar/thunar-icon-factory.c b/thunar/thunar-icon-factory.c
index ec12bfe..12dd602 100644
--- a/thunar/thunar-icon-factory.c
+++ b/thunar/thunar-icon-factory.c
@@ -38,11 +38,8 @@
 
 
 
-/* the timeout until the sweeper is run (in ms) */
-#define THUNAR_ICON_FACTORY_SWEEP_TIMEOUT (30 * 1000)
-
-/* the maximum length of the recently used list */
-#define MAX_RECENTLY (32u)
+/* the timeout until the sweeper is run (in seconds) */
+#define THUNAR_ICON_FACTORY_SWEEP_TIMEOUT (30)
 
 
 
@@ -83,8 +80,6 @@ static GdkPixbuf *thunar_icon_factory_lookup_icon           (ThunarIconFactory
                                                              const gchar              *name,
                                                              gint                      size,
                                                              gboolean                  wants_default);
-static void       thunar_icon_factory_mark_recently_used    (ThunarIconFactory        *factory,
-                                                             GdkPixbuf                *pixbuf);
 static guint      thunar_icon_key_hash                      (gconstpointer             data);
 static gboolean   thunar_icon_key_equal                     (gconstpointer             a,
                                                              gconstpointer             b);
@@ -105,9 +100,6 @@ struct _ThunarIconFactory
 
   ThunarPreferences *preferences;
 
-  GdkPixbuf         *recently[MAX_RECENTLY];  /* ring buffer */
-  guint              recently_pos;            /* insert position */
-
   GHashTable        *icon_cache;
 
   GtkIconTheme      *icon_theme;
@@ -117,6 +109,9 @@ struct _ThunarIconFactory
   guint              sweep_timer_id;
 
   gulong             changed_hook_id;
+
+  /* stamp that gets bumped when the theme changes */
+  guint              theme_stamp;
 };
 
 struct _ThunarIconKey
@@ -125,9 +120,20 @@ struct _ThunarIconKey
   gint   size;
 };
 
+typedef struct
+{
+  ThunarFileIconState   icon_state;
+  ThunarFileThumbState  thumb_state;
+  gint                  icon_size;
+  guint                 stamp;
+  GdkPixbuf            *icon;
+}
+ThunarIconStore;
+
 
 
 static GQuark thunar_icon_factory_quark = 0;
+static GQuark thunar_icon_factory_store_quark = 0;
 
 
 
@@ -140,6 +146,8 @@ thunar_icon_factory_class_init (ThunarIconFactoryClass *klass)
 {
   GObjectClass *gobject_class;
 
+  thunar_icon_factory_store_quark = g_quark_from_static_string ("thunar-icon-factory-store");
+
   gobject_class = G_OBJECT_CLASS (klass);
   gobject_class->dispose = thunar_icon_factory_dispose;
   gobject_class->finalize = thunar_icon_factory_finalize;
@@ -188,7 +196,8 @@ thunar_icon_factory_init (ThunarIconFactory *factory)
                                                          0, thunar_icon_factory_changed, factory, NULL);
 
   /* allocate the hash table for the icon cache */
-  factory->icon_cache = g_hash_table_new_full (thunar_icon_key_hash, thunar_icon_key_equal, thunar_icon_key_free, g_object_unref);
+  factory->icon_cache = g_hash_table_new_full (thunar_icon_key_hash, thunar_icon_key_equal,
+                                               thunar_icon_key_free, g_object_unref);
 }
 
 
@@ -212,15 +221,9 @@ static void
 thunar_icon_factory_finalize (GObject *object)
 {
   ThunarIconFactory *factory = THUNAR_ICON_FACTORY (object);
-  guint              n;
 
   _thunar_return_if_fail (THUNAR_IS_ICON_FACTORY (factory));
 
-  /* clear the recently used list */
-  for (n = 0; n < MAX_RECENTLY; ++n)
-    if (G_LIKELY (factory->recently[n] != NULL))
-      g_object_unref (G_OBJECT (factory->recently[n]));
-
   /* clear the icon cache hash table */
   g_hash_table_destroy (factory->icon_cache);
 
@@ -297,18 +300,12 @@ thunar_icon_factory_changed (GSignalInvocationHint *ihint,
                              gpointer               user_data)
 {
   ThunarIconFactory *factory = THUNAR_ICON_FACTORY (user_data);
-  guint              n;
-
-  /* drop all items from the recently used list */
-  for (n = 0; n < MAX_RECENTLY; ++n)
-    if (G_LIKELY (factory->recently[n] != NULL))
-      {
-        g_object_unref (G_OBJECT (factory->recently[n]));
-        factory->recently[n] = NULL;
-      }
 
   /* drop all items from the icon cache */
-  g_hash_table_foreach_remove (factory->icon_cache, (GHRFunc) exo_noop_true, NULL);
+  g_hash_table_remove_all (factory->icon_cache);
+
+  /* bump the stamp so all file icons are reloaded */
+  factory->theme_stamp++;
 
   /* keep the emission hook alive */
   return TRUE;
@@ -525,48 +522,15 @@ thunar_icon_factory_lookup_icon (ThunarIconFactory *factory,
       g_hash_table_insert (factory->icon_cache, key, pixbuf);
     }
 
-  /* add the icon to the recently used list */
-  thunar_icon_factory_mark_recently_used (factory, pixbuf);
-
-  return g_object_ref (G_OBJECT (pixbuf));
-}
-
-
-
-static void
-thunar_icon_factory_mark_recently_used (ThunarIconFactory *factory,
-                                        GdkPixbuf         *pixbuf)
-{
-  guint n;
-
-  _thunar_return_if_fail (THUNAR_IS_ICON_FACTORY (factory));
-  _thunar_return_if_fail (GDK_IS_PIXBUF (pixbuf));
-
-  /* check if the icon is already on the list */
-  for (n = 0; n < MAX_RECENTLY; ++n)
-    if (G_UNLIKELY (factory->recently[n] == pixbuf))
-      return;
-
-  /* ditch the previous item on the current insert position,
-   * which - if present - is the oldest item in the list.
-   */
-  if (G_LIKELY (factory->recently[factory->recently_pos] != NULL))
-    g_object_unref (G_OBJECT (factory->recently[factory->recently_pos]));
-
-  /* insert the new pixbuf into the list */
-  factory->recently[factory->recently_pos] = pixbuf;
-  g_object_ref (G_OBJECT (pixbuf));
-
-  /* advance the insert position */
-  factory->recently_pos = (factory->recently_pos + 1) % MAX_RECENTLY;
-
   /* schedule the sweeper */
   if (G_UNLIKELY (factory->sweep_timer_id == 0))
     {
-      factory->sweep_timer_id = g_timeout_add_full (G_PRIORITY_LOW, THUNAR_ICON_FACTORY_SWEEP_TIMEOUT,
-                                                    thunar_icon_factory_sweep_timer, factory,
-                                                    thunar_icon_factory_sweep_timer_destroy);
+      factory->sweep_timer_id = g_timeout_add_seconds_full (G_PRIORITY_LOW, THUNAR_ICON_FACTORY_SWEEP_TIMEOUT,
+                                                            thunar_icon_factory_sweep_timer, factory,
+                                                            thunar_icon_factory_sweep_timer_destroy);
     }
+
+  return g_object_ref (G_OBJECT (pixbuf));
 }
 
 
@@ -616,6 +580,18 @@ thunar_icon_key_free (gpointer data)
 
 
 
+static void
+thunar_icon_store_free (gpointer data)
+{
+  ThunarIconStore *store = data;
+
+  if (store->icon != NULL)
+    g_object_unref (store->icon);
+  g_slice_free (ThunarIconStore, store);
+}
+
+
+
 static GdkPixbuf*
 thunar_icon_factory_load_fallback (ThunarIconFactory *factory,
                                    gint               size)
@@ -736,7 +712,7 @@ thunar_icon_factory_load_icon (ThunarIconFactory        *factory,
   /* cannot happen unless there's no XSETTINGS manager
    * for the default screen, but just in case...
    */
-  if (G_UNLIKELY (name == NULL || *name == '\0'))
+  if (G_UNLIKELY (exo_str_is_empty (name)))
     {
       /* check if the caller will happly accept the fallback icon */
       if (G_LIKELY (wants_default))
@@ -769,18 +745,30 @@ thunar_icon_factory_load_file_icon (ThunarIconFactory  *factory,
                                     ThunarFileIconState icon_state,
                                     gint                icon_size)
 {
-  GInputStream *stream;
-  GtkIconInfo  *icon_info;
-  const gchar  *thumbnail_path;
-  GdkPixbuf    *icon = NULL;
-  GIcon        *gicon;
-  gchar        *icon_name;
-  const gchar  *custom_icon;
+  GInputStream    *stream;
+  GtkIconInfo     *icon_info;
+  const gchar     *thumbnail_path;
+  GdkPixbuf       *icon = NULL;
+  GIcon           *gicon;
+  gchar           *icon_name;
+  const gchar     *custom_icon;
+  ThunarIconStore *store;
 
   _thunar_return_val_if_fail (THUNAR_IS_ICON_FACTORY (factory), NULL);
   _thunar_return_val_if_fail (THUNAR_IS_FILE (file), NULL);
   _thunar_return_val_if_fail (icon_size > 0, NULL);
 
+  /* check if we have a stored icon on the file and it is still valid */
+  store = g_object_get_qdata (G_OBJECT (file), thunar_icon_factory_store_quark);
+  if (store != NULL
+      && store->icon_state == icon_state
+      && store->icon_size == icon_size
+      && store->stamp == factory->theme_stamp
+      && store->thumb_state == thunar_file_get_thumb_state (file))
+    {
+      return g_object_ref (store->icon);
+    }
+
   /* check if we have a custom icon for this file */
   custom_icon = thunar_file_get_custom_icon (file);
   if (custom_icon != NULL)
@@ -863,5 +851,18 @@ thunar_icon_factory_load_file_icon (ThunarIconFactory  *factory,
       g_free (icon_name);
     }
 
+  if (G_LIKELY (icon != NULL))
+    {
+      store = g_slice_new (ThunarIconStore);
+      store->icon_size = icon_size;
+      store->icon_state = icon_state;
+      store->stamp = factory->theme_stamp;
+      store->thumb_state = thunar_file_get_thumb_state (file);
+      store->icon = g_object_ref (icon);
+
+      g_object_set_qdata_full (G_OBJECT (file), thunar_icon_factory_store_quark,
+                               store, thunar_icon_store_free);
+    }
+
   return icon;
 }


More information about the Xfce4-commits mailing list