diff src/data.c @ 1590:03009473262a

[xemacs-hg @ 2003-07-26 14:00:27 by michaels] 2003-07-24 Mike Sperber <mike@xemacs.org> * lisp.h: * data.c: (init_marking_ephemerons): (continue_marking_ephemerons): (finish_marking_ephemerons): (prune_ephemerons): * alloc.c (garbage_collect_1): Rewrite the ephemeron marker once again to allow ephemerons to be used for implementing simple object finalization. * data.c (Fmake_ephemeron): Fix comments
author michaels
date Sat, 26 Jul 2003 14:00:28 +0000
parents ddcdeb1a25c4
children ac1be85b4a5f
line wrap: on
line diff
--- a/src/data.c	Fri Jul 25 21:52:27 2003 +0000
+++ b/src/data.c	Sat Jul 26 14:00:28 2003 +0000
@@ -2132,72 +2132,106 @@
  */
 
 static Lisp_Object Vall_ephemerons; /* Gemarke es niemals ever!!! */
+static Lisp_Object Vnew_all_ephemerons;
 static Lisp_Object Vfinalize_list;
 
+void
+init_marking_ephemerons(void)
+{
+  Vnew_all_ephemerons = Qnil;
+}
+
+/* Move all live ephemerons with live keys over to
+ * Vnew_all_ephemerons, marking the values and finalizers along the
+ * way. */
+
+int
+continue_marking_ephemerons(void)
+{
+  Lisp_Object rest = Vall_ephemerons, next, prev = Qnil;
+  int did_mark = 0;
+
+  while (!NILP (rest))
+    {
+      next = XEPHEMERON_NEXT (rest);
+
+      if (marked_p (rest))
+	{
+	  MARK_CONS (XCONS (XEPHEMERON (rest)->cons_chain));
+	  if (marked_p (XEPHEMERON (rest)->key))
+	    {
+	      mark_object (XCAR (XEPHEMERON (rest)->cons_chain));
+	      did_mark = 1;
+	      XSET_EPHEMERON_NEXT (rest, Vnew_all_ephemerons);
+	      Vnew_all_ephemerons = rest;
+	      if (NILP (prev))
+		Vall_ephemerons = next;
+	      else
+		XSET_EPHEMERON_NEXT (prev, next);
+	    }
+	  else
+	    prev = rest;
+	}
+      else
+	prev = rest;
+
+      rest = next;
+    }
+
+  return did_mark;
+}
+
+/* At this point, everything that's in Vall_ephemerons is dead.
+ * Well, almost: we still need to run the finalizers, so we need to
+ * resurrect them.
+ */
+
 int
 finish_marking_ephemerons(void)
 {
-  Lisp_Object rest;
+  Lisp_Object rest = Vall_ephemerons, next, prev = Qnil;
   int did_mark = 0;
 
-  for (rest = Vall_ephemerons;
-       !NILP (rest);
-       rest = XEPHEMERON_NEXT (rest))
-    {
-      if (marked_p (rest) && ! marked_p (XEPHEMERON (rest)->cons_chain))
-	{
-	  MARK_CONS (XCONS (XEPHEMERON (rest)->cons_chain));
-	  mark_object (XCAR (XEPHEMERON (rest)->cons_chain));
-	  did_mark = 1;
-	}
-    }
-  return did_mark;
-}
-
-void
-prune_ephemerons(void)
-{
-  int removep = 0;
-  Lisp_Object rest = Vall_ephemerons, next, prev = Qnil;
-
   while (! NILP (rest))
     {
       next = XEPHEMERON_NEXT (rest);
 
       if (marked_p (rest))
-	/* The ephemeron itself is live ... */
+	/* The ephemeron itself is live, but its key is garbage */
 	{
-	  if (! marked_p(XEPHEMERON (rest)->key))
-	    /* ... but its key is garbage */
+	  /* tombstone */
+	  XSET_EPHEMERON_VALUE (rest, Qnil);
+
+	  if (! NILP (XEPHEMERON_FINALIZER (rest)))
 	    {
-	      removep = 1;
-	      XSET_EPHEMERON_VALUE (rest, Qnil);
-	      if (! NILP (XEPHEMERON_FINALIZER (rest)))
-		/* Register the finalizer */
-		{
-		  XSET_EPHEMERON_NEXT (rest, Vfinalize_list);
-		  Vfinalize_list = XEPHEMERON (rest)->cons_chain;
-		}
+	      MARK_CONS (XCONS (XEPHEMERON (rest)->cons_chain));
+	      mark_object (XCAR (XEPHEMERON (rest)->cons_chain));
+
+	      /* Register the finalizer */
+	      XSET_EPHEMERON_NEXT (rest, Vfinalize_list);
+	      Vfinalize_list = XEPHEMERON (rest)->cons_chain;
+	      did_mark = 1;
 	    }
-	}
-      else
-	/* The ephemeron itself is dead. */
-	removep = 1;
 
-      if (removep)
-	{
 	  /* Remove it from the list. */
 	  if (NILP (prev))
 	    Vall_ephemerons = next;
 	  else
 	    XSET_EPHEMERON_NEXT (prev, next);
-	  removep = 0;
 	}
       else
 	prev = rest;
 
       rest = next;
     }
+  
+  return did_mark;
+}
+
+void
+prune_ephemerons(void)
+{
+  Vall_ephemerons = Vnew_all_ephemerons;
 }
 
 Lisp_Object
@@ -2282,13 +2316,13 @@
 			       struct ephemeron);
 
 DEFUN ("make-ephemeron", Fmake_ephemeron, 2, 3, 0, /*
-Return a new ephemeron with key KEY, value CONTENTS, and finalizer FINALIZER.
-The ephemeron is a reference to CONTENTS which may be extracted with
-`ephemeron-ref'.  CONTENTS is only reachable through the ephemeron as
+Return a new ephemeron with key KEY, value VALUE, and finalizer FINALIZER.
+The ephemeron is a reference to VALUE which may be extracted with
+`ephemeron-ref'.  VALUE is only reachable through the ephemeron as
 long as KEY is reachable; the ephemeron does not contribute to the
 reachability of KEY.  When KEY becomes unreachable while the ephemeron
-itself is still reachable, CONTENTS is queued for finalization: FINALIZER
-will possibly be called on CONTENTS some time in the future.  Moreover,
+itself is still reachable, VALUE is queued for finalization: FINALIZER
+will possibly be called on VALUE some time in the future.  Moreover,
 future calls to `ephemeron-ref' will return NIL.
 */
        (key, value, finalizer))