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