weaks.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /* Copyright (C) 1995,1996,1998, 2000, 2002 Free Software Foundation, Inc.
  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
  15. * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. * Boston, MA 02111-1307 USA
  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.
  40. * If you do not wish that, delete this exception notice. */
  41. #include <stdio.h>
  42. #include "libguile/_scm.h"
  43. #include "libguile/vectors.h"
  44. #include "libguile/validate.h"
  45. #include "libguile/weaks.h"
  46. /* {Weak Vectors}
  47. */
  48. SCM_DEFINE (scm_make_weak_vector, "make-weak-vector", 1, 1, 0,
  49. (SCM k, SCM fill),
  50. "Return a weak vector with @var{size} elements. If the optional\n"
  51. "argument @var{fill} is given, all entries in the vector will be set to\n"
  52. "@var{fill}. The default value for @var{fill} is the empty list.")
  53. #define FUNC_NAME s_scm_make_weak_vector
  54. {
  55. SCM v;
  56. v = scm_make_vector (scm_sum (k, SCM_MAKINUM (2)), fill);
  57. SCM_DEFER_INTS;
  58. SCM_SETLENGTH(v, SCM_INUM (k), scm_tc7_wvect);
  59. SCM_SETVELTS(v, SCM_VELTS(v) + 2);
  60. SCM_VELTS(v)[-2] = SCM_EOL;
  61. SCM_UNPACK (SCM_VELTS (v)[-1]) = 0;
  62. SCM_ALLOW_INTS;
  63. return v;
  64. }
  65. #undef FUNC_NAME
  66. SCM_REGISTER_PROC(s_list_to_weak_vector, "list->weak-vector", 1, 0, 0, scm_weak_vector);
  67. SCM_DEFINE (scm_weak_vector, "weak-vector", 0, 0, 1,
  68. (SCM l),
  69. "@deffnx primitive list->weak-vector l\n"
  70. "Construct a weak vector from a list: @code{weak-vector} uses the list of\n"
  71. "its arguments while @code{list->weak-vector} uses its only argument\n"
  72. "@var{l} (a list) to construct a weak vector the same way\n"
  73. "@code{vector->list} would.")
  74. #define FUNC_NAME s_scm_weak_vector
  75. {
  76. SCM res;
  77. register SCM *data;
  78. long i;
  79. i = scm_ilength (l);
  80. SCM_ASSERT (i >= 0, l, SCM_ARG1, FUNC_NAME);
  81. res = scm_make_weak_vector (SCM_MAKINUM (i), SCM_UNSPECIFIED);
  82. data = SCM_VELTS (res);
  83. for (;
  84. i && SCM_CONSP (l);
  85. --i, l = SCM_CDR (l))
  86. *data++ = SCM_CAR (l);
  87. return res;
  88. }
  89. #undef FUNC_NAME
  90. SCM_DEFINE (scm_weak_vector_p, "weak-vector?", 1, 0, 0,
  91. (SCM x),
  92. "Return @var{#t} if @var{obj} is a weak vector. Note that all weak\n"
  93. "hashes are also weak vectors.")
  94. #define FUNC_NAME s_scm_weak_vector_p
  95. {
  96. return SCM_BOOL(SCM_WVECTP (x) && !SCM_IS_WHVEC (x));
  97. }
  98. #undef FUNC_NAME
  99. SCM_DEFINE (scm_make_weak_key_hash_table, "make-weak-key-hash-table", 1, 0, 0,
  100. (SCM k),
  101. "@deffnx primitive make-weak-value-hash-table size\n"
  102. "@deffnx primitive make-doubly-weak-hash-table size\n"
  103. "Return a weak hash table with @var{size} buckets. As with any hash\n"
  104. "table, choosing a good size for the table requires some caution.\n\n"
  105. "You can modify weak hash tables in exactly the same way you would modify\n"
  106. "regular hash tables. (@pxref{Hash Tables})")
  107. #define FUNC_NAME s_scm_make_weak_key_hash_table
  108. {
  109. SCM v;
  110. SCM_VALIDATE_INUM (1,k);
  111. v = scm_make_weak_vector (k, SCM_EOL);
  112. SCM_DEFER_INTS;
  113. SCM_UNPACK (SCM_VELTS (v)[-1]) = 1;
  114. SCM_ALLOW_INTS;
  115. return v;
  116. }
  117. #undef FUNC_NAME
  118. SCM_DEFINE (scm_make_weak_value_hash_table, "make-weak-value-hash-table", 1, 0, 0,
  119. (SCM k),
  120. "")
  121. #define FUNC_NAME s_scm_make_weak_value_hash_table
  122. {
  123. SCM v;
  124. SCM_VALIDATE_INUM (1,k);
  125. v = scm_make_weak_vector (k, SCM_EOL);
  126. SCM_DEFER_INTS;
  127. SCM_UNPACK (SCM_VELTS (v)[-1]) = 2;
  128. SCM_ALLOW_INTS;
  129. return v;
  130. }
  131. #undef FUNC_NAME
  132. SCM_DEFINE (scm_make_doubly_weak_hash_table, "make-doubly-weak-hash-table", 1, 0, 0,
  133. (SCM k),
  134. "")
  135. #define FUNC_NAME s_scm_make_doubly_weak_hash_table
  136. {
  137. SCM v;
  138. SCM_VALIDATE_INUM (1,k);
  139. v = scm_make_weak_vector (k, SCM_EOL);
  140. SCM_DEFER_INTS;
  141. SCM_UNPACK (SCM_VELTS (v)[-1]) = 3;
  142. SCM_ALLOW_INTS;
  143. return v;
  144. }
  145. #undef FUNC_NAME
  146. SCM_DEFINE (scm_weak_key_hash_table_p, "weak-key-hash-table?", 1, 0, 0,
  147. (SCM x),
  148. "@deffnx primitive weak-value-hash-table? obj\n"
  149. "@deffnx primitive doubly-weak-hash-table? obj\n"
  150. "Return @var{#t} if @var{obj} is the specified weak hash table. Note\n"
  151. "that a doubly weak hash table is neither a weak key nor a weak value\n"
  152. "hash table.")
  153. #define FUNC_NAME s_scm_weak_key_hash_table_p
  154. {
  155. return SCM_BOOL(SCM_WVECTP (x) && SCM_IS_WHVEC(x));
  156. }
  157. #undef FUNC_NAME
  158. SCM_DEFINE (scm_weak_value_hash_table_p, "weak-value-hash-table?", 1, 0, 0,
  159. (SCM x),
  160. "")
  161. #define FUNC_NAME s_scm_weak_value_hash_table_p
  162. {
  163. return SCM_BOOL(SCM_WVECTP (x) && SCM_IS_WHVEC_V(x));
  164. }
  165. #undef FUNC_NAME
  166. SCM_DEFINE (scm_doubly_weak_hash_table_p, "doubly-weak-hash-table?", 1, 0, 0,
  167. (SCM x),
  168. "")
  169. #define FUNC_NAME s_scm_doubly_weak_hash_table_p
  170. {
  171. return SCM_BOOL(SCM_WVECTP (x) && SCM_IS_WHVEC_B (x));
  172. }
  173. #undef FUNC_NAME
  174. static void *
  175. scm_weak_vector_gc_init (void *dummy1, void *dummy2, void *dummy3)
  176. {
  177. scm_weak_vectors = SCM_EOL;
  178. return 0;
  179. }
  180. static void *
  181. scm_mark_weak_vector_spines (void *dummy1, void *dummy2, void *dummy3)
  182. {
  183. SCM w;
  184. for (w = scm_weak_vectors; !SCM_NULLP (w); w = SCM_WVECT_GC_CHAIN (w))
  185. {
  186. if (SCM_IS_WHVEC_ANY (w))
  187. {
  188. SCM *ptr;
  189. SCM obj;
  190. int j;
  191. int n;
  192. obj = w;
  193. ptr = SCM_VELTS (w);
  194. n = SCM_LENGTH (w);
  195. for (j = 0; j < n; ++j)
  196. {
  197. SCM alist;
  198. alist = ptr[j];
  199. while ( SCM_CONSP (alist)
  200. && !SCM_GCMARKP (alist)
  201. && SCM_CONSP (SCM_CAR (alist)))
  202. {
  203. SCM_SETGCMARK (alist);
  204. SCM_SETGCMARK (SCM_CAR (alist));
  205. alist = SCM_GCCDR (alist);
  206. }
  207. }
  208. }
  209. }
  210. return 0;
  211. }
  212. static void *
  213. scm_scan_weak_vectors (void *dummy1, void *dummy2, void *dummy3)
  214. {
  215. SCM *ptr, w;
  216. for (w = scm_weak_vectors; !SCM_NULLP (w); w = SCM_WVECT_GC_CHAIN (w))
  217. {
  218. if (!SCM_IS_WHVEC_ANY (w))
  219. {
  220. register long j, n;
  221. ptr = SCM_VELTS (w);
  222. n = SCM_LENGTH (w);
  223. for (j = 0; j < n; ++j)
  224. if (SCM_FREEP (ptr[j]))
  225. ptr[j] = SCM_BOOL_F;
  226. }
  227. else /* if (SCM_IS_WHVEC_ANY (scm_weak_vectors[i])) */
  228. {
  229. SCM obj = w;
  230. register long n = SCM_LENGTH (w);
  231. register long j;
  232. ptr = SCM_VELTS (w);
  233. for (j = 0; j < n; ++j)
  234. {
  235. SCM * fixup;
  236. SCM alist;
  237. int weak_keys;
  238. int weak_values;
  239. weak_keys = SCM_IS_WHVEC (obj) || SCM_IS_WHVEC_B (obj);
  240. weak_values = SCM_IS_WHVEC_V (obj) || SCM_IS_WHVEC_B (obj);
  241. fixup = ptr + j;
  242. alist = *fixup;
  243. while ( SCM_CONSP (alist)
  244. && SCM_CONSP (SCM_CAR (alist)))
  245. {
  246. SCM key;
  247. SCM value;
  248. key = SCM_CAAR (alist);
  249. value = SCM_CDAR (alist);
  250. if ( (weak_keys && SCM_FREEP (key))
  251. || (weak_values && SCM_FREEP (value)))
  252. {
  253. *fixup = SCM_CDR (alist);
  254. }
  255. else
  256. fixup = SCM_CDRLOC (alist);
  257. alist = SCM_CDR (alist);
  258. }
  259. }
  260. }
  261. }
  262. return 0;
  263. }
  264. void
  265. scm_weaks_prehistory ()
  266. {
  267. scm_c_hook_add (&scm_before_mark_c_hook, scm_weak_vector_gc_init, 0, 0);
  268. scm_c_hook_add (&scm_before_sweep_c_hook, scm_mark_weak_vector_spines, 0, 0);
  269. scm_c_hook_add (&scm_after_sweep_c_hook, scm_scan_weak_vectors, 0, 0);
  270. }
  271. void
  272. scm_init_weaks ()
  273. {
  274. #include "libguile/weaks.x"
  275. }
  276. /*
  277. Local Variables:
  278. c-file-style: "gnu"
  279. End:
  280. */