[babl] Add a babl_set_destructor



commit c435986318527b8dba3265d963b0e45fedb0d18b
Author: �yvind Kolås <pippin gimp org>
Date:   Sat Jun 26 03:54:53 2010 +0100

    Add a babl_set_destructor
    
    Keep a callback function for each allocation instance, that allows an
    allocation specific callback to be called when the memory segment is
    freed. This makes a valgrind warning go away, most of the time no extra
    memory should be needed since this is likely to fit within the padding.

 babl/babl-format.c |   14 +++++++++++
 babl/babl-image.c  |   12 +++++++++
 babl/babl-memory.c |   66 ++++++++++++++-------------------------------------
 babl/babl-memory.h |   40 ++++++++++++++++---------------
 4 files changed, 65 insertions(+), 67 deletions(-)
---
diff --git a/babl/babl-format.c b/babl/babl-format.c
index 8494d9f..227dab0 100644
--- a/babl/babl-format.c
+++ b/babl/babl-format.c
@@ -24,6 +24,19 @@
 #include "babl-internal.h"
 #include "babl-db.h"
 
+static int babl_format_destruct (void *babl)
+{
+  BablFormat *format = babl;
+  if (format->image_template != NULL)
+    {
+      babl_set_destructor (format->image_template, NULL);
+      /* with no destructor set, the circular reference is no problem */
+      babl_free (format->image_template);
+      format->image_template = NULL;
+    }
+  return 0;
+}
+
 static int
 each_babl_format_destroy (Babl *babl,
                           void *data)
@@ -75,6 +88,7 @@ format_new (const char     *name,
                       sizeof (BablType *) * (components) +
                       sizeof (int) * (components) +
                       sizeof (int) * (components));
+  babl_set_destructor (babl, babl_format_destruct);
 
   babl->format.from_list = NULL;
   babl->format.component = (void *) (((char *) babl) + sizeof (BablFormat));
diff --git a/babl/babl-image.c b/babl/babl-image.c
index f54c87e..ed28c89 100644
--- a/babl/babl-image.c
+++ b/babl/babl-image.c
@@ -22,6 +22,17 @@
 
 #include "babl-internal.h"
 
+static int babl_image_destruct (void *babl)
+{
+  BablFormat *format = BABL (babl)->image.format;
+  if (format && format->image_template == NULL)
+    {
+      format->image_template = babl;
+      return -1; /* this should avoid freeing images created for formats,. */
+    }
+  return 0;
+}
+
 static Babl *
 image_new (BablFormat     *format,
            BablModel      *model,
@@ -43,6 +54,7 @@ image_new (BablFormat     *format,
                        sizeof (void*)          * (components) +
                        sizeof (int)            * (components) +
                        sizeof (int)            * (components));
+  babl_set_destructor (babl, babl_image_destruct);
   babl->image.component = (void*)(((char *)babl)                  + sizeof (BablImage));
   babl->image.sampling  = (void*)(((char *)babl->image.component) + sizeof (BablComponent*) * (components));
   babl->image.type      = (void*)(((char *)babl->image.sampling)  + sizeof (BablSampling*)  * (components));
diff --git a/babl/babl-memory.c b/babl/babl-memory.c
index b228447..df837a3 100644
--- a/babl/babl-memory.c
+++ b/babl/babl-memory.c
@@ -47,6 +47,7 @@ typedef struct
 {
   char  *signature;
   size_t size;
+  int  (*destructor)(void *ptr);
 } BablAllocInfo;
 
 #define BABL_ALIGN     16
@@ -117,6 +118,7 @@ babl_malloc (size_t size)
   *((void **) ret - 1) = ret - BABL_ALLOC - offset;
   BAI (ret)->signature = signature;
   BAI (ret)->size      = size;
+  BAI (ret)->destructor = NULL;
 #if BABL_DEBUG_MEM
   babl_mutex_lock (babl_debug_mutex); 
   mallocs++;
@@ -125,6 +127,16 @@ babl_malloc (size_t size)
   return (void *) (ret);
 }
 
