(gh_uniform_vector_length): Properly use scm_c_uniform_vector_length
[bpt/guile.git] / libguile / fluids.c
CommitLineData
16c5cac2 1/* Copyright (C) 1996,1997,2000,2001, 2004 Free Software Foundation, Inc.
9482a297 2 *
73be1d9e
MV
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
9482a297 7 *
73be1d9e
MV
8 * This library 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 GNU
11 * Lesser General Public License for more details.
9482a297 12 *
73be1d9e
MV
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
9482a297 17
1bbd0b84
GB
18
19
a0599745
MD
20#include "libguile/_scm.h"
21#include "libguile/print.h"
22#include "libguile/smob.h"
23#include "libguile/dynwind.h"
24#include "libguile/fluids.h"
25#include "libguile/alist.h"
26#include "libguile/eval.h"
27#include "libguile/ports.h"
143e0902 28#include "libguile/deprecation.h"
c96d76b8 29#include "libguile/lang.h"
9482a297
MV
30
31#define INITIAL_FLUIDS 10
a0599745 32#include "libguile/validate.h"
9482a297 33
c014a02e 34static volatile long n_fluids;
92c2555f 35scm_t_bits scm_tc16_fluid;
9482a297
MV
36
37SCM
a52dbe01 38scm_i_make_initial_fluids ()
9482a297 39{
00ffa0e7 40 return scm_c_make_vector (INITIAL_FLUIDS, SCM_BOOL_F);
9482a297
MV
41}
42
9482a297 43static void
ed4d7cee 44grow_fluids (scm_root_state *root_state, int new_length)
9482a297
MV
45{
46 SCM old_fluids, new_fluids;
c014a02e 47 long old_length, i;
9482a297
MV
48
49 old_fluids = root_state->fluids;
bfa974f0 50 old_length = SCM_VECTOR_LENGTH (old_fluids);
00ffa0e7 51 new_fluids = scm_c_make_vector (new_length, SCM_BOOL_F);
9482a297
MV
52 i = 0;
53 while (i < old_length)
54 {
34d19ef6 55 SCM_VECTOR_SET (new_fluids, i, SCM_VELTS(old_fluids)[i]);
9482a297
MV
56 i++;
57 }
58 while (i < new_length)
59 {
34d19ef6 60 SCM_VECTOR_SET (new_fluids, i, SCM_BOOL_F);
9482a297
MV
61 i++;
62 }
63
64 root_state->fluids = new_fluids;
65}
66
67void
a52dbe01 68scm_i_copy_fluids (scm_root_state *root_state)
9482a297 69{
bfa974f0 70 grow_fluids (root_state, SCM_VECTOR_LENGTH (root_state->fluids));
9482a297
MV
71}
72
9482a297 73static int
e81d98ec 74fluid_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
9482a297 75{
ed4d7cee
GB
76 scm_puts ("#<fluid ", port);
77 scm_intprint ((int) SCM_FLUID_NUM (exp), 10, port);
78 scm_putc ('>', port);
79 return 1;
9482a297
MV
80}
81
c014a02e 82static long
ed4d7cee 83next_fluid_num ()
9482a297 84{
c014a02e 85 long n;
216eedfc 86 SCM_CRITICAL_SECTION_START;
9482a297 87 n = n_fluids++;
216eedfc 88 SCM_CRITICAL_SECTION_END;
9482a297
MV
89 return n;
90}
91
a1ec6916 92SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0,
ed4d7cee
GB
93 (),
94 "Return a newly created fluid.\n"
95 "Fluids are objects of a certain type (a smob) that can hold one SCM\n"
96 "value per dynamic root. That is, modifications to this value are\n"
97 "only visible to code that executes within the same dynamic root as\n"
98 "the modifying code. When a new dynamic root is constructed, it\n"
99 "inherits the values from its parent. Because each thread executes\n"
100 "in its own dynamic root, you can use fluids for thread local storage.")
1bbd0b84 101#define FUNC_NAME s_scm_make_fluid
9482a297 102{
c014a02e 103 long n;
9482a297 104
9482a297 105 n = next_fluid_num ();
23a62151 106 SCM_RETURN_NEWSMOB (scm_tc16_fluid, n);
9482a297 107}
1bbd0b84 108#undef FUNC_NAME
9482a297 109
a1ec6916 110SCM_DEFINE (scm_fluid_p, "fluid?", 1, 0, 0,
ed4d7cee 111 (SCM obj),
1e6808ea
MG
112 "Return @code{#t} iff @var{obj} is a fluid; otherwise, return\n"
113 "@code{#f}.")
1bbd0b84 114#define FUNC_NAME s_scm_fluid_p
b3460a50 115{
7888309b 116 return scm_from_bool(SCM_FLUIDP (obj));
b3460a50 117}
1bbd0b84 118#undef FUNC_NAME
b3460a50 119
a1ec6916 120SCM_DEFINE (scm_fluid_ref, "fluid-ref", 1, 0, 0,
ed4d7cee 121 (SCM fluid),
1e6808ea
MG
122 "Return the value associated with @var{fluid} in the current\n"
123 "dynamic root. If @var{fluid} has not been set, then return\n"
124 "@code{#f}.")
1bbd0b84 125#define FUNC_NAME s_scm_fluid_ref
9482a297 126{
5843e5c9 127 unsigned long int n;
9482a297 128
ed4d7cee 129 SCM_VALIDATE_FLUID (1, fluid);
ed4d7cee 130 n = SCM_FLUID_NUM (fluid);
9482a297 131
bfa974f0 132 if (SCM_VECTOR_LENGTH (scm_root->fluids) <= n)
9482a297 133 grow_fluids (scm_root, n+1);
7e73eaee 134 return SCM_VELTS (scm_root->fluids)[n];
9482a297 135}
1bbd0b84 136#undef FUNC_NAME
9482a297 137
a1ec6916 138SCM_DEFINE (scm_fluid_set_x, "fluid-set!", 2, 0, 0,
ed4d7cee
GB
139 (SCM fluid, SCM value),
140 "Set the value associated with @var{fluid} in the current dynamic root.")
1bbd0b84 141#define FUNC_NAME s_scm_fluid_set_x
9482a297 142{
5843e5c9 143 unsigned long int n;
9482a297 144
ed4d7cee
GB
145 SCM_VALIDATE_FLUID (1, fluid);
146 n = SCM_FLUID_NUM (fluid);
9482a297 147
bfa974f0 148 if (SCM_VECTOR_LENGTH (scm_root->fluids) <= n)
9482a297 149 grow_fluids (scm_root, n+1);
34d19ef6 150 SCM_VECTOR_SET (scm_root->fluids, n, value);
86f9f9ae 151 return SCM_UNSPECIFIED;
9482a297 152}
1bbd0b84 153#undef FUNC_NAME
9482a297 154
bebd3fba
MV
155static void
156swap_fluids (SCM data)
b3460a50 157{
bebd3fba
MV
158 SCM fluids = SCM_CAR (data), vals = SCM_CDR (data);
159
c96d76b8 160 while (!SCM_NULL_OR_NIL_P (fluids))
b3460a50
MV
161 {
162 SCM fl = SCM_CAR (fluids);
163 SCM old_val = scm_fluid_ref (fl);
164 scm_fluid_set_x (fl, SCM_CAR (vals));
165 SCM_SETCAR (vals, old_val);
166 fluids = SCM_CDR (fluids);
167 vals = SCM_CDR (vals);
168 }
169}
170
171/* Swap the fluid values in reverse order. This is important when the
172same fluid appears multiple times in the fluids list. */
173
bebd3fba
MV
174static void
175swap_fluids_reverse_aux (SCM fluids, SCM vals)
b3460a50 176{
c96d76b8 177 if (!SCM_NULL_OR_NIL_P (fluids))
b3460a50
MV
178 {
179 SCM fl, old_val;
180
bebd3fba 181 swap_fluids_reverse_aux (SCM_CDR (fluids), SCM_CDR (vals));
b3460a50
MV
182 fl = SCM_CAR (fluids);
183 old_val = scm_fluid_ref (fl);
184 scm_fluid_set_x (fl, SCM_CAR (vals));
185 SCM_SETCAR (vals, old_val);
186 }
187}
188
bebd3fba
MV
189static void
190swap_fluids_reverse (SCM data)
191{
192 swap_fluids_reverse_aux (SCM_CAR (data), SCM_CDR (data));
193}
1bbd0b84
GB
194
195static SCM
196apply_thunk (void *thunk)
197{
fdc28395 198 return scm_call_0 (SCM_PACK (thunk));
1bbd0b84
GB
199}
200
a1ec6916 201SCM_DEFINE (scm_with_fluids, "with-fluids*", 3, 0, 0,
ed4d7cee
GB
202 (SCM fluids, SCM values, SCM thunk),
203 "Set @var{fluids} to @var{values} temporary, and call @var{thunk}.\n"
204 "@var{fluids} must be a list of fluids and @var{values} must be the same\n"
205 "number of their values to be applied. Each substitution is done\n"
206 "one after another. @var{thunk} must be a procedure with no argument.")
1bbd0b84
GB
207#define FUNC_NAME s_scm_with_fluids
208{
bebd3fba
MV
209 return scm_c_with_fluids (fluids, values,
210 apply_thunk, (void *) SCM_UNPACK (thunk));
1bbd0b84
GB
211}
212#undef FUNC_NAME
b3460a50
MV
213
214SCM
143e0902
MV
215scm_c_with_fluids (SCM fluids, SCM values, SCM (*cproc) (), void *cdata)
216#define FUNC_NAME "scm_c_with_fluids"
b3460a50 217{
bebd3fba 218 SCM ans, data;
c014a02e 219 long flen, vlen;
b3460a50 220
c1bfcf60 221 SCM_VALIDATE_LIST_COPYLEN (1, fluids, flen);
ed4d7cee 222 SCM_VALIDATE_LIST_COPYLEN (2, values, vlen);
b3460a50 223 if (flen != vlen)
ed4d7cee 224 scm_out_of_range (s_scm_with_fluids, values);
b3460a50 225
bebd3fba
MV
226 if (flen == 1)
227 return scm_c_with_fluid (SCM_CAR (fluids), SCM_CAR (values),
228 cproc, cdata);
229
230 data = scm_cons (fluids, values);
231 scm_frame_begin (SCM_F_FRAME_REWINDABLE);
16c5cac2
MV
232 scm_frame_rewind_handler_with_scm (swap_fluids, data,
233 SCM_F_WIND_EXPLICITLY);
234 scm_frame_unwind_handler_with_scm (swap_fluids_reverse, data,
235 SCM_F_WIND_EXPLICITLY);
b3460a50 236 ans = cproc (cdata);
bebd3fba 237 scm_frame_end ();
b3460a50
MV
238 return ans;
239}
c1bfcf60 240#undef FUNC_NAME
b3460a50 241
bebd3fba
MV
242SCM_DEFINE (scm_with_fluid, "with-fluid*", 3, 0, 0,
243 (SCM fluid, SCM value, SCM thunk),
244 "Set @var{fluid} to @var{value} temporarily, and call @var{thunk}.\n"
245 "@var{thunk} must be a procedure with no argument.")
246#define FUNC_NAME s_scm_with_fluid
247{
248 return scm_c_with_fluid (fluid, value,
249 apply_thunk, (void *) SCM_UNPACK (thunk));
250}
251#undef FUNC_NAME
252
143e0902
MV
253SCM
254scm_c_with_fluid (SCM fluid, SCM value, SCM (*cproc) (), void *cdata)
255#define FUNC_NAME "scm_c_with_fluid"
256{
bebd3fba
MV
257 SCM ans;
258
259 scm_frame_begin (SCM_F_FRAME_REWINDABLE);
260 scm_frame_fluid (fluid, value);
261 ans = cproc (cdata);
262 scm_frame_end ();
263 return ans;
143e0902
MV
264}
265#undef FUNC_NAME
b3460a50 266
ef20bf70
MV
267static void
268swap_fluid (SCM data)
269{
270 SCM f = SCM_CAR (data);
271 SCM t = scm_fluid_ref (f);
272 scm_fluid_set_x (f, SCM_CDR (data));
273 SCM_SETCDR (data, t);
274}
275
276void
277scm_frame_fluid (SCM fluid, SCM value)
278{
279 SCM data = scm_cons (fluid, value);
16c5cac2
MV
280 scm_frame_rewind_handler_with_scm (swap_fluid, data, SCM_F_WIND_EXPLICITLY);
281 scm_frame_unwind_handler_with_scm (swap_fluid, data, SCM_F_WIND_EXPLICITLY);
ef20bf70
MV
282}
283
9482a297
MV
284void
285scm_init_fluids ()
286{
e841c3e0
KN
287 scm_tc16_fluid = scm_make_smob_type ("fluid", 0);
288 scm_set_smob_print (scm_tc16_fluid, fluid_print);
a0599745 289#include "libguile/fluids.x"
9482a297 290}
89e00824
ML
291
292/*
293 Local Variables:
294 c-file-style: "gnu"
295 End:
296*/