emacs-diffs
[Top][All Lists]
Advanced

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

master 68ec0ffa21: Fix anim_cache garbage collection


From: Lars Ingebrigtsen
Subject: master 68ec0ffa21: Fix anim_cache garbage collection
Date: Mon, 11 Apr 2022 09:18:56 -0400 (EDT)

branch: master
commit 68ec0ffa2181d7e061bc4799798be0b2344d6a6b
Author: Lars Ingebrigtsen <larsi@gnus.org>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Fix anim_cache garbage collection
    
    * src/image.c (struct anim_cache): Move earlier.
    (mark_image_cache): Mark the Lisp_Object in the anim cache.
---
 src/image.c | 174 +++++++++++++++++++++++++++++++-----------------------------
 1 file changed, 89 insertions(+), 85 deletions(-)

diff --git a/src/image.c b/src/image.c
index 4b2a038cc1..f28eb5eb6e 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2782,6 +2782,90 @@ cache_image (struct frame *f, struct image *img)
 }
 
 
+#if defined (HAVE_WEBP) || defined (HAVE_GIF)
+
+/* To speed animations up, we keep a cache (based on EQ-ness of the
+   image spec/object) where we put the animator iterator.  */
+
+struct anim_cache
+{
+  Lisp_Object spec;
+  /* For webp, this will be an iterator, and for libgif, a gif handle.  */
+  void *handle;
+  /* If we need to maintain temporary data of some sort.  */
+  void *temp;
+  /* A function to call to free the handle.  */
+  void (*destructor) (void *);
+  int index, width, height, frames;
+  struct timespec update_time;
+  struct anim_cache *next;
+};
+
+static struct anim_cache *anim_cache = NULL;
+
+static struct anim_cache *
+anim_create_cache (Lisp_Object spec)
+{
+  struct anim_cache *cache = xmalloc (sizeof (struct anim_cache));
+  cache->handle = NULL;
+  cache->temp = NULL;
+
+  cache->index = 0;
+  cache->next = NULL;
+  cache->spec = spec;
+  return cache;
+}
+
+/* Discard cached images that haven't been used for a minute. */
+static void
+anim_prune_animation_cache (void)
+{
+  struct anim_cache **pcache = &anim_cache;
+  struct timespec old = timespec_sub (current_timespec (),
+                                     make_timespec (60, 0));
+
+  while (*pcache)
+    {
+      struct anim_cache *cache = *pcache;
+      if (timespec_cmp (old, cache->update_time) <= 0)
+       pcache = &cache->next;
+      else
+       {
+         if (cache->handle)
+           cache->destructor (cache);
+         if (cache->temp)
+           xfree (cache->temp);
+         *pcache = cache->next;
+         xfree (cache);
+       }
+    }
+}
+
+static struct anim_cache *
+anim_get_animation_cache (Lisp_Object spec)
+{
+  struct anim_cache *cache;
+  struct anim_cache **pcache = &anim_cache;
+
+  anim_prune_animation_cache ();
+
+  while (1)
+    {
+      cache = *pcache;
+      if (! cache)
+       {
+          *pcache = cache = anim_create_cache (spec);
+          break;
+        }
+      if (EQ (spec, cache->spec))
+       break;
+      pcache = &cache->next;
+    }
+
+  cache->update_time = current_timespec ();
+  return cache;
+}
+
 /* Call FN on every image in the image cache of frame F.  Used to mark
    Lisp Objects in the image cache.  */
 
@@ -2808,6 +2892,11 @@ mark_image_cache (struct image_cache *c)
        if (c->images[i])
          mark_image (c->images[i]);
     }
+
+#if defined HAVE_WEBP || defined HAVE_GIF
+  for (struct anim_cache *cache = anim_cache; cache; cache = cache->next)
+    mark_object (cache->spec);
+#endif
 }
 
 
@@ -8433,91 +8522,6 @@ tiff_load (struct frame *f, struct image *img)
 
 
 
-#if defined (HAVE_WEBP) || defined (HAVE_GIF)
-
-/* To speed animations up, we keep a cache (based on EQ-ness of the
-   image spec/object) where we put the animator iterator.  */
-
-struct anim_cache
-{
-  Lisp_Object spec;
-  /* For webp, this will be an iterator, and for libgif, a gif handle.  */
-  void *handle;
-  /* If we need to maintain temporary data of some sort.  */
-  void *temp;
-  /* A function to call to free the handle.  */
-  void (*destructor)(void*);
-  int index, width, height, frames;
-  struct timespec update_time;
-  struct anim_cache *next;
-};
-
-static struct anim_cache *anim_cache = NULL;
-
-static struct anim_cache *
-anim_create_cache (Lisp_Object spec)
-{
-  struct anim_cache *cache = xmalloc (sizeof (struct anim_cache));
-  cache->handle = NULL;
-  cache->temp = NULL;
-
-  cache->index = 0;
-  cache->next = NULL;
-  /* FIXME: Does this need gc protection?  */
-  cache->spec = spec;
-  return cache;
-}
-
-/* Discard cached images that haven't been used for a minute. */
-static void
-anim_prune_animation_cache (void)
-{
-  struct anim_cache **pcache = &anim_cache;
-  struct timespec old = timespec_sub (current_timespec (),
-                                     make_timespec (60, 0));
-
-  while (*pcache)
-    {
-      struct anim_cache *cache = *pcache;
-      if (timespec_cmp (old, cache->update_time) <= 0)
-       pcache = &cache->next;
-      else
-       {
-         if (cache->handle)
-           cache->destructor (cache);
-         if (cache->temp)
-           xfree (cache->temp);
-         *pcache = cache->next;
-         xfree (cache);
-       }
-    }
-}
-
-static struct anim_cache *
-anim_get_animation_cache (Lisp_Object spec)
-{
-  struct anim_cache *cache;
-  struct anim_cache **pcache = &anim_cache;
-
-  anim_prune_animation_cache ();
-
-  while (1)
-    {
-      cache = *pcache;
-      if (! cache)
-       {
-          *pcache = cache = anim_create_cache (spec);
-          break;
-        }
-      if (EQ (spec, cache->spec))
-       break;
-      pcache = &cache->next;
-    }
-
-  cache->update_time = current_timespec ();
-  return cache;
-}
-
 #endif /* HAVE_GIF || HAVE_WEBP */
 
 /***********************************************************************



reply via email to

[Prev in Thread] Current Thread [Next in Thread]