1 /* weak-refs.c --
2
3 Copyright (C) 2001 John Harper <jsh@pixelslut.com>
4
5 $Id$
6
7 This file is part of librep.
8
9 librep is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 librep is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with librep; see the file COPYING. If not, write to
21 the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23 #define _GNU_SOURCE
24
25 #include "repint.h"
26
27 #define WEAKP(x) rep_CELL16_TYPEP(x, weak_ref_type ())
28 #define WEAK(v) ((rep_tuple *) rep_PTR (v))
29 #define WEAK_NEXT(v) (WEAK(v)->a)
30 #define WEAK_REF(v) (WEAK(v)->b)
31
32 static repv weak_refs;
33
34 static int weak_ref_type (void);
35
36 DEFUN ("make-weak-ref", Fmake_weak_ref, Smake_weak_ref, (repv ref), rep_Subr1)
37 {
38 repv weak_ref;
39
40 weak_ref = rep_make_tuple (weak_ref_type (), rep_NULL, rep_NULL);
41 WEAK_REF (weak_ref) = ref;
42 WEAK_NEXT (weak_ref) = weak_refs;
43 weak_refs = weak_ref;
44
45 return weak_ref;
46 }
47
48 DEFUN ("weak-ref", Fweak_ref, Sweak_ref, (repv weak), rep_Subr1)
49 {
50 rep_DECLARE1 (weak, WEAKP);
51 return WEAK_REF (weak);
52 }
53
54 DEFUN ("weak-ref-set", Fweak_ref_set, Sweak_ref_set, (repv weak, repv value), rep_Subr2)
55 {
56 rep_DECLARE1 (weak, WEAKP);
57 WEAK_REF (weak) = value;
58 return value;
59 }
60
61 void
rep_scan_weak_refs(void)62 rep_scan_weak_refs (void)
63 {
64 repv ref = weak_refs;
65 weak_refs = rep_NULL;
66 while (ref != rep_NULL)
67 {
68 repv next = WEAK_NEXT (ref);
69 if (rep_GC_CELL_MARKEDP (ref))
70 {
71 /* this ref wasn't gc'd */
72 WEAK_NEXT (ref) = weak_refs;
73 weak_refs = ref;
74
75 if (rep_CELLP (WEAK_REF (ref))
76 && !rep_GC_MARKEDP (WEAK_REF (ref)))
77 {
78 /* but the object it points to was */
79 WEAK_REF (ref) = Qnil;
80 }
81 }
82 ref = next;
83 }
84 }
85
86 static void
weak_ref_print(repv stream,repv arg)87 weak_ref_print (repv stream, repv arg)
88 {
89 rep_stream_puts (stream, "#<weak-reference>", -1, rep_FALSE);
90 }
91
92 static int
weak_ref_type(void)93 weak_ref_type (void)
94 {
95 static int type;
96
97 if (type == 0)
98 {
99 type = rep_register_new_type ("weak-ref", rep_ptr_cmp,
100 weak_ref_print, weak_ref_print,
101 0, 0, 0, 0, 0, 0, 0, 0, 0);
102 }
103
104 return type;
105 }
106
107 void
rep_weak_refs_init(void)108 rep_weak_refs_init (void)
109 {
110 repv tem = rep_push_structure ("rep.data");
111 rep_ADD_SUBR(Smake_weak_ref);
112 rep_ADD_SUBR(Sweak_ref);
113 rep_ADD_SUBR(Sweak_ref_set);
114 rep_pop_structure (tem);
115 }
116