[Xfce4-commits] <thunar:master> Optimize supported type comparison in the thumbnailer.
Nick Schermer
noreply at xfce.org
Tue Sep 25 19:02:01 CEST 2012
Updating branch refs/heads/master
to bde6706f2ccc9d04f31b7804c00b88aff3c17918 (commit)
from f31046c1d802213c966b75c8deb499d2af55f448 (commit)
commit bde6706f2ccc9d04f31b7804c00b88aff3c17918
Author: Nick Schermer <nick at xfce.org>
Date: Tue Sep 25 18:41:23 2012 +0200
Optimize supported type comparison in the thumbnailer.
Traversing the list was very inefficient, so go for the lazy
way and prepare a hash table with mimetypes and the supported
schemes in an array. This way it becomes much faster to
find out if a file is supported by the thumbnailer.
thunar/thunar-thumbnailer.c | 179 ++++++++++++++++++++++++++++++-------------
1 files changed, 124 insertions(+), 55 deletions(-)
diff --git a/thunar/thunar-thumbnailer.c b/thunar/thunar-thumbnailer.c
index 1b7cde9..c6298ef 100644
--- a/thunar/thunar-thumbnailer.c
+++ b/thunar/thunar-thumbnailer.c
@@ -148,10 +148,8 @@ struct _ThunarThumbnailer
GMutex *lock;
- /* cached arrays of URI schemes and MIME types for which thumbnails
- * can be generated */
- gchar **supported_schemes;
- gchar **supported_types;
+ /* cached MIME types -> URI schemes for which thumbs can be generated */
+ GHashTable *supported;
/* last ThunarThumbnailer request ID */
guint last_request;
@@ -297,9 +295,9 @@ thunar_thumbnailer_finalize (GObject *object)
if (thumbnailer->thumbnailer_proxy != NULL)
g_object_unref (thumbnailer->thumbnailer_proxy);
- /* free the cached URI schemes and MIME types array */
- g_strfreev (thumbnailer->supported_schemes);
- g_strfreev (thumbnailer->supported_types);
+ /* free the cached URI schemes and MIME types table */
+ if (thumbnailer->supported != NULL)
+ g_hash_table_unref (thumbnailer->supported);
/* release the thumbnailer lock */
g_mutex_unlock (thumbnailer->lock);
@@ -370,6 +368,102 @@ thunar_thumbnailer_init_thumbnailer_proxy (ThunarThumbnailer *thumbnailer,
+static gint
+thunar_thumbnailer_file_schemes_compare (gconstpointer a,
+ gconstpointer b)
+{
+ const gchar *scheme_a = *(gconstpointer *) a;
+ const gchar *scheme_b = *(gconstpointer *) b;
+
+ /* sort file before other schemes */
+ if (strcmp (scheme_a, "file") == 0)
+ return -1;
+ if (strcmp (scheme_b, "file") == 0)
+ return 1;
+
+ /* sort trash before other schemes */
+ if (strcmp (scheme_a, "trash") == 0)
+ return -1;
+ if (strcmp (scheme_b, "trash") == 0)
+ return 1;
+
+ /* other order is just fine */
+ return 0;
+}
+
+
+
+static void
+thunar_thumbnailer_file_sort_schemes (gpointer mime_type,
+ gpointer schemes,
+ gpointer user_data)
+{
+ g_ptr_array_sort (schemes, thunar_thumbnailer_file_schemes_compare);
+}
+
+
+
+static void
+thunar_thumbnailer_get_supported_types (ThunarThumbnailer *thumbnailer)
+{
+ guint n;
+ gchar **schemes = NULL;
+ gchar **types = NULL;
+ GPtrArray *schemes_array;
+
+ _thunar_return_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer));
+ _thunar_return_if_fail (DBUS_IS_G_PROXY (thumbnailer->thumbnailer_proxy));
+ _thunar_return_if_fail (!g_mutex_trylock (thumbnailer->lock));
+
+ /* leave if there already is a hash table */
+ if (thumbnailer->supported != NULL)
+ return;
+
+ /* prepare table */
+ thumbnailer->supported = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free,
+ (GDestroyNotify) g_ptr_array_unref);
+
+ /* request the supported types from the thumbnailer D-Bus service. We only do
+ * this once, so using a non-async call should be ok */
+ thunar_thumbnailer_proxy_get_supported (thumbnailer->thumbnailer_proxy,
+ &schemes, &types,
+ NULL);
+
+ if (G_LIKELY (schemes != NULL && types != NULL))
+ {
+ /* combine content types and uri schemes */
+ for (n = 0; types[n] != NULL; ++n)
+ {
+ schemes_array = g_hash_table_lookup (thumbnailer->supported, types[n]);
+ if (G_UNLIKELY (schemes_array == NULL))
+ {
+ /* create an array for the uri schemes this content type supports */
+ schemes_array = g_ptr_array_new_with_free_func (g_free);
+ g_ptr_array_add (schemes_array, schemes[n]);
+ g_hash_table_insert (thumbnailer->supported, types[n], schemes_array);
+ }
+ else
+ {
+ /* add the uri scheme to the array of the content type */
+ g_ptr_array_add (schemes_array, schemes[n]);
+
+ /* cleanup */
+ g_free (types[n]);
+ }
+ }
+
+ /* remove arrays, we stole the values */
+ g_free (types);
+ g_free (schemes);
+
+ /* sort array to optimize for local files */
+ g_hash_table_foreach (thumbnailer->supported, thunar_thumbnailer_file_sort_schemes, NULL);
+ }
+}
+
+
+
static gboolean
thunar_thumbnailer_file_is_supported (ThunarThumbnailer *thumbnailer,
ThunarFile *file)
@@ -377,64 +471,36 @@ thunar_thumbnailer_file_is_supported (ThunarThumbnailer *thumbnailer,
const gchar *content_type;
gboolean supported = FALSE;
guint n;
+ GPtrArray *schemes_array;
+ const gchar *scheme;
_thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), FALSE);
_thunar_return_val_if_fail (THUNAR_IS_FILE (file), FALSE);
-
- /* acquire the thumbnailer lock */
- g_mutex_lock (thumbnailer->lock);
-
- /* no types are supported if we don't have a thumbnailer */
- if (thumbnailer->thumbnailer_proxy == NULL)
- {
- /* release the thumbnailer lock */
- g_mutex_unlock (thumbnailer->lock);
- return FALSE;
- }
+ _thunar_return_val_if_fail (DBUS_IS_G_PROXY (thumbnailer->thumbnailer_proxy), FALSE);
+ _thunar_return_val_if_fail (thumbnailer->supported != NULL, FALSE);
+ _thunar_return_val_if_fail (!g_mutex_trylock (thumbnailer->lock), FALSE);
/* determine the content type of the passed file */
content_type = thunar_file_get_content_type (file);
/* abort if the content type is unknown */
if (content_type == NULL)
- {
- /* release the thumbnailer lock */
- g_mutex_unlock (thumbnailer->lock);
- return FALSE;
- }
-
- /* request the supported types on demand */
- if (thumbnailer->supported_schemes == NULL
- || thumbnailer->supported_types == NULL)
- {
- /* request the supported types from the thumbnailer D-Bus service. We only do
- * this once, so using a non-async call should be ok */
- thunar_thumbnailer_proxy_get_supported (thumbnailer->thumbnailer_proxy,
- &thumbnailer->supported_schemes,
- &thumbnailer->supported_types,
- NULL);
- }
+ return FALSE;
- /* check if we have supported URI schemes and MIME types now */
- if (thumbnailer->supported_schemes != NULL
- && thumbnailer->supported_types != NULL)
+ /* lazy lookup the content type, no difficult parent type matching here */
+ schemes_array = g_hash_table_lookup (thumbnailer->supported, content_type);
+ if (schemes_array != NULL)
{
- /* go through all the URI schemes we support */
- for (n = 0; !supported && thumbnailer->supported_schemes[n] != NULL; ++n)
+ /* go through all the URI schemes this type supports */
+ for (n = 0; !supported && n < schemes_array->len; ++n)
{
/* check if the file has the current URI scheme */
- if (thunar_file_has_uri_scheme (file, thumbnailer->supported_schemes[n]))
- {
- /* check if the type of the file is a subtype of the supported type */
- if (g_content_type_is_a (content_type, thumbnailer->supported_types[n]))
- supported = TRUE;
- }
+ scheme = g_ptr_array_index (schemes_array, n);
+ if (thunar_file_has_uri_scheme (file, scheme))
+ supported = TRUE;
}
}
- /* release the thumbnailer lock */
- g_mutex_unlock (thumbnailer->lock);
-
return supported;
}
@@ -768,7 +834,7 @@ thunar_thumbnailer_queue_files (ThunarThumbnailer *thumbnailer,
GList *lp;
GList *supported_files = NULL;
guint n;
- guint n_items;
+ guint n_items = 0;
#endif
_thunar_return_val_if_fail (THUNAR_IS_THUMBNAILER (thumbnailer), FALSE);
@@ -785,8 +851,8 @@ thunar_thumbnailer_queue_files (ThunarThumbnailer *thumbnailer,
return FALSE;
}
- /* release the thumbnailer lock */
- g_mutex_unlock (thumbnailer->lock);
+ /* make sure there is a hash table with supported files */
+ thunar_thumbnailer_get_supported_types (thumbnailer);
/* collect all supported files from the list that are neither in the
* about to be queued (wait queue), nor already queued, nor already
@@ -794,11 +860,14 @@ thunar_thumbnailer_queue_files (ThunarThumbnailer *thumbnailer,
for (lp = g_list_last (files); lp != NULL; lp = lp->prev)
{
if (thunar_thumbnailer_file_is_supported (thumbnailer, lp->data))
- supported_files = g_list_prepend (supported_files, lp->data);
+ {
+ supported_files = g_list_prepend (supported_files, lp->data);
+ n_items++;
+ }
}
- /* determine how many URIs are in the wait queue */
- n_items = g_list_length (supported_files);
+ /* release the thumbnailer lock */
+ g_mutex_unlock (thumbnailer->lock);
/* check if we have any supported files */
if (n_items > 0)
More information about the Xfce4-commits
mailing list