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