Mercurial > hg > xemacs-beta
comparison src/data.c @ 888:201c016cfc12
[xemacs-hg @ 2002-06-28 14:24:07 by michaels]
2002-06-27 Mike Sperber <mike@xemacs.org>
* data.c (prune_weak_boxes): Rewrite for better readability.
2002-06-23 Martin Köbele <martin@mkoebele.de>
Jens Müller <jmueller@informatik.uni-tuebingen.de>
Mike Sperber <mike@xemacs.org>
* lrecord.h (lrecord_type): add lrecord_type_ephemeron to lrecord_type enumeration.
* lisp.h (XEPHEMERON):
(XEPHEMERON_REF):
(XEPHEMERON_NEXT):
(XEPHEMERON_FINALIZER):
(XSET_EPHEMERON_NEXT):
(XSET_EPHEMERON_VALUE):
(XSET_EPHEMERON_KEY):
(wrap_ephemeron):
(EPHEMERONP):
(CHECK_EPHEMERON):
(CONCHECK_EPHEMERON):
(struct ephemeron): Add representation of ephemerons.
* alloc.c (garbage_collect_1):
(finish_marking_ephemerons):
(prune_ephemerons): Call.
* data.c:
(finish_marking_ephemerons):
(prune_ephemerons):
(mark_ephemeron):
(print_ephemeron):
(ephemeron_equal)
(ephemeron_hash)::
(make_ephemeron):
(Fmake_ephemeron):
(Fephemeronp):
(Fephemeron_ref):
(syms_of_data):
(vars_of_data): Add implementation of ephemerons
author | michaels |
---|---|
date | Fri, 28 Jun 2002 14:24:08 +0000 |
parents | 804517e16990 |
children | c925bacdda60 |
comparison
equal
deleted
inserted
replaced
887:ccc3177ef10b | 888:201c016cfc12 |
---|---|
2002 CHECK_WEAK_LIST (weak); | 2002 CHECK_WEAK_LIST (weak); |
2003 XWEAK_LIST_LIST (weak) = new_list; | 2003 XWEAK_LIST_LIST (weak) = new_list; |
2004 return new_list; | 2004 return new_list; |
2005 } | 2005 } |
2006 | 2006 |
2007 | |
2007 /************************************************************************/ | 2008 /************************************************************************/ |
2008 /* weak boxes */ | 2009 /* weak boxes */ |
2009 /************************************************************************/ | 2010 /************************************************************************/ |
2010 | 2011 |
2011 static Lisp_Object Vall_weak_boxes; /* Gemarke es niemals ever!!! */ | 2012 static Lisp_Object Vall_weak_boxes; /* Gemarke es niemals ever!!! */ |
2012 | 2013 |
2013 void | 2014 void |
2014 prune_weak_boxes (void) | 2015 prune_weak_boxes (void) |
2015 { | 2016 { |
2016 Lisp_Object rest, prev = Qnil; | 2017 Lisp_Object rest, prev = Qnil; |
2018 int removep = 0; | |
2017 | 2019 |
2018 for (rest = Vall_weak_boxes; | 2020 for (rest = Vall_weak_boxes; |
2019 !NILP(rest); | 2021 !NILP(rest); |
2020 rest = XWEAK_BOX (rest)->next_weak_box) | 2022 rest = XWEAK_BOX (rest)->next_weak_box) |
2021 { | 2023 { |
2022 if (! (marked_p (rest))) | 2024 if (! (marked_p (rest))) |
2023 /* This weak box itself is garbage. Remove it from the list. */ | 2025 /* This weak box itself is garbage. */ |
2024 if (NILP (prev)) | 2026 removep = 1; |
2025 Vall_weak_boxes = XWEAK_BOX (rest)->next_weak_box; | 2027 |
2026 else | 2028 if (! marked_p (XWEAK_BOX (rest)->value)) |
2027 XWEAK_BOX (prev)->next_weak_box = XWEAK_BOX (rest)->next_weak_box; | 2029 { |
2028 else if (!marked_p(XWEAK_BOX (rest)->value)) | 2030 XSET_WEAK_BOX (rest, Qnil); |
2029 XSET_WEAK_BOX (rest, Qnil); | 2031 removep = 1; |
2032 } | |
2033 | |
2034 if (removep) | |
2035 { | |
2036 /* Remove weak box from list. */ | |
2037 if (NILP (prev)) | |
2038 Vall_weak_boxes = XWEAK_BOX (rest)->next_weak_box; | |
2039 else | |
2040 XWEAK_BOX (prev)->next_weak_box = XWEAK_BOX (rest)->next_weak_box; | |
2041 removep = 0; | |
2042 } | |
2043 else | |
2044 prev = rest; | |
2030 } | 2045 } |
2031 } | 2046 } |
2032 | 2047 |
2033 static Lisp_Object | 2048 static Lisp_Object |
2034 mark_weak_box (Lisp_Object obj) | 2049 mark_weak_box (Lisp_Object obj) |
2035 { | 2050 { |
2036 return Qnil; | 2051 return Qnil; |
2037 } | 2052 } |
2038 | 2053 |
2039 static void | 2054 static void |
2045 } | 2060 } |
2046 | 2061 |
2047 static int | 2062 static int |
2048 weak_box_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) | 2063 weak_box_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
2049 { | 2064 { |
2050 struct weak_box *b1 = XWEAK_BOX (obj1); | 2065 struct weak_box *wb1 = XWEAK_BOX (obj1); |
2051 struct weak_box *b2 = XWEAK_BOX (obj2); | 2066 struct weak_box *wb2 = XWEAK_BOX (obj2); |
2052 | 2067 |
2053 return (internal_equal (b1->value, b2->value, depth + 1)); | 2068 return (internal_equal (wb1->value, wb2->value, depth + 1)); |
2054 } | 2069 } |
2055 | 2070 |
2056 static Hashcode | 2071 static Hashcode |
2057 weak_box_hash (Lisp_Object obj, int depth) | 2072 weak_box_hash (Lisp_Object obj, int depth) |
2058 { | 2073 { |
2059 struct weak_box *b = XWEAK_BOX (obj); | 2074 struct weak_box *wb = XWEAK_BOX (obj); |
2060 | 2075 |
2061 return internal_hash (b->value, depth + 1); | 2076 return internal_hash (wb->value, depth + 1); |
2062 } | 2077 } |
2063 | 2078 |
2064 Lisp_Object | 2079 Lisp_Object |
2065 make_weak_box (Lisp_Object value) | 2080 make_weak_box (Lisp_Object value) |
2066 { | 2081 { |
2074 wb->next_weak_box = Vall_weak_boxes; | 2089 wb->next_weak_box = Vall_weak_boxes; |
2075 Vall_weak_boxes = result; | 2090 Vall_weak_boxes = result; |
2076 return result; | 2091 return result; |
2077 } | 2092 } |
2078 | 2093 |
2079 static const struct lrecord_description weak_box_description[] = { | 2094 static const struct lrecord_description weak_box_description[] = { |
2080 { XD_LO_LINK, offsetof (struct weak_box, value) }, | 2095 { XD_LO_LINK, offsetof (struct weak_box, value) }, |
2081 { XD_END} | 2096 { XD_END} |
2082 }; | 2097 }; |
2083 | 2098 |
2084 DEFINE_LRECORD_IMPLEMENTATION ("weak_box", weak_box, | 2099 DEFINE_LRECORD_IMPLEMENTATION ("weak_box", weak_box, |
2085 mark_weak_box, print_weak_box, | 2100 mark_weak_box, print_weak_box, |
2086 0, weak_box_equal, weak_box_hash, | 2101 0, weak_box_equal, weak_box_hash, |
2101 | 2116 |
2102 DEFUN ("weak-box-ref", Fweak_box_ref, 1, 1, 0, /* | 2117 DEFUN ("weak-box-ref", Fweak_box_ref, 1, 1, 0, /* |
2103 Return the contents of weak box WEAK-BOX. | 2118 Return the contents of weak box WEAK-BOX. |
2104 If the contents have been GCed, return NIL. | 2119 If the contents have been GCed, return NIL. |
2105 */ | 2120 */ |
2106 (box)) | 2121 (wb)) |
2107 { | 2122 { |
2108 return XWEAK_BOX(box)->value; | 2123 return XWEAK_BOX (wb)->value; |
2109 } | 2124 } |
2110 | 2125 |
2111 DEFUN ("weak-box-p", Fweak_boxp, 1, 1, 0, /* | 2126 DEFUN ("weak-box-p", Fweak_boxp, 1, 1, 0, /* |
2112 Return non-nil if OBJECT is a weak box. | 2127 Return non-nil if OBJECT is a weak box. |
2113 */ | 2128 */ |
2114 (object)) | 2129 (object)) |
2115 { | 2130 { |
2116 return WEAK_BOXP (object) ? Qt : Qnil; | 2131 return WEAK_BOXP (object) ? Qt : Qnil; |
2117 } | 2132 } |
2118 | 2133 |
2134 /************************************************************************/ | |
2135 /* ephemerons */ | |
2136 /************************************************************************/ | |
2137 | |
2138 static Lisp_Object Vall_ephemerons; /* Gemarke es niemals ever!!! */ | |
2139 static Lisp_Object Vfinalize_list; | |
2140 | |
2141 int | |
2142 finish_marking_ephemerons(void) | |
2143 { | |
2144 Lisp_Object rest; | |
2145 int did_mark = 0; | |
2146 | |
2147 for (rest = Vall_ephemerons; | |
2148 !NILP (rest); | |
2149 rest = XEPHEMERON_NEXT (rest)) | |
2150 { | |
2151 if (marked_p (rest) && ! marked_p (XEPHEMERON (rest)->cons_chain)) | |
2152 { | |
2153 MARK_CONS (XCONS (XEPHEMERON (rest)->cons_chain)); | |
2154 mark_object (XCAR (XEPHEMERON (rest)->cons_chain)); | |
2155 did_mark = 1; | |
2156 } | |
2157 } | |
2158 return did_mark; | |
2159 } | |
2160 | |
2161 void | |
2162 prune_ephemerons(void) | |
2163 { | |
2164 int removep = 0; | |
2165 Lisp_Object rest = Vall_ephemerons, next, prev = Qnil; | |
2166 | |
2167 while (! NILP (rest)) | |
2168 { | |
2169 next = XEPHEMERON_NEXT (rest); | |
2170 | |
2171 if (marked_p (rest)) | |
2172 /* The ephemeron itself is live ... */ | |
2173 { | |
2174 if (! marked_p(XEPHEMERON (rest)->key)) | |
2175 /* ... but its key is garbage */ | |
2176 { | |
2177 removep = 1; | |
2178 XSET_EPHEMERON_VALUE (rest, Qnil); | |
2179 if (! NILP (XEPHEMERON_FINALIZER (rest))) | |
2180 /* Register the finalizer */ | |
2181 { | |
2182 XSET_EPHEMERON_NEXT (rest, Vfinalize_list); | |
2183 Vfinalize_list = XEPHEMERON (rest)->cons_chain; | |
2184 } | |
2185 } | |
2186 } | |
2187 else | |
2188 /* The ephemeron itself is dead. */ | |
2189 removep = 1; | |
2190 | |
2191 if (removep) | |
2192 { | |
2193 /* Remove it from the list. */ | |
2194 if (NILP (prev)) | |
2195 Vall_ephemerons = next; | |
2196 else | |
2197 XSET_EPHEMERON_NEXT (prev, next); | |
2198 removep = 0; | |
2199 } | |
2200 else | |
2201 prev = rest; | |
2202 | |
2203 rest = next; | |
2204 } | |
2205 } | |
2206 | |
2207 Lisp_Object | |
2208 zap_finalize_list(void) | |
2209 { | |
2210 Lisp_Object finalizers = Vfinalize_list; | |
2211 | |
2212 Vfinalize_list = Qnil; | |
2213 | |
2214 return finalizers; | |
2215 } | |
2216 | |
2217 static Lisp_Object | |
2218 mark_ephemeron (Lisp_Object obj) | |
2219 { | |
2220 return Qnil; | |
2221 } | |
2222 | |
2223 static void | |
2224 print_ephemeron (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) | |
2225 { | |
2226 if (print_readably) | |
2227 printing_unreadable_object ("#<ephemeron>"); | |
2228 write_fmt_string (printcharfun, "#<ephemeron>"); | |
2229 } | |
2230 | |
2231 static int | |
2232 ephemeron_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) | |
2233 { | |
2234 return | |
2235 internal_equal (XEPHEMERON_REF (obj1), XEPHEMERON_REF(obj2), depth + 1); | |
2236 } | |
2237 | |
2238 static Hashcode | |
2239 ephemeron_hash(Lisp_Object obj, int depth) | |
2240 { | |
2241 return internal_hash (XEPHEMERON_REF (obj), depth + 1); | |
2242 } | |
2243 | |
2244 Lisp_Object | |
2245 make_ephemeron(Lisp_Object key, Lisp_Object value, Lisp_Object finalizer) | |
2246 { | |
2247 Lisp_Object result, temp = Qnil; | |
2248 struct gcpro gcpro1, gcpro2; | |
2249 | |
2250 struct ephemeron *eph = | |
2251 alloc_lcrecord_type (struct ephemeron, &lrecord_ephemeron); | |
2252 | |
2253 eph->key = Qnil; | |
2254 eph->cons_chain = Qnil; | |
2255 eph->value = Qnil; | |
2256 | |
2257 result = wrap_ephemeron(eph); | |
2258 GCPRO2 (result, temp); | |
2259 | |
2260 eph->key = key; | |
2261 temp = Fcons(value, finalizer); | |
2262 eph->cons_chain = Fcons(temp, Vall_ephemerons); | |
2263 eph->value = value; | |
2264 | |
2265 Vall_ephemerons = result; | |
2266 | |
2267 UNGCPRO; | |
2268 return result; | |
2269 } | |
2270 | |
2271 static const struct lrecord_description ephemeron_description[] = { | |
2272 { XD_LISP_OBJECT, offsetof(struct ephemeron, key)}, | |
2273 { XD_LISP_OBJECT, offsetof(struct ephemeron, cons_chain)}, | |
2274 { XD_LISP_OBJECT, offsetof(struct ephemeron, value)}, | |
2275 { XD_END } | |
2276 }; | |
2277 | |
2278 DEFINE_LRECORD_IMPLEMENTATION ("ephemeron", ephemeron, | |
2279 mark_ephemeron, print_ephemeron, | |
2280 0, ephemeron_equal, ephemeron_hash, | |
2281 ephemeron_description, | |
2282 struct ephemeron); | |
2283 | |
2284 DEFUN ("make-ephemeron", Fmake_ephemeron, 2, 3, 0, /* | |
2285 Return a new ephemeron with key KEY, value CONTENTS, and finalizer FINALIZER. | |
2286 The ephemeron is a reference to CONTENTS which may be extracted with | |
2287 `ephemeron-ref'. CONTENTS is only reachable through the ephemeron as | |
2288 long as KEY is reachable; the ephemeron does not contribute to the | |
2289 reachability of KEY. When KEY becomes unreachable while the ephemeron | |
2290 itself is still reachable, CONTENTS is queued for finalization: FINALIZER | |
2291 will possibly be called on CONTENTS some time in the future. Moreover, | |
2292 future calls to `ephemeron-ref' will return NIL. | |
2293 */ | |
2294 (key, value, finalizer)) | |
2295 { | |
2296 return make_ephemeron(key, value, finalizer); | |
2297 } | |
2298 | |
2299 DEFUN ("ephemeron-ref", Fephemeron_ref, 1, 1, 0, /* | |
2300 Return the contents of ephemeron EPHEMERON. | |
2301 If the contents have been GCed, return NIL. | |
2302 */ | |
2303 (eph)) | |
2304 { | |
2305 return XEPHEMERON_REF (eph); | |
2306 } | |
2307 | |
2308 DEFUN ("ephemeron-p", Fephemeronp, 1, 1, 0, /* | |
2309 Return non-nil if OBJECT is an ephemeron. | |
2310 */ | |
2311 (object)) | |
2312 { | |
2313 return EPHEMERONP (object) ? Qt : Qnil; | |
2314 } | |
2119 | 2315 |
2120 /************************************************************************/ | 2316 /************************************************************************/ |
2121 /* initialization */ | 2317 /* initialization */ |
2122 /************************************************************************/ | 2318 /************************************************************************/ |
2123 | 2319 |
2222 | 2418 |
2223 void | 2419 void |
2224 syms_of_data (void) | 2420 syms_of_data (void) |
2225 { | 2421 { |
2226 INIT_LRECORD_IMPLEMENTATION (weak_list); | 2422 INIT_LRECORD_IMPLEMENTATION (weak_list); |
2423 INIT_LRECORD_IMPLEMENTATION (ephemeron); | |
2227 INIT_LRECORD_IMPLEMENTATION (weak_box); | 2424 INIT_LRECORD_IMPLEMENTATION (weak_box); |
2228 | 2425 |
2229 DEFSYMBOL (Qquote); | 2426 DEFSYMBOL (Qquote); |
2230 DEFSYMBOL (Qlambda); | 2427 DEFSYMBOL (Qlambda); |
2231 DEFSYMBOL (Qlistp); | 2428 DEFSYMBOL (Qlistp); |
2340 DEFSUBR (Fmake_weak_list); | 2537 DEFSUBR (Fmake_weak_list); |
2341 DEFSUBR (Fweak_list_type); | 2538 DEFSUBR (Fweak_list_type); |
2342 DEFSUBR (Fweak_list_list); | 2539 DEFSUBR (Fweak_list_list); |
2343 DEFSUBR (Fset_weak_list_list); | 2540 DEFSUBR (Fset_weak_list_list); |
2344 | 2541 |
2542 DEFSUBR (Fmake_ephemeron); | |
2543 DEFSUBR (Fephemeron_ref); | |
2544 DEFSUBR (Fephemeronp); | |
2345 DEFSUBR (Fmake_weak_box); | 2545 DEFSUBR (Fmake_weak_box); |
2346 DEFSUBR (Fweak_box_ref); | 2546 DEFSUBR (Fweak_box_ref); |
2347 DEFSUBR (Fweak_boxp); | 2547 DEFSUBR (Fweak_boxp); |
2348 } | 2548 } |
2349 | 2549 |
2351 vars_of_data (void) | 2551 vars_of_data (void) |
2352 { | 2552 { |
2353 /* This must not be staticpro'd */ | 2553 /* This must not be staticpro'd */ |
2354 Vall_weak_lists = Qnil; | 2554 Vall_weak_lists = Qnil; |
2355 dump_add_weak_object_chain (&Vall_weak_lists); | 2555 dump_add_weak_object_chain (&Vall_weak_lists); |
2556 | |
2557 Vall_ephemerons = Qnil; | |
2558 dump_add_weak_object_chain (&Vall_ephemerons); | |
2559 | |
2560 Vfinalize_list = Qnil; | |
2561 staticpro (&Vfinalize_list); | |
2356 | 2562 |
2357 Vall_weak_boxes = Qnil; | 2563 Vall_weak_boxes = Qnil; |
2358 dump_add_weak_object_chain (&Vall_weak_boxes); | 2564 dump_add_weak_object_chain (&Vall_weak_boxes); |
2359 | 2565 |
2360 #ifdef DEBUG_XEMACS | 2566 #ifdef DEBUG_XEMACS |