2002-07-20 Han-Wen <hanwen@cs.uu.nl>
[bpt/guile.git] / libguile / fluids.c
CommitLineData
22a52da1 1/* Copyright (C) 1996,1997,2000,2001 Free Software Foundation, Inc.
9482a297
MV
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, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE 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 the GUILE 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 the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, 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 them.
37 *
38 * If you write modifications of your own for GUILE, 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
1bbd0b84
GB
42
43
a0599745
MD
44#include "libguile/_scm.h"
45#include "libguile/print.h"
46#include "libguile/smob.h"
47#include "libguile/dynwind.h"
48#include "libguile/fluids.h"
49#include "libguile/alist.h"
50#include "libguile/eval.h"
51#include "libguile/ports.h"
143e0902 52#include "libguile/deprecation.h"
c96d76b8 53#include "libguile/lang.h"
9482a297
MV
54
55#define INITIAL_FLUIDS 10
a0599745 56#include "libguile/validate.h"
9482a297 57
c014a02e 58static volatile long n_fluids;
92c2555f 59scm_t_bits scm_tc16_fluid;
9482a297
MV
60
61SCM
62scm_make_initial_fluids ()
63{
00ffa0e7 64 return scm_c_make_vector (INITIAL_FLUIDS, SCM_BOOL_F);
9482a297
MV
65}
66
9482a297 67static void
ed4d7cee 68grow_fluids (scm_root_state *root_state, int new_length)
9482a297
MV
69{
70 SCM old_fluids, new_fluids;
c014a02e 71 long old_length, i;
9482a297
MV
72
73 old_fluids = root_state->fluids;
bfa974f0 74 old_length = SCM_VECTOR_LENGTH (old_fluids);
00ffa0e7 75 new_fluids = scm_c_make_vector (new_length, SCM_BOOL_F);
9482a297
MV
76 i = 0;
77 while (i < old_length)
78 {
34d19ef6 79 SCM_VECTOR_SET (new_fluids, i, SCM_VELTS(old_fluids)[i]);
9482a297
MV
80 i++;
81 }
82 while (i < new_length)
83 {
34d19ef6 84 SCM_VECTOR_SET (new_fluids, i, SCM_BOOL_F);
9482a297
MV
85 i++;
86 }
87
88 root_state->fluids = new_fluids;
89}
90
91void
6e8d25a6 92scm_copy_fluids (scm_root_state *root_state)
9482a297 93{
bfa974f0 94 grow_fluids (root_state, SCM_VECTOR_LENGTH (root_state->fluids));
9482a297
MV
95}
96
9482a297 97static int
e81d98ec 98fluid_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
9482a297 99{
ed4d7cee
GB
100 scm_puts ("#<fluid ", port);
101 scm_intprint ((int) SCM_FLUID_NUM (exp), 10, port);
102 scm_putc ('>', port);
103 return 1;
9482a297
MV
104}
105
c014a02e 106static long
ed4d7cee 107next_fluid_num ()
9482a297 108{
c014a02e 109 long n;
216eedfc 110 SCM_CRITICAL_SECTION_START;
9482a297 111 n = n_fluids++;
216eedfc 112 SCM_CRITICAL_SECTION_END;
9482a297
MV
113 return n;
114}
115
a1ec6916 116SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0,
ed4d7cee
GB
117 (),
118 "Return a newly created fluid.\n"
119 "Fluids are objects of a certain type (a smob) that can hold one SCM\n"
120 "value per dynamic root. That is, modifications to this value are\n"
121 "only visible to code that executes within the same dynamic root as\n"
122 "the modifying code. When a new dynamic root is constructed, it\n"
123 "inherits the values from its parent. Because each thread executes\n"
124 "in its own dynamic root, you can use fluids for thread local storage.")
1bbd0b84 125#define FUNC_NAME s_scm_make_fluid
9482a297 126{
c014a02e 127 long n;
9482a297 128
9482a297 129 n = next_fluid_num ();
23a62151 130 SCM_RETURN_NEWSMOB (scm_tc16_fluid, n);
9482a297 131}
1bbd0b84 132#undef FUNC_NAME
9482a297 133
a1ec6916 134SCM_DEFINE (scm_fluid_p, "fluid?", 1, 0, 0,
ed4d7cee 135 (SCM obj),
1e6808ea
MG
136 "Return @code{#t} iff @var{obj} is a fluid; otherwise, return\n"
137 "@code{#f}.")
1bbd0b84 138#define FUNC_NAME s_scm_fluid_p
b3460a50 139{
ed4d7cee 140 return SCM_BOOL(SCM_FLUIDP (obj));
b3460a50 141}
1bbd0b84 142#undef FUNC_NAME
b3460a50 143
a1ec6916 144SCM_DEFINE (scm_fluid_ref, "fluid-ref", 1, 0, 0,
ed4d7cee 145 (SCM fluid),
1e6808ea
MG
146 "Return the value associated with @var{fluid} in the current\n"
147 "dynamic root. If @var{fluid} has not been set, then return\n"
148 "@code{#f}.")
1bbd0b84 149#define FUNC_NAME s_scm_fluid_ref
9482a297 150{
5843e5c9 151 unsigned long int n;
9482a297 152
ed4d7cee 153 SCM_VALIDATE_FLUID (1, fluid);
ed4d7cee 154 n = SCM_FLUID_NUM (fluid);
9482a297 155
bfa974f0 156 if (SCM_VECTOR_LENGTH (scm_root->fluids) <= n)
9482a297 157 grow_fluids (scm_root, n+1);
7e73eaee 158 return SCM_VELTS (scm_root->fluids)[n];
9482a297 159}
1bbd0b84 160#undef FUNC_NAME
9482a297 161
a1ec6916 162SCM_DEFINE (scm_fluid_set_x, "fluid-set!", 2, 0, 0,
ed4d7cee
GB
163 (SCM fluid, SCM value),
164 "Set the value associated with @var{fluid} in the current dynamic root.")
1bbd0b84 165#define FUNC_NAME s_scm_fluid_set_x
9482a297 166{
5843e5c9 167 unsigned long int n;
9482a297 168
ed4d7cee
GB
169 SCM_VALIDATE_FLUID (1, fluid);
170 n = SCM_FLUID_NUM (fluid);
9482a297 171
bfa974f0 172 if (SCM_VECTOR_LENGTH (scm_root->fluids) <= n)
9482a297 173 grow_fluids (scm_root, n+1);
34d19ef6 174 SCM_VECTOR_SET (scm_root->fluids, n, value);
86f9f9ae 175 return SCM_UNSPECIFIED;
9482a297 176}
1bbd0b84 177#undef FUNC_NAME
9482a297 178
b3460a50 179void
1bbd0b84 180scm_swap_fluids (SCM fluids, SCM vals)
b3460a50 181{
c96d76b8 182 while (!SCM_NULL_OR_NIL_P (fluids))
b3460a50
MV
183 {
184 SCM fl = SCM_CAR (fluids);
185 SCM old_val = scm_fluid_ref (fl);
186 scm_fluid_set_x (fl, SCM_CAR (vals));
187 SCM_SETCAR (vals, old_val);
188 fluids = SCM_CDR (fluids);
189 vals = SCM_CDR (vals);
190 }
191}
192
193/* Swap the fluid values in reverse order. This is important when the
194same fluid appears multiple times in the fluids list. */
195
196void
1bbd0b84 197scm_swap_fluids_reverse (SCM fluids, SCM vals)
b3460a50 198{
c96d76b8 199 if (!SCM_NULL_OR_NIL_P (fluids))
b3460a50
MV
200 {
201 SCM fl, old_val;
202
203 scm_swap_fluids_reverse (SCM_CDR (fluids), SCM_CDR (vals));
204 fl = SCM_CAR (fluids);
205 old_val = scm_fluid_ref (fl);
206 scm_fluid_set_x (fl, SCM_CAR (vals));
207 SCM_SETCAR (vals, old_val);
208 }
209}
210
1bbd0b84
GB
211
212static SCM
213apply_thunk (void *thunk)
214{
fdc28395 215 return scm_call_0 (SCM_PACK (thunk));
1bbd0b84
GB
216}
217
a1ec6916 218SCM_DEFINE (scm_with_fluids, "with-fluids*", 3, 0, 0,
ed4d7cee
GB
219 (SCM fluids, SCM values, SCM thunk),
220 "Set @var{fluids} to @var{values} temporary, and call @var{thunk}.\n"
221 "@var{fluids} must be a list of fluids and @var{values} must be the same\n"
222 "number of their values to be applied. Each substitution is done\n"
223 "one after another. @var{thunk} must be a procedure with no argument.")
1bbd0b84
GB
224#define FUNC_NAME s_scm_with_fluids
225{
143e0902 226 return scm_c_with_fluids (fluids, values, apply_thunk, (void *) SCM_UNPACK (thunk));
1bbd0b84
GB
227}
228#undef FUNC_NAME
b3460a50
MV
229
230SCM
143e0902
MV
231scm_c_with_fluids (SCM fluids, SCM values, SCM (*cproc) (), void *cdata)
232#define FUNC_NAME "scm_c_with_fluids"
b3460a50
MV
233{
234 SCM ans;
c014a02e 235 long flen, vlen;
b3460a50 236
c1bfcf60 237 SCM_VALIDATE_LIST_COPYLEN (1, fluids, flen);
ed4d7cee 238 SCM_VALIDATE_LIST_COPYLEN (2, values, vlen);
b3460a50 239 if (flen != vlen)
ed4d7cee 240 scm_out_of_range (s_scm_with_fluids, values);
b3460a50 241
ed4d7cee
GB
242 scm_swap_fluids (fluids, values);
243 scm_dynwinds = scm_acons (fluids, values, scm_dynwinds);
b3460a50
MV
244 ans = cproc (cdata);
245 scm_dynwinds = SCM_CDR (scm_dynwinds);
ed4d7cee 246 scm_swap_fluids_reverse (fluids, values);
b3460a50
MV
247 return ans;
248}
c1bfcf60 249#undef FUNC_NAME
b3460a50 250
143e0902
MV
251SCM
252scm_c_with_fluid (SCM fluid, SCM value, SCM (*cproc) (), void *cdata)
253#define FUNC_NAME "scm_c_with_fluid"
254{
df1ad0d1 255 return scm_c_with_fluids (scm_list_1 (fluid), scm_list_1 (value),
143e0902
MV
256 cproc, cdata);
257}
258#undef FUNC_NAME
b3460a50 259
9482a297
MV
260void
261scm_init_fluids ()
262{
e841c3e0
KN
263 scm_tc16_fluid = scm_make_smob_type ("fluid", 0);
264 scm_set_smob_print (scm_tc16_fluid, fluid_print);
a0599745 265#include "libguile/fluids.x"
9482a297 266}
89e00824
ML
267
268/*
269 Local Variables:
270 c-file-style: "gnu"
271 End:
272*/