[gegl] buffer: add GeglTile::keep_identity flag



commit e82a3fba40a1a9bbcca2ad3aff4a15e687728a08
Author: Ell <ell_se yahoo com>
Date:   Wed Jan 2 07:21:19 2019 -0500

    buffer: add GeglTile::keep_identity flag
    
    Add a keep_identity flag to GeglTile, which indicates that the
    tile's data pointer's identity must be maintained.  When the flag
    is set, we avoid cloning the tile in gegl_tile_dup(), and rather
    perform a direct copy, since we have to way to unclone the tile
    without changing its data pointer.  Additionally, we avoid trimming
    the tile out of the cache, since the tile storage might copy its
    data and get rid of the tile, returning a new tile, with a
    different data pointer, when re-fetching it.

 gegl/buffer/gegl-buffer-private.h     |  3 +++
 gegl/buffer/gegl-tile-handler-cache.c |  7 ++++++
 gegl/buffer/gegl-tile.c               | 44 ++++++++++++++++++++++++-----------
 3 files changed, 40 insertions(+), 14 deletions(-)
---
diff --git a/gegl/buffer/gegl-buffer-private.h b/gegl/buffer/gegl-buffer-private.h
index 102502322..2d6a3fa9c 100644
--- a/gegl/buffer/gegl-buffer-private.h
+++ b/gegl/buffer/gegl-buffer-private.h
@@ -164,6 +164,9 @@ struct _GeglTile
                                       * therefore can never be owned by a
                                       * single mutable tile)
                                       */
+  guint            keep_identity:1;  /* maintain data pointer identity, rather
+                                      * than data content only
+                                      */
 
   gint             clone_state; /* tile clone/unclone state & spinlock */
   gint            *n_clones;    /* an array of two atomic counters, shared
diff --git a/gegl/buffer/gegl-tile-handler-cache.c b/gegl/buffer/gegl-tile-handler-cache.c
index 2ff894bc9..b7f9d75d5 100644
--- a/gegl/buffer/gegl-tile-handler-cache.c
+++ b/gegl/buffer/gegl-tile-handler-cache.c
@@ -599,6 +599,13 @@ gegl_tile_handler_cache_trim (GeglTileHandlerCache *cache)
           if (tile->ref_count > 1)
             continue;
 
+          /* if we need to maintain the tile's data-pointer identity we can't
+           * remove it from the cache, since the storage might copy the data
+           * and throw the tile away.
+           */
+          if (tile->keep_identity)
+            continue;
+
           /* a set of cloned tiles is only counted once toward the total cache
            * size, so the entire set has to be removed from the cache in order
            * to reclaim the memory of a single tile.  in other words, in a set
diff --git a/gegl/buffer/gegl-tile.c b/gegl/buffer/gegl-tile.c
index 9fd0e8ba1..cea5b1f3f 100644
--- a/gegl/buffer/gegl-tile.c
+++ b/gegl/buffer/gegl-tile.c
@@ -129,30 +129,46 @@ gegl_tile_new_bare (void)
 GeglTile *
 gegl_tile_dup (GeglTile *src)
 {
-  GeglTile *tile = gegl_tile_new_bare_internal ();
+  GeglTile *tile;
 
   g_warn_if_fail (src->lock_count == 0);
   g_warn_if_fail (! src->damage);
 
-  src->clone_state     = CLONE_STATE_CLONED;
+  if (! src->keep_identity)
+    {
+      src->clone_state          = CLONE_STATE_CLONED;
+
+      tile                      = gegl_tile_new_bare_internal ();
+
+      tile->data                = src->data;
+      tile->size                = src->size;
+      tile->is_zero_tile        = src->is_zero_tile;
+      tile->is_global_tile      = src->is_global_tile;
+      tile->clone_state         = CLONE_STATE_CLONED;
+      tile->n_clones            = src->n_clones;
+
+      tile->destroy_notify      = src->destroy_notify;
+      tile->destroy_notify_data = src->destroy_notify_data;
+
+      g_atomic_int_inc (gegl_tile_n_clones (tile));
+    }
+  else
+    {
+      /* we can't clone the source tile if we need to keep its data-pointer
+       * identity, since we have no way of uncloning it without changing its
+       * data pointer.
+       */
+
+      tile = gegl_tile_new (src->size);
 
-  tile->data           = src->data;
-  tile->size           = src->size;
-  tile->is_zero_tile   = src->is_zero_tile;
-  tile->is_global_tile = src->is_global_tile;
-  tile->clone_state    = CLONE_STATE_CLONED;
-  tile->n_clones       = src->n_clones;
+      memcpy (tile->data, src->data, src->size);
+    }
 
-  /* mark the tile as dirty, since, even though the in-memory tile data is
+  /* mark the tile as dirty, since, even though the in-memory tile data may be
    * shared with the source tile, the stored tile data is separate.
    */
   tile->rev++;
 
-  tile->destroy_notify      = src->destroy_notify;
-  tile->destroy_notify_data = src->destroy_notify_data;
-
-  g_atomic_int_inc (gegl_tile_n_clones (tile));
-
   return tile;
 }
 


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