1 /* Copyright (C) 1996,1997,2000,2001 Free Software Foundation, Inc.
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.
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.
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
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"
28 #include "libguile/deprecation.h"
29 #include "libguile/lang.h"
31 #define INITIAL_FLUIDS 10
32 #include "libguile/validate.h"
34 static volatile long n_fluids
;
35 scm_t_bits scm_tc16_fluid
;
38 scm_make_initial_fluids ()
40 return scm_c_make_vector (INITIAL_FLUIDS
, SCM_BOOL_F
);
44 grow_fluids (scm_root_state
*root_state
, int new_length
)
46 SCM old_fluids
, new_fluids
;
49 old_fluids
= root_state
->fluids
;
50 old_length
= SCM_VECTOR_LENGTH (old_fluids
);
51 new_fluids
= scm_c_make_vector (new_length
, SCM_BOOL_F
);
53 while (i
< old_length
)
55 SCM_VECTOR_SET (new_fluids
, i
, SCM_VELTS(old_fluids
)[i
]);
58 while (i
< new_length
)
60 SCM_VECTOR_SET (new_fluids
, i
, SCM_BOOL_F
);
64 root_state
->fluids
= new_fluids
;
68 scm_copy_fluids (scm_root_state
*root_state
)
70 grow_fluids (root_state
, SCM_VECTOR_LENGTH (root_state
->fluids
));
74 fluid_print (SCM exp
, SCM port
, scm_print_state
*pstate SCM_UNUSED
)
76 scm_puts ("#<fluid ", port
);
77 scm_intprint ((int) SCM_FLUID_NUM (exp
), 10, port
);
86 SCM_CRITICAL_SECTION_START
;
88 SCM_CRITICAL_SECTION_END
;
92 SCM_DEFINE (scm_make_fluid
, "make-fluid", 0, 0, 0,
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.")
101 #define FUNC_NAME s_scm_make_fluid
105 n
= next_fluid_num ();
106 SCM_RETURN_NEWSMOB (scm_tc16_fluid
, n
);
110 SCM_DEFINE (scm_fluid_p
, "fluid?", 1, 0, 0,
112 "Return @code{#t} iff @var{obj} is a fluid; otherwise, return\n"
114 #define FUNC_NAME s_scm_fluid_p
116 return SCM_BOOL(SCM_FLUIDP (obj
));
120 SCM_DEFINE (scm_fluid_ref
, "fluid-ref", 1, 0, 0,
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"
125 #define FUNC_NAME s_scm_fluid_ref
129 SCM_VALIDATE_FLUID (1, fluid
);
130 n
= SCM_FLUID_NUM (fluid
);
132 if (SCM_VECTOR_LENGTH (scm_root
->fluids
) <= n
)
133 grow_fluids (scm_root
, n
+1);
134 return SCM_VELTS (scm_root
->fluids
)[n
];
138 SCM_DEFINE (scm_fluid_set_x
, "fluid-set!", 2, 0, 0,
139 (SCM fluid
, SCM value
),
140 "Set the value associated with @var{fluid} in the current dynamic root.")
141 #define FUNC_NAME s_scm_fluid_set_x
145 SCM_VALIDATE_FLUID (1, fluid
);
146 n
= SCM_FLUID_NUM (fluid
);
148 if (SCM_VECTOR_LENGTH (scm_root
->fluids
) <= n
)
149 grow_fluids (scm_root
, n
+1);
150 SCM_VECTOR_SET (scm_root
->fluids
, n
, value
);
151 return SCM_UNSPECIFIED
;
156 scm_swap_fluids (SCM fluids
, SCM vals
)
158 while (!SCM_NULL_OR_NIL_P (fluids
))
160 SCM fl
= SCM_CAR (fluids
);
161 SCM old_val
= scm_fluid_ref (fl
);
162 scm_fluid_set_x (fl
, SCM_CAR (vals
));
163 SCM_SETCAR (vals
, old_val
);
164 fluids
= SCM_CDR (fluids
);
165 vals
= SCM_CDR (vals
);
169 /* Swap the fluid values in reverse order. This is important when the
170 same fluid appears multiple times in the fluids list. */
173 scm_swap_fluids_reverse (SCM fluids
, SCM vals
)
175 if (!SCM_NULL_OR_NIL_P (fluids
))
179 scm_swap_fluids_reverse (SCM_CDR (fluids
), SCM_CDR (vals
));
180 fl
= SCM_CAR (fluids
);
181 old_val
= scm_fluid_ref (fl
);
182 scm_fluid_set_x (fl
, SCM_CAR (vals
));
183 SCM_SETCAR (vals
, old_val
);
189 apply_thunk (void *thunk
)
191 return scm_call_0 (SCM_PACK (thunk
));
194 SCM_DEFINE (scm_with_fluids
, "with-fluids*", 3, 0, 0,
195 (SCM fluids
, SCM values
, SCM thunk
),
196 "Set @var{fluids} to @var{values} temporary, and call @var{thunk}.\n"
197 "@var{fluids} must be a list of fluids and @var{values} must be the same\n"
198 "number of their values to be applied. Each substitution is done\n"
199 "one after another. @var{thunk} must be a procedure with no argument.")
200 #define FUNC_NAME s_scm_with_fluids
202 return scm_c_with_fluids (fluids
, values
, apply_thunk
, (void *) SCM_UNPACK (thunk
));
207 scm_c_with_fluids (SCM fluids
, SCM values
, SCM (*cproc
) (), void *cdata
)
208 #define FUNC_NAME "scm_c_with_fluids"
213 SCM_VALIDATE_LIST_COPYLEN (1, fluids
, flen
);
214 SCM_VALIDATE_LIST_COPYLEN (2, values
, vlen
);
216 scm_out_of_range (s_scm_with_fluids
, values
);
218 scm_swap_fluids (fluids
, values
);
219 scm_dynwinds
= scm_acons (fluids
, values
, scm_dynwinds
);
221 scm_dynwinds
= SCM_CDR (scm_dynwinds
);
222 scm_swap_fluids_reverse (fluids
, values
);
228 scm_c_with_fluid (SCM fluid
, SCM value
, SCM (*cproc
) (), void *cdata
)
229 #define FUNC_NAME "scm_c_with_fluid"
231 return scm_c_with_fluids (scm_list_1 (fluid
), scm_list_1 (value
),
239 scm_tc16_fluid
= scm_make_smob_type ("fluid", 0);
240 scm_set_smob_print (scm_tc16_fluid
, fluid_print
);
241 #include "libguile/fluids.x"