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);