More cache updates
authorWim Taymans <wim.taymans@gmail.com>
Mon, 2 Dec 2002 22:39:56 +0000 (22:39 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Mon, 2 Dec 2002 22:39:56 +0000 (22:39 +0000)
Original commit message from CVS:
More cache updates

gst/caches/gstmemcache.c
gst/gstcache.c
gst/gstcache.h

index 81e9acb448c37bb8e9ce8b81997bf25777b961ed..0a599c31748fb663903ff1395e0b7419b9c19b2a 100644 (file)
  * then do a lookup in the Tree to get the required value.
  */
 
-typedef struct _GstMemCacheFormatIndex {
+typedef struct {
   GstFormat     format;
   gint          offset;
   GTree                *tree;
 } GstMemCacheFormatIndex;
 
-typedef struct _GstMemCacheId {
+typedef struct {
   gint                  id;
   GHashTable   *format_index;
 } GstMemCacheId;
@@ -196,11 +196,14 @@ mem_cache_compare (gconstpointer a,
 {
   GstMemCacheFormatIndex *index = user_data;
   gint64 val1, val2;
+  gint64 diff;
 
   val1 = GST_CACHE_ASSOC_VALUE (((GstCacheEntry *)a), index->offset);
   val2 = GST_CACHE_ASSOC_VALUE (((GstCacheEntry *)b), index->offset);
          
-  return val1 - val2;
+  diff = (val2 - val1);
+
+  return (diff == 0 ? 0 : (diff > 0 ? 1 : -1));
 }
 
 static void
@@ -279,6 +282,54 @@ gst_mem_cache_add_entry (GstCache *cache, GstCacheEntry *entry)
   }
 }
 
+typedef struct {
+  gint64                 value;
+  GstMemCacheFormatIndex *index;
+  gboolean               exact;
+  GstCacheEntry         *lower;
+  gint64                 low_diff;
+  GstCacheEntry         *higher;
+  gint64                 high_diff;
+} GstMemCacheSearchData;
+
+static gint
+mem_cache_search (gconstpointer a,
+                 gconstpointer b)
+{
+  GstMemCacheSearchData *data = (GstMemCacheSearchData *) b;
+  GstMemCacheFormatIndex *index = data->index;
+  gint64 val1, val2;
+  gint64 diff;
+
+  val1 = GST_CACHE_ASSOC_VALUE (((GstCacheEntry *)a), index->offset);
+  val2 = data->value;
+         
+  diff = (val1 - val2);
+  if (diff == 0)
+    return 0;
+
+  /* exact matching, don't update low/high */
+  if (data->exact)
+    return (diff > 0 ? 1 : -1);
+
+  if (diff < 0) {
+    if (diff > data->low_diff) {
+      data->low_diff = diff;
+      data->lower = (GstCacheEntry *) a;
+    }
+    diff = -1;
+  }
+  else {
+    if (diff < data->high_diff) {
+      data->high_diff = diff;
+      data->higher = (GstCacheEntry *) a;
+    }
+    diff = 1;
+  }
+
+  return diff;
+}
+
 static GstCacheEntry*
 gst_mem_cache_get_assoc_entry (GstCache *cache, gint id,
                                GstCacheLookupMethod method,
@@ -287,45 +338,44 @@ gst_mem_cache_get_assoc_entry (GstCache *cache, gint id,
                                gpointer user_data)
 {
   GstMemCache *memcache = GST_MEM_CACHE (cache);
-  GList *walk = memcache->associations;
-  GList *next;
-
-  /* FIXME use GTree here */
-  while (walk) {
-    GstCacheEntry *entry = (GstCacheEntry *) walk->data;
-
-    next = g_list_next (walk);
-
-    if (entry->type == GST_CACHE_ENTRY_ASSOCIATION && entry->id == id) {
-      gint64 got;
-
-      if (gst_cache_entry_assoc_map (entry, format, &got)) {
-       if (got == value && method == GST_CACHE_LOOKUP_EXACT)
-          return entry;
-       else {
-          gint64 got_next = G_MININT64;
-          GstCacheEntry *next_entry = NULL;
-
-         if (next != NULL) {
-            next_entry = (GstCacheEntry *) next->data;
-
-           gst_cache_entry_assoc_map (next_entry, format, &got_next);
-         }
-
-          if ((got >= value) && (got_next <= value)) {
-           if (method == GST_CACHE_LOOKUP_BEFORE) 
-             return next_entry;
-           else if (method == GST_CACHE_LOOKUP_AFTER) 
-             return entry;
-         }
-       }
-      }
+  GstMemCacheId *id_index;
+  GstMemCacheFormatIndex *index;
+  GstCacheEntry *entry;
+  GstMemCacheSearchData data;
+
+  id_index = g_hash_table_lookup (memcache->id_index, &id);
+  if (!id_index)
+    return NULL;
+
+  index = g_hash_table_lookup (id_index->format_index, &format);
+  if (!index)
+    return NULL;
+
+  data.value = value;
+  data.index = index;
+  data.exact = (method == GST_CACHE_LOOKUP_EXACT);
+
+  /* setup data for low/high checks if we are not looking 
+   * for an exact match */
+  if (!data.exact) {
+    data.low_diff = G_MININT64;
+    data.lower = NULL;
+    data.high_diff = G_MAXINT64;
+    data.higher = NULL;
+  }
+
+  entry = g_tree_search (index->tree, mem_cache_search, &data);
+
+  /* get the low/high values if we're not exact */
+  if (entry == NULL && !data.exact) { 
+    if (method == GST_CACHE_LOOKUP_BEFORE)
+      entry = data.lower;
+    else if (method == GST_CACHE_LOOKUP_AFTER) {
+      entry = data.higher;
     }
-    
-    walk = next;
   }
 
-  return NULL;
+  return entry;
 }
 
 static gboolean
index 038d429ad6b5376ccdbba377d6d2dc3ccf4ed03c..ae5aba96fc7d51c0b56b7629f4e91c0c95097f77 100644 (file)
@@ -246,6 +246,12 @@ gst_cache_set_resolver (GstCache *cache,
   cache->resolver_user_data = user_data;
 }
 
+void
+gst_cache_entry_free (GstCacheEntry *entry)
+{
+  g_free (entry);
+}
+
 /**
  * gst_cache_add_format:
  * @cache: the cache to add the entry to
@@ -370,12 +376,14 @@ gst_cache_get_writer_id (GstCache *cache, GstObject *writer, gint *id)
  * @...: other format/value pairs or 0 to end the list
  *
  * Associate given format/value pairs with eachother.
+ * Be sure to pass gint64 values to this functions varargs,
+ * you might want to use a gint64 cast to be sure.
  *
  * Returns: a pointer to the newly added entry in the cache.
  */
 GstCacheEntry*
 gst_cache_add_association (GstCache *cache, gint id, GstAssocFlags flags, 
-                               GstFormat format, gint64 value, ...)
+                          GstFormat format, gint64 value, ...)
 {
   va_list args;
   GstCacheAssociation *assoc;
@@ -383,7 +391,7 @@ gst_cache_add_association (GstCache *cache, gint id, GstAssocFlags flags,
   gulong size;
   gint nassocs = 0;
   GstFormat cur_format;
-  gint64 dummy;
+  volatile gint64 dummy;
 
   g_return_val_if_fail (GST_IS_CACHE (cache), NULL);
   g_return_val_if_fail (format != 0, NULL);
@@ -433,6 +441,59 @@ gst_cache_add_association (GstCache *cache, gint id, GstAssocFlags flags,
   return entry;
 }
 
+static gint
+gst_cache_compare_func (gconstpointer a,
+                        gconstpointer b,
+                        gpointer user_data)
+{
+  return a - b;  
+}
+
+GstCacheEntry*
+gst_cache_get_assoc_entry (GstCache *cache, gint id,
+                          GstCacheLookupMethod method,
+                          GstFormat format, gint64 value)
+{
+  g_return_val_if_fail (GST_IS_CACHE (cache), NULL);
+
+  return gst_cache_get_assoc_entry_full (cache, id, method, format, value, 
+                                 gst_cache_compare_func, NULL);
+}
+
+GstCacheEntry*
+gst_cache_get_assoc_entry_full (GstCache *cache, gint id,
+                               GstCacheLookupMethod method,
+                               GstFormat format, gint64 value,
+                               GCompareDataFunc func,
+                               gpointer user_data)
+{
+  g_return_val_if_fail (GST_IS_CACHE (cache), NULL);
+
+  if (CLASS(cache)->get_assoc_entry)
+    return CLASS (cache)->get_assoc_entry (cache, id, method, format, value, func, user_data);
+  
+  return NULL;
+}
+
+gboolean
+gst_cache_entry_assoc_map (GstCacheEntry *entry,
+                          GstFormat format, gint64 *value)
+{
+  gint i;
+
+  g_return_val_if_fail (entry != NULL, FALSE);
+  g_return_val_if_fail (value != NULL, FALSE);
+
+  for (i = 0; i < GST_CACHE_NASSOCS (entry); i++) {
+     if (GST_CACHE_ASSOC_FORMAT (entry, i) == format) {
+       *value = GST_CACHE_ASSOC_VALUE (entry, i);
+       return TRUE;
+     }
+  }
+  return FALSE;
+}
+
+
 static void            gst_cache_factory_class_init            (GstCacheFactoryClass *klass);
 static void            gst_cache_factory_init          (GstCacheFactory *factory);
 
index d1237dcae1c9da5db49fc3b9966445cd7a96db3b..a2acc1e2657a6418753cf0fa8e4365d2962344c4 100644 (file)
@@ -53,6 +53,12 @@ typedef enum {
   GST_CACHE_ENTRY_FORMAT,
 } GstCacheEntryType;
 
+typedef enum {
+  GST_CACHE_LOOKUP_EXACT,
+  GST_CACHE_LOOKUP_BEFORE,
+  GST_CACHE_LOOKUP_AFTER,
+} GstCacheLookupMethod;
+
 #define GST_CACHE_NASSOCS(entry)               ((entry)->data.assoc.nassocs)
 #define GST_CACHE_ASSOC_FLAGS(entry)   ((entry)->data.assoc.flags)
 #define GST_CACHE_ASSOC_FORMAT(entry,i)        ((entry)->data.assoc.assocs[(i)].format)
@@ -149,8 +155,11 @@ struct _GstCacheClass {
   /* abstract methods */
   void         (*add_entry)            (GstCache *cache, GstCacheEntry *entry);
 
-  GstCacheEntry* (*get_entry)          (GstCache *cache); 
-
+  GstCacheEntry* (*get_assoc_entry)    (GstCache *cache, gint id, 
+                                        GstCacheLookupMethod method,
+                                        GstFormat format, gint64 value,
+                                        GCompareDataFunc func,
+                                        gpointer user_data); 
   /* signals */
   void         (*entry_added)          (GstCache *cache, GstCacheEntry *entry);
 };
@@ -181,6 +190,19 @@ GstCacheEntry*             gst_cache_add_object            (GstCache *cache, gint id, gchar *key,
 GstCacheEntry*         gst_cache_add_id                (GstCache *cache, gint id,
                                                         gchar *description); 
 
+GstCacheEntry*         gst_cache_get_assoc_entry       (GstCache *cache, gint id, 
+                                                        GstCacheLookupMethod method,
+                                                        GstFormat format, gint64 value);
+GstCacheEntry*         gst_cache_get_assoc_entry_full  (GstCache *cache, gint id, 
+                                                        GstCacheLookupMethod method,
+                                                        GstFormat format, gint64 value,
+                                                        GCompareDataFunc func,
+                                                        gpointer user_data);
+
+/* working with cache entries */
+void                   gst_cache_entry_free            (GstCacheEntry *entry);
+gboolean               gst_cache_entry_assoc_map       (GstCacheEntry *entry,
+                                                        GstFormat format, gint64 *value);
 /*
  * creating caches
  *