* Makefile.am (DEFS): Added. automake adds -I options to DEFS,
[bpt/guile.git] / libguile / fluids.c
CommitLineData
b7f3516f 1/* Copyright (C) 1996, 1997 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/* Software engineering face-lift by Greg J. Badros, 11-Dec-1999,
43 gjb@cs.washington.edu, http://www.cs.washington.edu/homes/gjb */
44
45
a0599745
MD
46#include "libguile/_scm.h"
47#include "libguile/print.h"
48#include "libguile/smob.h"
49#include "libguile/dynwind.h"
50#include "libguile/fluids.h"
51#include "libguile/alist.h"
52#include "libguile/eval.h"
53#include "libguile/ports.h"
9482a297
MV
54
55#define INITIAL_FLUIDS 10
a0599745 56#include "libguile/validate.h"
9482a297
MV
57
58static volatile int n_fluids;
59long scm_tc16_fluid;
60
61SCM
62scm_make_initial_fluids ()
63{
64 return scm_make_vector (SCM_MAKINUM (INITIAL_FLUIDS),
a8741caa 65 SCM_BOOL_F);
9482a297
MV
66}
67
9482a297 68static void
ed4d7cee 69grow_fluids (scm_root_state *root_state, int new_length)
9482a297
MV
70{
71 SCM old_fluids, new_fluids;
72 int old_length, i;
73
74 old_fluids = root_state->fluids;
9482a297 75 old_length = SCM_LENGTH (old_fluids);
a8741caa 76 new_fluids = scm_make_vector (SCM_MAKINUM (new_length), SCM_BOOL_F);
9482a297
MV
77 i = 0;
78 while (i < old_length)
79 {
80 SCM_VELTS(new_fluids)[i] = SCM_VELTS(old_fluids)[i];
81 i++;
82 }
83 while (i < new_length)
84 {
85 SCM_VELTS(new_fluids)[i] = SCM_BOOL_F;
86 i++;
87 }
88
89 root_state->fluids = new_fluids;
90}
91
92void
6e8d25a6 93scm_copy_fluids (scm_root_state *root_state)
9482a297
MV
94{
95 grow_fluids (root_state, SCM_LENGTH(root_state->fluids));
96}
97
9482a297 98static int
1bbd0b84 99print_fluid (SCM exp, SCM port, scm_print_state *pstate)
9482a297 100{
ed4d7cee
GB
101 scm_puts ("#<fluid ", port);
102 scm_intprint ((int) SCM_FLUID_NUM (exp), 10, port);
103 scm_putc ('>', port);
104 return 1;
9482a297
MV
105}
106
ed4d7cee
GB
107static int
108next_fluid_num ()
9482a297
MV
109{
110 int n;
eadd48de 111#ifdef USE_THREADS
9482a297 112 SCM_THREAD_CRITICAL_SECTION_START;
eadd48de 113#endif
9482a297 114 n = n_fluids++;
eadd48de 115#ifdef USE_THREADS
9482a297 116 SCM_THREAD_CRITICAL_SECTION_END;
eadd48de 117#endif
9482a297
MV
118 return n;
119}
120
a1ec6916 121SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0,
ed4d7cee
GB
122 (),
123 "Return a newly created fluid.\n"
124 "Fluids are objects of a certain type (a smob) that can hold one SCM\n"
125 "value per dynamic root. That is, modifications to this value are\n"
126 "only visible to code that executes within the same dynamic root as\n"
127 "the modifying code. When a new dynamic root is constructed, it\n"
128 "inherits the values from its parent. Because each thread executes\n"
129 "in its own dynamic root, you can use fluids for thread local storage.")
1bbd0b84 130#define FUNC_NAME s_scm_make_fluid
9482a297 131{
9482a297
MV
132 int n;
133
134 SCM_DEFER_INTS;
135 n = next_fluid_num ();
23a62151 136 SCM_RETURN_NEWSMOB (scm_tc16_fluid, n);
9482a297 137}
1bbd0b84 138#undef FUNC_NAME
9482a297 139
a1ec6916 140SCM_DEFINE (scm_fluid_p, "fluid?", 1, 0, 0,
ed4d7cee
GB
141 (SCM obj),
142 "Return #t iff @var{obj} is a fluid; otherwise, return #f.")
1bbd0b84 143#define FUNC_NAME s_scm_fluid_p
b3460a50 144{
ed4d7cee 145 return SCM_BOOL(SCM_FLUIDP (obj));
b3460a50 146}
1bbd0b84 147#undef FUNC_NAME
b3460a50 148
a1ec6916 149SCM_DEFINE (scm_fluid_ref, "fluid-ref", 1, 0, 0,
ed4d7cee
GB
150 (SCM fluid),
151 "Return the value associated with @var{fluid} in the current dynamic root.\n"
152 "If @var{fluid} has not been set, then this returns #f.")
1bbd0b84 153#define FUNC_NAME s_scm_fluid_ref
9482a297
MV
154{
155 int n;
156
ed4d7cee 157 SCM_VALIDATE_FLUID (1, fluid);
9482a297 158
ed4d7cee 159 n = SCM_FLUID_NUM (fluid);
9482a297
MV
160
161 if (SCM_LENGTH (scm_root->fluids) <= n)
162 grow_fluids (scm_root, n+1);
163 return SCM_VELTS(scm_root->fluids)[n];
164}
1bbd0b84 165#undef FUNC_NAME
9482a297 166
a1ec6916 167SCM_DEFINE (scm_fluid_set_x, "fluid-set!", 2, 0, 0,
ed4d7cee
GB
168 (SCM fluid, SCM value),
169 "Set the value associated with @var{fluid} in the current dynamic root.")
1bbd0b84 170#define FUNC_NAME s_scm_fluid_set_x
9482a297
MV
171{
172 int n;
173
ed4d7cee
GB
174 SCM_VALIDATE_FLUID (1, fluid);
175 n = SCM_FLUID_NUM (fluid);
9482a297
MV
176
177 if (SCM_LENGTH (scm_root->fluids) <= n)
178 grow_fluids (scm_root, n+1);
ed4d7cee
GB
179 SCM_VELTS(scm_root->fluids)[n] = value;
180 return value;
9482a297 181}
1bbd0b84 182#undef FUNC_NAME
9482a297 183
b3460a50 184void
1bbd0b84 185scm_swap_fluids (SCM fluids, SCM vals)
b3460a50
MV
186{
187 while (SCM_NIMP (fluids))
188 {
189 SCM fl = SCM_CAR (fluids);
190 SCM old_val = scm_fluid_ref (fl);
191 scm_fluid_set_x (fl, SCM_CAR (vals));
192 SCM_SETCAR (vals, old_val);
193 fluids = SCM_CDR (fluids);
194 vals = SCM_CDR (vals);
195 }
196}
197
198/* Swap the fluid values in reverse order. This is important when the
199same fluid appears multiple times in the fluids list. */
200
201void
1bbd0b84 202scm_swap_fluids_reverse (SCM fluids, SCM vals)
b3460a50
MV
203{
204 if (SCM_NIMP (fluids))
205 {
206 SCM fl, old_val;
207
208 scm_swap_fluids_reverse (SCM_CDR (fluids), SCM_CDR (vals));
209 fl = SCM_CAR (fluids);
210 old_val = scm_fluid_ref (fl);
211 scm_fluid_set_x (fl, SCM_CAR (vals));
212 SCM_SETCAR (vals, old_val);
213 }
214}
215
1bbd0b84
GB
216
217static SCM
218apply_thunk (void *thunk)
219{
54778cd3 220 return scm_apply (SCM_PACK (thunk), SCM_EOL, SCM_EOL);
1bbd0b84
GB
221}
222
a1ec6916 223SCM_DEFINE (scm_with_fluids, "with-fluids*", 3, 0, 0,
ed4d7cee
GB
224 (SCM fluids, SCM values, SCM thunk),
225 "Set @var{fluids} to @var{values} temporary, and call @var{thunk}.\n"
226 "@var{fluids} must be a list of fluids and @var{values} must be the same\n"
227 "number of their values to be applied. Each substitution is done\n"
228 "one after another. @var{thunk} must be a procedure with no argument.")
1bbd0b84
GB
229#define FUNC_NAME s_scm_with_fluids
230{
54778cd3 231 return scm_internal_with_fluids (fluids, values, apply_thunk, (void *) SCM_UNPACK (thunk));
1bbd0b84
GB
232}
233#undef FUNC_NAME
b3460a50
MV
234
235SCM
ed4d7cee 236scm_internal_with_fluids (SCM fluids, SCM values, SCM (*cproc) (), void *cdata)
c1bfcf60 237#define FUNC_NAME "scm_internal_with_fluids"
b3460a50
MV
238{
239 SCM ans;
c1bfcf60 240 int flen, vlen;
b3460a50 241
c1bfcf60 242 SCM_VALIDATE_LIST_COPYLEN (1, fluids, flen);
ed4d7cee 243 SCM_VALIDATE_LIST_COPYLEN (2, values, vlen);
b3460a50 244 if (flen != vlen)
ed4d7cee 245 scm_out_of_range (s_scm_with_fluids, values);
b3460a50 246
ed4d7cee
GB
247 scm_swap_fluids (fluids, values);
248 scm_dynwinds = scm_acons (fluids, values, scm_dynwinds);
b3460a50
MV
249 ans = cproc (cdata);
250 scm_dynwinds = SCM_CDR (scm_dynwinds);
ed4d7cee 251 scm_swap_fluids_reverse (fluids, values);
b3460a50
MV
252 return ans;
253}
c1bfcf60 254#undef FUNC_NAME
b3460a50 255
b3460a50 256
b3460a50 257
9482a297
MV
258void
259scm_init_fluids ()
260{
23a62151
MD
261 scm_tc16_fluid = scm_make_smob_type_mfpe ("fluid", 0,
262 NULL, NULL, print_fluid, NULL);
a0599745 263#include "libguile/fluids.x"
9482a297 264}
89e00824
ML
265
266/*
267 Local Variables:
268 c-file-style: "gnu"
269 End:
270*/