[gegl] buffer: cache and reuse tile-storages



commit f2bbd06f50959b0bff47b7348727c93962b0f9f0
Author: �yvind Kolås <pippin gimp org>
Date:   Fri Dec 17 17:36:24 2010 +0000

    buffer: cache and reuse tile-storages

 gegl/buffer/gegl-buffer.c       |  134 ++++++++++++++++++++++++++++++---------
 gegl/buffer/gegl-tile-handler.c |    8 ++-
 gegl/gegl-init.c                |    2 +
 3 files changed, 113 insertions(+), 31 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer.c b/gegl/buffer/gegl-buffer.c
index 89baa16..fef5cbf 100644
--- a/gegl/buffer/gegl-buffer.c
+++ b/gegl/buffer/gegl-buffer.c
@@ -1037,6 +1037,110 @@ gegl_buffer_destroy (GeglBuffer *buffer)
   g_object_unref (buffer);
 }
 
+typedef struct TileStorageCacheItem {
+  GeglTileStorage *storage;
+  gboolean         ram;
+  gint             tile_width;
+  gint             tile_height;
+  const void      *babl_fmt;
+} TileStorageCacheItem;
+
+static GStaticMutex storage_cache_mutex = G_STATIC_MUTEX_INIT;
+static GSList *storage_cache = NULL;
+
+/* returns TRUE if it could be done */
+gboolean gegl_tile_storage_cached_release (GeglTileStorage *storage);
+gboolean gegl_tile_storage_cached_release (GeglTileStorage *storage)
+{
+  TileStorageCacheItem *item = g_object_get_data (G_OBJECT (storage), "storage-cache-item");
+
+  if (!item)
+    return FALSE;
+  g_static_mutex_lock (&storage_cache_mutex);
+  storage_cache = g_slist_prepend (storage_cache, item);
+  g_static_mutex_unlock (&storage_cache_mutex);
+  return TRUE;
+}
+
+void gegl_tile_storage_cache_cleanup (void);
+void gegl_tile_storage_cache_cleanup (void)
+{
+  g_static_mutex_lock (&storage_cache_mutex);
+  for (;storage_cache; storage_cache = g_slist_remove (storage_cache, storage_cache->data))
+    {
+      TileStorageCacheItem *item = storage_cache->data;
+      g_object_unref (item->storage);
+    }
+  g_static_mutex_unlock (&storage_cache_mutex);
+}
+
+static GeglTileStorage *
+gegl_tile_storage_new_cached (gint tile_width, gint tile_height,
+                              const void *babl_fmt, gboolean use_ram)
+{
+  GeglTileStorage *storage = NULL;
+  GSList *iter;
+  g_static_mutex_lock (&storage_cache_mutex);
+  for (iter = storage_cache; iter; iter = iter->next)
+    {
+      TileStorageCacheItem *item = iter->data;
+      if (item->babl_fmt == babl_fmt &&
+          item->tile_width == tile_width &&
+          item->tile_height == tile_height &&
+          item->ram == item->ram)
+       {
+         storage = item->storage;
+         storage_cache = g_slist_remove (storage_cache, item);
+         break;
+       }
+    }
+
+  if (!storage)
+    {
+      TileStorageCacheItem *item = g_new0 (TileStorageCacheItem, 1);
+
+      item->tile_width = tile_width;
+      item->tile_height = tile_height;
+      item->babl_fmt = babl_fmt;
+
+      if (use_ram || 
+          !gegl_config()->swap ||
+          g_str_equal (gegl_config()->swap, "RAM") ||
+          g_str_equal (gegl_config()->swap, "ram"))
+        {
+          item->ram = TRUE;
+          storage = gegl_tile_storage_new (tile_width, tile_height, babl_fmt, NULL);
+        }
+      else
+        {
+          static gint no = 1;
+
+          gchar *filename;
+          gchar *path;
+          item->ram = FALSE;
+
+#if 0
+          filename = g_strdup_printf ("GEGL-%i-%s-%i.swap",
+                                      getpid (),
+                                      babl_name ((Babl *) babl_fmt),
+                                      no++);
+#endif
+
+          filename = g_strdup_printf ("%i-%i", getpid(), no);
+          g_atomic_int_inc (&no);
+          path = g_build_filename (gegl_config()->swap, filename, NULL);
+          g_free (filename);
+
+          storage = gegl_tile_storage_new (tile_width, tile_height, babl_fmt, path);
+          g_free (path);
+        }
+      item->storage = storage;
+      g_object_set_data_full (G_OBJECT (storage), "storage-cache-item", item, g_free);
+    }
+
+  g_static_mutex_unlock (&storage_cache_mutex);
+  return storage;
+}
 
 static GeglBuffer *
 gegl_buffer_new_from_format (const void *babl_fmt,
@@ -1051,35 +1155,7 @@ gegl_buffer_new_from_format (const void *babl_fmt,
   GeglTileStorage *tile_storage;
   GeglBuffer  *buffer;
 
-  if (use_ram || 
-      !gegl_config()->swap ||
-      g_str_equal (gegl_config()->swap, "RAM") ||
-      g_str_equal (gegl_config()->swap, "ram"))
-    { 
-      tile_storage = gegl_tile_storage_new (tile_width, tile_height, babl_fmt, NULL);
-    }
-  else
-    {
-      static gint no = 1;
-
-      gchar *filename;
-      gchar *path;
-
-#if 0
-      filename = g_strdup_printf ("GEGL-%i-%s-%i.swap",
-                                  getpid (),
-                                  babl_name ((Babl *) babl_fmt),
-                                  no++);
-#endif
-
-      filename = g_strdup_printf ("%i-%i", getpid(), no);
-      g_atomic_int_inc (&no);
-      path = g_build_filename (gegl_config()->swap, filename, NULL);
-      g_free (filename);
-
-      tile_storage = gegl_tile_storage_new (tile_width, tile_height, babl_fmt, path);
-      g_free (path);
-    }
+  tile_storage = gegl_tile_storage_new_cached (tile_width, tile_height, babl_fmt, use_ram);
 
   buffer = g_object_new (GEGL_TYPE_BUFFER,
                          "source",      tile_storage,
diff --git a/gegl/buffer/gegl-tile-handler.c b/gegl/buffer/gegl-tile-handler.c
index 888e2d2..e2b0642 100644
--- a/gegl/buffer/gegl-tile-handler.c
+++ b/gegl/buffer/gegl-tile-handler.c
@@ -25,7 +25,7 @@
 #include "gegl-tile-source.h"
 #include "gegl-tile-handler.h"
 #include "gegl-tile-handler-chain.h"
-
+#include "gegl-tile-storage.h"
 
 G_DEFINE_TYPE (GeglTileHandler, gegl_tile_handler, GEGL_TYPE_TILE_SOURCE)
 
@@ -35,6 +35,8 @@ enum
   PROP_SOURCE
 };
 
+gboolean gegl_tile_storage_cached_release (GeglTileStorage *storage);
+
 static void
 gegl_tile_handler_dispose (GObject *object)
 {
@@ -42,7 +44,9 @@ gegl_tile_handler_dispose (GObject *object)
 
   if (handler->source != NULL)
     {
-      g_object_unref (handler->source);
+      if (!(GEGL_IS_TILE_STORAGE (handler->source) &&
+	    gegl_tile_storage_cached_release ((void*)handler->source)))
+        g_object_unref (handler->source);
       handler->source = NULL;
     }
 
diff --git a/gegl/gegl-init.c b/gegl/gegl-init.c
index 93a34f4..be718b4 100644
--- a/gegl/gegl-init.c
+++ b/gegl/gegl-init.c
@@ -342,12 +342,14 @@ static void swap_clean (void)
     }
 }
 
+void gegl_tile_storage_cache_cleanup (void);
 
 void
 gegl_exit (void)
 {
   glong timing = gegl_ticks ();
 
+  gegl_tile_storage_cache_cleanup ();
   gegl_tile_cache_destroy ();
   gegl_operation_gtype_cleanup ();
   gegl_extension_handler_cleanup ();



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