+/* set a callback to be called when the segment is freed.
+ */
+void
+babl_set_destructor (void  *ptr,
+                     int (*destructor)(void *ptr))
+{
+  babl_assert (IS_BAI (ptr));
+  BAI(ptr)->destructor = destructor;
+}
+
 /* Create a duplicate allocation of the same size, note
  * that the exact location of the allocation needs to be
  * passed.
@@ -158,58 +170,16 @@ void
 babl_free (void *ptr,
            ...)
 {
-  /* XXX:
-   *  Extra logic to make the bookeeping of BablImage cached
-   *  templates work out correctly, by using a babl_image_destroy
-   *  and custom destroy functions for babl_format this would be
-   *  avoided and the extra overhead not needed for non image/format
-   *  typed allocations.
-   */
-  if (BABL_IS_BABL (ptr))
-    {
-      switch (BABL (ptr)->instance.class_type)
-        {
-        case BABL_IMAGE:
-          {
-            BablFormat *format = BABL(ptr)->image.format;
-            if (format)
-              {
-                if (format->image_template == NULL)
-                  {
-                    format->image_template = ptr;
-                    return;
-                  }
-                else
-                  {
-                  }
-              }
-          }
-          break;
-        case BABL_FORMAT:
-          {
-            BablFormat *format = ptr;
-            if (format->image_template != NULL)
-              {
-                BAI (format->image_template)->signature = NULL;
-                free_f (BAI (format->image_template));
-#if BABL_DEBUG_MEM
-                babl_mutex_lock (babl_debug_mutex); 
-                frees++;
-                babl_mutex_unlock (babl_debug_mutex); 
-#endif
-              }
-            format->image_template = NULL;
-          }
-          break;
-          default:
-          break;
-        }
-    }
+  functions_sanity ();
   if (!ptr)
     return;
   if (!IS_BAI (ptr))
     babl_fatal ("memory not allocated by babl allocator");
-  functions_sanity ();
+
+  if (BAI (ptr)->destructor)
+    if (BAI (ptr)->destructor (ptr))
+      return; /* bail out on non 0 return from destructor */
+
   BAI (ptr)->signature = NULL;
   free_f (BAI (ptr));
 #if BABL_DEBUG_MEM
diff --git a/babl/babl-memory.h b/babl/babl-memory.h
index b4e0d81..251f0c3 100644
--- a/babl/babl-memory.h
+++ b/babl/babl-memory.h
@@ -24,24 +24,26 @@ typedef void * (* BablMallocFunc) (size_t size);
 typedef void   (* BablFreeFunc)   (void  *ptr);
 
 
-void   babl_set_malloc    (BablMallocFunc malloc_function);
-void   babl_set_free      (BablFreeFunc   free_function);
-int    babl_memory_sanity (void);
-
-void * babl_malloc        (size_t      size);
-void   babl_free          (void       *ptr,
-                           ...);
-void * babl_calloc        (size_t      nmemb,
-                           size_t      size);
-void * babl_realloc       (void       *ptr,
-                           size_t      size);
-
-size_t babl_sizeof        (void       *ptr);
-void * babl_dup           (void       *ptr);
-
-char * babl_strdup        (const char *s);
-char * babl_strcat        (char       *dest,
-                           const char *src);
-
+void   babl_set_malloc     (BablMallocFunc malloc_function);
+void   babl_set_free       (BablFreeFunc   free_function);
+int    babl_memory_sanity  (void);
+
+void * babl_malloc         (size_t      size);
+void   babl_set_destructor (void       *ptr,
+                            int       (*destructor)(void *ptr));
+
+void   babl_free           (void       *ptr,
+                            ...);
+void * babl_calloc         (size_t      nmemb,
+                            size_t      size);
+void * babl_realloc        (void       *ptr,
+                            size_t      size);
+
+size_t babl_sizeof         (void       *ptr);
+void * babl_dup            (void       *ptr);
+
+char * babl_strdup         (const char *s);
+char * babl_strcat         (char       *dest,
+                            const char *src);
 
 #endif



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