Mercurial > hg > xemacs-beta
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))