(scm_frame_current_module): New.
[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;
4057a3e0 50 old_length = SCM_SIMPLE_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 {
4057a3e0
MV
55 SCM_SIMPLE_VECTOR_SET (new_fluids, i,
56 SCM_SIMPLE_VECTOR_REF (old_fluids, i));
9482a297
MV
57 i++;
58 }
59 while (i < new_length)
60 {
4057a3e0 61 SCM_SIMPLE_VECTOR_SET (new_fluids, i, SCM_BOOL_F);
9482a297
MV
62 i++;
63 }
64
65 root_state->fluids = new_fluids;
66}
67
68void
a52dbe01 69scm_i_copy_fluids (scm_root_state *root_state)
9482a297 70{
4057a3e0 71 grow_fluids (root_state, SCM_SIMPLE_VECTOR_LENGTH (root_state->fluids));
9482a297
MV
72}
73
9482a297 74static int
e81d98ec 75fluid_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
9482a297 76{
ed4d7cee
GB
77 scm_puts ("#<fluid ", port);
78 scm_intprint ((int) SCM_FLUID_NUM (exp), 10, port);
79 scm_putc ('>', port);
80 return 1;
9482a297
MV
81}
82
c014a02e 83static long
ed4d7cee 84next_fluid_num ()
9482a297 85{
c014a02e 86 long n;
216eedfc 87 SCM_CRITICAL_SECTION_START;
9482a297 88 n = n_fluids++;
216eedfc 89 SCM_CRITICAL_SECTION_END;
9482a297
MV
90 return n;
91}
92
a1ec6916 93SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0,
ed4d7cee
GB
94 (),
95 "Return a newly created fluid.\n"
96 "Fluids are objects of a certain type (a smob) that can hold one SCM\n"
97 "value per dynamic root. That is, modifications to this value are\n"
98 "only visible to code that executes within the same dynamic root as\n"
99 "the modifying code. When a new dynamic root is constructed, it\n"
100 "inherits the values from its parent. Because each thread executes\n"
101 "in its own dynamic root, you can use fluids for thread local storage.")
1bbd0b84 102#define FUNC_NAME s_scm_make_fluid
9482a297 103{
c014a02e 104 long n;
9482a297 105
9482a297 106 n = next_fluid_num ();
23a62151 107 SCM_RETURN_NEWSMOB (scm_tc16_fluid, n);
9482a297 108}
1bbd0b84 109#undef FUNC_NAME
9482a297 110
a1ec6916 111SCM_DEFINE (scm_fluid_p, "fluid?", 1, 0, 0,
ed4d7cee 112 (SCM obj),
1e6808ea
MG
113 "Return @code{#t} iff @var{obj} is a fluid; otherwise, return\n"
114 "@code{#f}.")
1bbd0b84 115#define FUNC_NAME s_scm_fluid_p
b3460a50 116{
7888309b 117 return scm_from_bool(SCM_FLUIDP (obj));
b3460a50 118}
1bbd0b84 119#undef FUNC_NAME
b3460a50 120
a1ec6916 121SCM_DEFINE (scm_fluid_ref, "fluid-ref", 1, 0, 0,
ed4d7cee 122 (SCM fluid),
1e6808ea
MG
123 "Return the value associated with @var{fluid} in the current\n"
124 "dynamic root. If @var{fluid} has not been set, then return\n"
125 "@code{#f}.")
1bbd0b84 126#define FUNC_NAME s_scm_fluid_ref
9482a297 127{
5843e5c9 128 unsigned long int n;
9482a297 129
ed4d7cee 130 SCM_VALIDATE_FLUID (1, fluid);
ed4d7cee 131 n = SCM_FLUID_NUM (fluid);
9482a297 132
4057a3e0 133 if (SCM_SIMPLE_VECTOR_LENGTH (scm_root->fluids) <= n)
9482a297 134 grow_fluids (scm_root, n+1);
4057a3e0 135 return SCM_SIMPLE_VECTOR_REF (scm_root->fluids, n);
9482a297 136}
1bbd0b84 137#undef FUNC_NAME
9482a297 138
a1ec6916 139SCM_DEFINE (scm_fluid_set_x, "fluid-set!", 2, 0, 0,
ed4d7cee
GB
140 (SCM fluid, SCM value),
141 "Set the value associated with @var{fluid} in the current dynamic root.")
1bbd0b84 142#define FUNC_NAME s_scm_fluid_set_x
9482a297 143{
5843e5c9 144 unsigned long int n;
9482a297 145
ed4d7cee
GB
146 SCM_VALIDATE_FLUID (1, fluid);
147 n = SCM_FLUID_NUM (fluid);
9482a297 148
4057a3e0 149 if (SCM_SIMPLE_VECTOR_LENGTH (scm_root->fluids) <= n)
9482a297 150 grow_fluids (scm_root, n+1);
4057a3e0 151 SCM_SIMPLE_VECTOR_SET (scm_root->fluids, n, value);
86f9f9ae 152 return SCM_UNSPECIFIED;
9482a297 153}
1bbd0b84 154#undef FUNC_NAME
9482a297 155
bebd3fba
MV
156static void
157swap_fluids (SCM data)
b3460a50 158{
bebd3fba
MV
159 SCM fluids = SCM_CAR (data), vals = SCM_CDR (data);
160
c96d76b8 161 while (!SCM_NULL_OR_NIL_P (fluids))
b3460a50
MV
162 {
163 SCM fl = SCM_CAR (fluids);
164 SCM old_val = scm_fluid_ref (fl);
165 scm_fluid_set_x (fl, SCM_CAR (vals));
166 SCM_SETCAR (vals, old_val);
167 fluids = SCM_CDR (fluids);
168 vals = SCM_CDR (vals);
169 }
170}
171
172/* Swap the fluid values in reverse order. This is important when the
173same fluid appears multiple times in the fluids list. */
174
bebd3fba
MV
175static void
176swap_fluids_reverse_aux (SCM fluids, SCM vals)
b3460a50 177{
c96d76b8 178 if (!SCM_NULL_OR_NIL_P (fluids))
b3460a50
MV
179 {
180 SCM fl, old_val;
181
bebd3fba 182 swap_fluids_reverse_aux (SCM_CDR (fluids), SCM_CDR (vals));
b3460a50
MV
183 fl = SCM_CAR (fluids);
184 old_val = scm_fluid_ref (fl);
185 scm_fluid_set_x (fl, SCM_CAR (vals));
186 SCM_SETCAR (vals, old_val);
187 }
188}
189
bebd3fba
MV
190static void
191swap_fluids_reverse (SCM data)
192{
193 swap_fluids_reverse_aux (SCM_CAR (data), SCM_CDR (data));
194}
1bbd0b84
GB
195
196static SCM
197apply_thunk (void *thunk)
198{
fdc28395 199 return scm_call_0 (SCM_PACK (thunk));
1bbd0b84
GB
200}
201
a1ec6916 202SCM_DEFINE (scm_with_fluids, "with-fluids*", 3, 0, 0,
ed4d7cee
GB
203 (SCM fluids, SCM values, SCM thunk),
204 "Set @var{fluids} to @var{values} temporary, and call @var{thunk}.\n"
205 "@var{fluids} must be a list of fluids and @var{values} must be the same\n"
206 "number of their values to be applied. Each substitution is done\n"
207 "one after another. @var{thunk} must be a procedure with no argument.")
1bbd0b84
GB
208#define FUNC_NAME s_scm_with_fluids
209{
bebd3fba
MV
210 return scm_c_with_fluids (fluids, values,
211 apply_thunk, (void *) SCM_UNPACK (thunk));
1bbd0b84
GB
212}
213#undef FUNC_NAME
b3460a50
MV
214
215SCM
143e0902
MV
216scm_c_with_fluids (SCM fluids, SCM values, SCM (*cproc) (), void *cdata)
217#define FUNC_NAME "scm_c_with_fluids"
b3460a50 218{
bebd3fba 219 SCM ans, data;
c014a02e 220 long flen, vlen;
b3460a50 221
c1bfcf60 222 SCM_VALIDATE_LIST_COPYLEN (1, fluids, flen);
ed4d7cee 223 SCM_VALIDATE_LIST_COPYLEN (2, values, vlen);
b3460a50 224 if (flen != vlen)
ed4d7cee 225 scm_out_of_range (s_scm_with_fluids, values);
b3460a50 226
bebd3fba
MV
227 if (flen == 1)
228 return scm_c_with_fluid (SCM_CAR (fluids), SCM_CAR (values),
229 cproc, cdata);
230
231 data = scm_cons (fluids, values);
232 scm_frame_begin (SCM_F_FRAME_REWINDABLE);
16c5cac2
MV
233 scm_frame_rewind_handler_with_scm (swap_fluids, data,
234 SCM_F_WIND_EXPLICITLY);
235 scm_frame_unwind_handler_with_scm (swap_fluids_reverse, data,
236 SCM_F_WIND_EXPLICITLY);
b3460a50 237 ans = cproc (cdata);
bebd3fba 238 scm_frame_end ();
b3460a50
MV
239 return ans;
240}
c1bfcf60 241#undef FUNC_NAME
b3460a50 242
bebd3fba
MV
243SCM_DEFINE (scm_with_fluid, "with-fluid*", 3, 0, 0,
244 (SCM fluid, SCM value, SCM thunk),
245 "Set @var{fluid} to @var{value} temporarily, and call @var{thunk}.\n"
246 "@var{thunk} must be a procedure with no argument.")
247#define FUNC_NAME s_scm_with_fluid
248{
249 return scm_c_with_fluid (fluid, value,
250 apply_thunk, (void *) SCM_UNPACK (thunk));
251}
252#undef FUNC_NAME
253
143e0902
MV
254SCM
255scm_c_with_fluid (SCM fluid, SCM value, SCM (*cproc) (), void *cdata)
256#define FUNC_NAME "scm_c_with_fluid"
257{
bebd3fba
MV
258 SCM ans;
259
260 scm_frame_begin (SCM_F_FRAME_REWINDABLE);
261 scm_frame_fluid (fluid, value);
262 ans = cproc (cdata);
263 scm_frame_end ();
264 return ans;
143e0902
MV
265}
266#undef FUNC_NAME
b3460a50 267
ef20bf70
MV
268static void
269swap_fluid (SCM data)
270{
271 SCM f = SCM_CAR (data);
272 SCM t = scm_fluid_ref (f);
273 scm_fluid_set_x (f, SCM_CDR (data));
274 SCM_SETCDR (data, t);
275}
276
277void
278scm_frame_fluid (SCM fluid, SCM value)
279{
280 SCM data = scm_cons (fluid, value);
16c5cac2
MV
281 scm_frame_rewind_handler_with_scm (swap_fluid, data, SCM_F_WIND_EXPLICITLY);
282 scm_frame_unwind_handler_with_scm (swap_fluid, data, SCM_F_WIND_EXPLICITLY);
ef20bf70
MV
283}
284
9482a297
MV
285void
286scm_init_fluids ()
287{
e841c3e0
KN
288 scm_tc16_fluid = scm_make_smob_type ("fluid", 0);
289 scm_set_smob_print (scm_tc16_fluid, fluid_print);
a0599745 290#include "libguile/fluids.x"
9482a297 291}
89e00824
ML
292
293/*
294 Local Variables:
295 c-file-style: "gnu"
296 End:
297*/