* gc.h, gc.c (scm_gc_sweep): Issue deprecation warning when
[bpt/guile.git] / libguile / weaks.c
CommitLineData
22a52da1 1/* Copyright (C) 1995,1996,1998,2000,2001 Free Software Foundation, Inc.
0f2d19dd
JB
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2, or (at your option)
6 * any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; see the file COPYING. If not, write to
82892bed
JB
15 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
16 * Boston, MA 02111-1307 USA
0f2d19dd
JB
17 *
18 * As a special exception, Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of this library.
20 *
21 * The exception is that, if you link this library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking this library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by
31 * Free Software Foundation as part of this library. If you copy
32 * code from other releases distributed under the terms of the GPL into a copy of
33 * this library, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from such code.
37 *
38 * If you write modifications of your own for this library, it is your choice
39 * whether to permit this exception to apply to your modifications.
82892bed 40 * If you do not wish that, delete this exception notice. */
1bbd0b84 41
1bbd0b84 42
0f2d19dd 43\f
592996c9 44
a0599745
MD
45#include "libguile/_scm.h"
46#include "libguile/vectors.h"
c96d76b8 47#include "libguile/lang.h"
0f2d19dd 48
a0599745
MD
49#include "libguile/validate.h"
50#include "libguile/weaks.h"
0f2d19dd 51
592996c9 52\f
0f2d19dd
JB
53
54/* {Weak Vectors}
55 */
56
57
592996c9
DH
58/* Allocate memory for a weak vector on behalf of the caller. The allocated
59 * vector will be of the given weak vector subtype. It will contain size
60 * elements which are initialized with the 'fill' object, or, if 'fill' is
61 * undefined, with an unspecified object.
62 */
63static SCM
64allocate_weak_vector (scm_t_bits type, SCM size, SCM fill, const char* caller)
65#define FUNC_NAME caller
66{
67 if (SCM_INUMP (size))
68 {
69 size_t c_size;
70 SCM v;
71
72 SCM_ASSERT_RANGE (1, size, SCM_INUM (size) >= 0);
73 c_size = SCM_INUM (size);
74
592996c9
DH
75 if (c_size > 0)
76 {
77 scm_t_bits *base;
78 size_t j;
79
80 if (SCM_UNBNDP (fill))
81 fill = SCM_UNSPECIFIED;
82
83 SCM_ASSERT_RANGE (1, size, c_size <= SCM_VECTOR_MAX_LENGTH);
4c9419ac 84 base = scm_gc_malloc (c_size * sizeof (scm_t_bits), "weak vector");
592996c9
DH
85 for (j = 0; j != c_size; ++j)
86 base[j] = SCM_UNPACK (fill);
16d4699b
MV
87 v = scm_alloc_double_cell (SCM_MAKE_VECTOR_TAG (c_size,
88 scm_tc7_wvect),
89 (scm_t_bits) base,
90 type,
91 SCM_UNPACK (SCM_EOL));
592996c9
DH
92 scm_remember_upto_here_1 (fill);
93 }
94 else
95 {
16d4699b
MV
96 v = scm_alloc_double_cell (SCM_MAKE_VECTOR_TAG (0,
97 scm_tc7_wvect),
98 (scm_t_bits) NULL,
99 type,
100 SCM_UNPACK (SCM_EOL));
592996c9
DH
101 }
102
103 return v;
104 }
105 else if (SCM_BIGP (size))
106 SCM_OUT_OF_RANGE (1, size);
107 else
108 SCM_WRONG_TYPE_ARG (1, size);
109}
110#undef FUNC_NAME
111
112
3b3b36dd 113SCM_DEFINE (scm_make_weak_vector, "make-weak-vector", 1, 1, 0,
1e6808ea 114 (SCM size, SCM fill),
b380b885 115 "Return a weak vector with @var{size} elements. If the optional\n"
1e6808ea
MG
116 "argument @var{fill} is given, all entries in the vector will be\n"
117 "set to @var{fill}. The default value for @var{fill} is the\n"
118 "empty list.")
1bbd0b84 119#define FUNC_NAME s_scm_make_weak_vector
0f2d19dd 120{
592996c9 121 return allocate_weak_vector (0, size, fill, FUNC_NAME);
0f2d19dd 122}
1bbd0b84 123#undef FUNC_NAME
0f2d19dd
JB
124
125
1bbd0b84 126SCM_REGISTER_PROC(s_list_to_weak_vector, "list->weak-vector", 1, 0, 0, scm_weak_vector);
1cc91f1b 127
3b3b36dd 128SCM_DEFINE (scm_weak_vector, "weak-vector", 0, 0, 1,
1bbd0b84 129 (SCM l),
8f85c0c6 130 "@deffnx {Scheme Procedure} list->weak-vector l\n"
1e6808ea
MG
131 "Construct a weak vector from a list: @code{weak-vector} uses\n"
132 "the list of its arguments while @code{list->weak-vector} uses\n"
133 "its only argument @var{l} (a list) to construct a weak vector\n"
134 "the same way @code{list->vector} would.")
1bbd0b84 135#define FUNC_NAME s_scm_weak_vector
0f2d19dd
JB
136{
137 SCM res;
22a52da1 138 SCM *data;
c014a02e 139 long i;
0f2d19dd 140
22a52da1
DH
141 /* Dirk:FIXME:: In case of multiple threads, the list might get corrupted
142 while the vector is being created. */
0f2d19dd 143 i = scm_ilength (l);
1bbd0b84 144 SCM_ASSERT (i >= 0, l, SCM_ARG1, FUNC_NAME);
0f2d19dd
JB
145 res = scm_make_weak_vector (SCM_MAKINUM (i), SCM_UNSPECIFIED);
146 data = SCM_VELTS (res);
22a52da1 147
c96d76b8 148 while (!SCM_NULL_OR_NIL_P (l))
22a52da1
DH
149 {
150 *data++ = SCM_CAR (l);
151 l = SCM_CDR (l);
152 }
153
0f2d19dd
JB
154 return res;
155}
1bbd0b84 156#undef FUNC_NAME
0f2d19dd
JB
157
158
3b3b36dd 159SCM_DEFINE (scm_weak_vector_p, "weak-vector?", 1, 0, 0,
1e6808ea 160 (SCM obj),
5352393c
MG
161 "Return @code{#t} if @var{obj} is a weak vector. Note that all\n"
162 "weak hashes are also weak vectors.")
1bbd0b84 163#define FUNC_NAME s_scm_weak_vector_p
0f2d19dd 164{
592996c9 165 return SCM_BOOL (SCM_WVECTP (obj) && !SCM_IS_WHVEC (obj));
0f2d19dd 166}
1bbd0b84 167#undef FUNC_NAME
0f2d19dd 168
0f2d19dd
JB
169\f
170
3b3b36dd 171SCM_DEFINE (scm_make_weak_key_hash_table, "make-weak-key-hash-table", 1, 0, 0,
1e6808ea 172 (SCM size),
8f85c0c6
NJ
173 "@deffnx {Scheme Procedure} make-weak-value-hash-table size\n"
174 "@deffnx {Scheme Procedure} make-doubly-weak-hash-table size\n"
1e6808ea
MG
175 "Return a weak hash table with @var{size} buckets. As with any\n"
176 "hash table, choosing a good size for the table requires some\n"
177 "caution.\n"
178 "\n"
179 "You can modify weak hash tables in exactly the same way you\n"
180 "would modify regular hash tables. (@pxref{Hash Tables})")
1bbd0b84 181#define FUNC_NAME s_scm_make_weak_key_hash_table
0f2d19dd 182{
592996c9 183 return allocate_weak_vector (1, size, SCM_EOL, FUNC_NAME);
0f2d19dd 184}
1bbd0b84 185#undef FUNC_NAME
0f2d19dd
JB
186
187
a1ec6916 188SCM_DEFINE (scm_make_weak_value_hash_table, "make-weak-value-hash-table", 1, 0, 0,
1e6808ea 189 (SCM size),
e3239868
DH
190 "Return a hash table with weak values with @var{size} buckets.\n"
191 "(@pxref{Hash Tables})")
1bbd0b84 192#define FUNC_NAME s_scm_make_weak_value_hash_table
0f2d19dd 193{
592996c9 194 return allocate_weak_vector (2, size, SCM_EOL, FUNC_NAME);
0f2d19dd 195}
1bbd0b84 196#undef FUNC_NAME
0f2d19dd
JB
197
198
a1ec6916 199SCM_DEFINE (scm_make_doubly_weak_hash_table, "make-doubly-weak-hash-table", 1, 0, 0,
1e6808ea 200 (SCM size),
e3239868
DH
201 "Return a hash table with weak keys and values with @var{size}\n"
202 "buckets. (@pxref{Hash Tables})")
1bbd0b84 203#define FUNC_NAME s_scm_make_doubly_weak_hash_table
0f2d19dd 204{
592996c9 205 return allocate_weak_vector (3, size, SCM_EOL, FUNC_NAME);
0f2d19dd 206}
1bbd0b84 207#undef FUNC_NAME
0f2d19dd 208
592996c9 209
3b3b36dd 210SCM_DEFINE (scm_weak_key_hash_table_p, "weak-key-hash-table?", 1, 0, 0,
1e6808ea 211 (SCM obj),
8f85c0c6
NJ
212 "@deffnx {Scheme Procedure} weak-value-hash-table? obj\n"
213 "@deffnx {Scheme Procedure} doubly-weak-hash-table? obj\n"
5352393c
MG
214 "Return @code{#t} if @var{obj} is the specified weak hash\n"
215 "table. Note that a doubly weak hash table is neither a weak key\n"
216 "nor a weak value hash table.")
1bbd0b84 217#define FUNC_NAME s_scm_weak_key_hash_table_p
0f2d19dd 218{
592996c9 219 return SCM_BOOL (SCM_WVECTP (obj) && SCM_IS_WHVEC (obj));
0f2d19dd 220}
1bbd0b84 221#undef FUNC_NAME
0f2d19dd
JB
222
223
a1ec6916 224SCM_DEFINE (scm_weak_value_hash_table_p, "weak-value-hash-table?", 1, 0, 0,
1e6808ea
MG
225 (SCM obj),
226 "Return @code{#t} if @var{obj} is a weak value hash table.")
1bbd0b84 227#define FUNC_NAME s_scm_weak_value_hash_table_p
0f2d19dd 228{
592996c9 229 return SCM_BOOL (SCM_WVECTP (obj) && SCM_IS_WHVEC_V (obj));
0f2d19dd 230}
1bbd0b84 231#undef FUNC_NAME
0f2d19dd
JB
232
233
a1ec6916 234SCM_DEFINE (scm_doubly_weak_hash_table_p, "doubly-weak-hash-table?", 1, 0, 0,
1e6808ea
MG
235 (SCM obj),
236 "Return @code{#t} if @var{obj} is a doubly weak hash table.")
1bbd0b84 237#define FUNC_NAME s_scm_doubly_weak_hash_table_p
0f2d19dd 238{
592996c9 239 return SCM_BOOL (SCM_WVECTP (obj) && SCM_IS_WHVEC_B (obj));
0f2d19dd 240}
1bbd0b84 241#undef FUNC_NAME
0f2d19dd 242
592996c9 243
d662820a 244static void *
e81d98ec
DH
245scm_weak_vector_gc_init (void *dummy1 SCM_UNUSED,
246 void *dummy2 SCM_UNUSED,
247 void *dummy3 SCM_UNUSED)
d662820a
MD
248{
249 scm_weak_vectors = SCM_EOL;
250
251 return 0;
252}
253
592996c9 254
d662820a 255static void *
e81d98ec
DH
256scm_mark_weak_vector_spines (void *dummy1 SCM_UNUSED,
257 void *dummy2 SCM_UNUSED,
258 void *dummy3 SCM_UNUSED)
d662820a
MD
259{
260 SCM w;
261
262 for (w = scm_weak_vectors; !SCM_NULLP (w); w = SCM_WVECT_GC_CHAIN (w))
263 {
264 if (SCM_IS_WHVEC_ANY (w))
265 {
266 SCM *ptr;
267 SCM obj;
c014a02e
ML
268 long j;
269 long n;
d662820a
MD
270
271 obj = w;
272 ptr = SCM_VELTS (w);
bfa974f0 273 n = SCM_VECTOR_LENGTH (w);
d662820a
MD
274 for (j = 0; j < n; ++j)
275 {
276 SCM alist;
277
278 alist = ptr[j];
279 while ( SCM_CONSP (alist)
280 && !SCM_GCMARKP (alist)
281 && SCM_CONSP (SCM_CAR (alist)))
282 {
283 SCM_SETGCMARK (alist);
284 SCM_SETGCMARK (SCM_CAR (alist));
fd336365 285 alist = SCM_CDR (alist);
d662820a
MD
286 }
287 }
288 }
289 }
290
291 return 0;
292}
293
592996c9 294
d662820a 295static void *
e81d98ec
DH
296scm_scan_weak_vectors (void *dummy1 SCM_UNUSED,
297 void *dummy2 SCM_UNUSED,
298 void *dummy3 SCM_UNUSED)
d662820a
MD
299{
300 SCM *ptr, w;
301 for (w = scm_weak_vectors; !SCM_NULLP (w); w = SCM_WVECT_GC_CHAIN (w))
302 {
303 if (!SCM_IS_WHVEC_ANY (w))
304 {
305 register long j, n;
306
307 ptr = SCM_VELTS (w);
bfa974f0 308 n = SCM_VECTOR_LENGTH (w);
d662820a 309 for (j = 0; j < n; ++j)
406c7d90 310 if (SCM_FREE_CELL_P (ptr[j]))
d662820a
MD
311 ptr[j] = SCM_BOOL_F;
312 }
313 else /* if (SCM_IS_WHVEC_ANY (scm_weak_vectors[i])) */
314 {
315 SCM obj = w;
c014a02e
ML
316 register long n = SCM_VECTOR_LENGTH (w);
317 register long j;
d9dcd933
ML
318 int weak_keys = SCM_IS_WHVEC (obj) || SCM_IS_WHVEC_B (obj);
319 int weak_values = SCM_IS_WHVEC_V (obj) || SCM_IS_WHVEC_B (obj);
d662820a
MD
320
321 ptr = SCM_VELTS (w);
322
323 for (j = 0; j < n; ++j)
324 {
325 SCM * fixup;
326 SCM alist;
d662820a
MD
327
328 fixup = ptr + j;
329 alist = *fixup;
330
331 while ( SCM_CONSP (alist)
332 && SCM_CONSP (SCM_CAR (alist)))
333 {
334 SCM key;
335 SCM value;
336
337 key = SCM_CAAR (alist);
338 value = SCM_CDAR (alist);
406c7d90
DH
339 if ( (weak_keys && SCM_FREE_CELL_P (key))
340 || (weak_values && SCM_FREE_CELL_P (value)))
d662820a
MD
341 {
342 *fixup = SCM_CDR (alist);
343 }
344 else
345 fixup = SCM_CDRLOC (alist);
346 alist = SCM_CDR (alist);
347 }
348 }
349 }
350 }
351
352 return 0;
353}
354
0f2d19dd
JB
355\f
356
d662820a
MD
357void
358scm_weaks_prehistory ()
359{
360 scm_c_hook_add (&scm_before_mark_c_hook, scm_weak_vector_gc_init, 0, 0);
361 scm_c_hook_add (&scm_before_sweep_c_hook, scm_mark_weak_vector_spines, 0, 0);
362 scm_c_hook_add (&scm_after_sweep_c_hook, scm_scan_weak_vectors, 0, 0);
363}
364
592996c9 365
0f2d19dd
JB
366void
367scm_init_weaks ()
0f2d19dd 368{
8dc9439f 369#ifndef SCM_MAGIC_SNARFER
a0599745 370#include "libguile/weaks.x"
8dc9439f 371#endif
0f2d19dd
JB
372}
373
89e00824
ML
374
375/*
376 Local Variables:
377 c-file-style: "gnu"
378 End:
379*/