Mercurial > hg > xemacs-beta
comparison 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 |
comparison
equal
deleted
inserted
replaced
1589:ea138ff01850 | 1590:03009473262a |
---|---|
2130 * Stretching the storage manager | 2130 * Stretching the storage manager |
2131 * Implementation of Functional Languages, 1999 | 2131 * Implementation of Functional Languages, 1999 |
2132 */ | 2132 */ |
2133 | 2133 |
2134 static Lisp_Object Vall_ephemerons; /* Gemarke es niemals ever!!! */ | 2134 static Lisp_Object Vall_ephemerons; /* Gemarke es niemals ever!!! */ |
2135 static Lisp_Object Vnew_all_ephemerons; | |
2135 static Lisp_Object Vfinalize_list; | 2136 static Lisp_Object Vfinalize_list; |
2137 | |
2138 void | |
2139 init_marking_ephemerons(void) | |
2140 { | |
2141 Vnew_all_ephemerons = Qnil; | |
2142 } | |
2143 | |
2144 /* Move all live ephemerons with live keys over to | |
2145 * Vnew_all_ephemerons, marking the values and finalizers along the | |
2146 * way. */ | |
2147 | |
2148 int | |
2149 continue_marking_ephemerons(void) | |
2150 { | |
2151 Lisp_Object rest = Vall_ephemerons, next, prev = Qnil; | |
2152 int did_mark = 0; | |
2153 | |
2154 while (!NILP (rest)) | |
2155 { | |
2156 next = XEPHEMERON_NEXT (rest); | |
2157 | |
2158 if (marked_p (rest)) | |
2159 { | |
2160 MARK_CONS (XCONS (XEPHEMERON (rest)->cons_chain)); | |
2161 if (marked_p (XEPHEMERON (rest)->key)) | |
2162 { | |
2163 mark_object (XCAR (XEPHEMERON (rest)->cons_chain)); | |
2164 did_mark = 1; | |
2165 XSET_EPHEMERON_NEXT (rest, Vnew_all_ephemerons); | |
2166 Vnew_all_ephemerons = rest; | |
2167 if (NILP (prev)) | |
2168 Vall_ephemerons = next; | |
2169 else | |
2170 XSET_EPHEMERON_NEXT (prev, next); | |
2171 } | |
2172 else | |
2173 prev = rest; | |
2174 } | |
2175 else | |
2176 prev = rest; | |
2177 | |
2178 rest = next; | |
2179 } | |
2180 | |
2181 return did_mark; | |
2182 } | |
2183 | |
2184 /* At this point, everything that's in Vall_ephemerons is dead. | |
2185 * Well, almost: we still need to run the finalizers, so we need to | |
2186 * resurrect them. | |
2187 */ | |
2136 | 2188 |
2137 int | 2189 int |
2138 finish_marking_ephemerons(void) | 2190 finish_marking_ephemerons(void) |
2139 { | 2191 { |
2140 Lisp_Object rest; | 2192 Lisp_Object rest = Vall_ephemerons, next, prev = Qnil; |
2141 int did_mark = 0; | 2193 int did_mark = 0; |
2142 | 2194 |
2143 for (rest = Vall_ephemerons; | 2195 while (! NILP (rest)) |
2144 !NILP (rest); | 2196 { |
2145 rest = XEPHEMERON_NEXT (rest)) | 2197 next = XEPHEMERON_NEXT (rest); |
2146 { | 2198 |
2147 if (marked_p (rest) && ! marked_p (XEPHEMERON (rest)->cons_chain)) | 2199 if (marked_p (rest)) |
2200 /* The ephemeron itself is live, but its key is garbage */ | |
2148 { | 2201 { |
2149 MARK_CONS (XCONS (XEPHEMERON (rest)->cons_chain)); | 2202 /* tombstone */ |
2150 mark_object (XCAR (XEPHEMERON (rest)->cons_chain)); | 2203 XSET_EPHEMERON_VALUE (rest, Qnil); |
2151 did_mark = 1; | 2204 |
2152 } | 2205 if (! NILP (XEPHEMERON_FINALIZER (rest))) |
2153 } | |
2154 return did_mark; | |
2155 } | |
2156 | |
2157 void | |
2158 prune_ephemerons(void) | |
2159 { | |
2160 int removep = 0; | |
2161 Lisp_Object rest = Vall_ephemerons, next, prev = Qnil; | |
2162 | |
2163 while (! NILP (rest)) | |
2164 { | |
2165 next = XEPHEMERON_NEXT (rest); | |
2166 | |
2167 if (marked_p (rest)) | |
2168 /* The ephemeron itself is live ... */ | |
2169 { | |
2170 if (! marked_p(XEPHEMERON (rest)->key)) | |
2171 /* ... but its key is garbage */ | |
2172 { | 2206 { |
2173 removep = 1; | 2207 MARK_CONS (XCONS (XEPHEMERON (rest)->cons_chain)); |
2174 XSET_EPHEMERON_VALUE (rest, Qnil); | 2208 mark_object (XCAR (XEPHEMERON (rest)->cons_chain)); |
2175 if (! NILP (XEPHEMERON_FINALIZER (rest))) | 2209 |
2176 /* Register the finalizer */ | 2210 /* Register the finalizer */ |
2177 { | 2211 XSET_EPHEMERON_NEXT (rest, Vfinalize_list); |
2178 XSET_EPHEMERON_NEXT (rest, Vfinalize_list); | 2212 Vfinalize_list = XEPHEMERON (rest)->cons_chain; |
2179 Vfinalize_list = XEPHEMERON (rest)->cons_chain; | 2213 did_mark = 1; |
2180 } | |
2181 } | 2214 } |
2182 } | 2215 |
2183 else | |
2184 /* The ephemeron itself is dead. */ | |
2185 removep = 1; | |
2186 | |
2187 if (removep) | |
2188 { | |
2189 /* Remove it from the list. */ | 2216 /* Remove it from the list. */ |
2190 if (NILP (prev)) | 2217 if (NILP (prev)) |
2191 Vall_ephemerons = next; | 2218 Vall_ephemerons = next; |
2192 else | 2219 else |
2193 XSET_EPHEMERON_NEXT (prev, next); | 2220 XSET_EPHEMERON_NEXT (prev, next); |
2194 removep = 0; | |
2195 } | 2221 } |
2196 else | 2222 else |
2197 prev = rest; | 2223 prev = rest; |
2198 | 2224 |
2199 rest = next; | 2225 rest = next; |
2200 } | 2226 } |
2227 | |
2228 return did_mark; | |
2229 } | |
2230 | |
2231 void | |
2232 prune_ephemerons(void) | |
2233 { | |
2234 Vall_ephemerons = Vnew_all_ephemerons; | |
2201 } | 2235 } |
2202 | 2236 |
2203 Lisp_Object | 2237 Lisp_Object |
2204 zap_finalize_list(void) | 2238 zap_finalize_list(void) |
2205 { | 2239 { |
2280 0, ephemeron_equal, ephemeron_hash, | 2314 0, ephemeron_equal, ephemeron_hash, |
2281 ephemeron_description, | 2315 ephemeron_description, |
2282 struct ephemeron); | 2316 struct ephemeron); |
2283 | 2317 |
2284 DEFUN ("make-ephemeron", Fmake_ephemeron, 2, 3, 0, /* | 2318 DEFUN ("make-ephemeron", Fmake_ephemeron, 2, 3, 0, /* |
2285 Return a new ephemeron with key KEY, value CONTENTS, and finalizer FINALIZER. | 2319 Return a new ephemeron with key KEY, value VALUE, and finalizer FINALIZER. |
2286 The ephemeron is a reference to CONTENTS which may be extracted with | 2320 The ephemeron is a reference to VALUE which may be extracted with |
2287 `ephemeron-ref'. CONTENTS is only reachable through the ephemeron as | 2321 `ephemeron-ref'. VALUE is only reachable through the ephemeron as |
2288 long as KEY is reachable; the ephemeron does not contribute to the | 2322 long as KEY is reachable; the ephemeron does not contribute to the |
2289 reachability of KEY. When KEY becomes unreachable while the ephemeron | 2323 reachability of KEY. When KEY becomes unreachable while the ephemeron |
2290 itself is still reachable, CONTENTS is queued for finalization: FINALIZER | 2324 itself is still reachable, VALUE is queued for finalization: FINALIZER |
2291 will possibly be called on CONTENTS some time in the future. Moreover, | 2325 will possibly be called on VALUE some time in the future. Moreover, |
2292 future calls to `ephemeron-ref' will return NIL. | 2326 future calls to `ephemeron-ref' will return NIL. |
2293 */ | 2327 */ |
2294 (key, value, finalizer)) | 2328 (key, value, finalizer)) |
2295 { | 2329 { |
2296 return make_ephemeron(key, value, finalizer); | 2330 return make_ephemeron(key, value, finalizer); |