1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

optional default-value arg to make-fluid

* libguile/fluids.c (grow_dynamic_state, new_fluid): Arrange for the
  default value in the dynamic-state vector to be SCM_UNDEFINED instead
  of SCM_BOOL_F.  If the value in the dynamic-state is #f, default to a
  value attached to the fluid instead.  This allows useful default
  values.
  (scm_make_fluid_with_default): New function, allows the user to
  specify a default value for the fluid.  Defaults to #f.  Bound to
  `make-fluid' on the Scheme side.
  (scm_make_unbound_fluid): Use SCM_UNDEFINED as the default in all
  threads.
  (scm_fluid_unset_x): Also unset the default value.  Not sure if this
  is the right thing.
  (fluid_ref): Update to the new default-value strategy.

* libguile/threads.c (scm_i_reset_fluid): Reset to SCM_UNDEFINED.
* libguile/threads.h: Remove extra arg to scm_i_reset_fluid.
* libguile/vm-i-system.c (fluid-ref): Update to new default-value
  strategy.

* module/ice-9/vlist.scm (block-growth-factor): Default to 2 in all
  threads.  Fixes http://debbugs.gnu.org/10093.
This commit is contained in:
Andy Wingo 2011-11-23 12:13:12 +01:00
parent adf8616fab
commit aafb4ed724
6 changed files with 37 additions and 23 deletions

View file

@ -68,7 +68,7 @@ grow_dynamic_state (SCM state)
/* Assume the assignment below is atomic. */
len = allocated_fluids_len;
new_fluids = scm_c_make_vector (len, SCM_BOOL_F);
new_fluids = scm_c_make_vector (len, SCM_UNDEFINED);
for (i = 0; i < old_len; i++)
SCM_SIMPLE_VECTOR_SET (new_fluids, i,
@ -103,14 +103,14 @@ scm_i_with_fluids_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
/* Return a new fluid. */
static SCM
new_fluid ()
new_fluid (SCM init)
{
SCM fluid;
size_t trial, n;
/* Fluids are pointerless cells: the first word is the type tag; the second
word is the fluid number. */
fluid = PTR2SCM (scm_gc_malloc_pointerless (sizeof (scm_t_cell), "fluid"));
/* Fluids hold the type tag and the fluid number in the first word,
and the default value in the second word. */
fluid = scm_cell (scm_tc7_fluid, SCM_UNPACK (init));
SCM_SET_CELL_TYPE (fluid, scm_tc7_fluid);
scm_dynwind_begin (0);
@ -157,7 +157,7 @@ new_fluid ()
}
allocated_fluids[n] = SCM2PTR (fluid);
SCM_SET_CELL_WORD_1 (fluid, (scm_t_bits) n);
SCM_SET_CELL_WORD_0 (fluid, (scm_tc7_fluid | (n << 8)));
GC_GENERAL_REGISTER_DISAPPEARING_LINK (&allocated_fluids[n],
SCM2PTR (fluid));
@ -166,13 +166,19 @@ new_fluid ()
/* Now null out values. We could (and probably should) do this when
the fluid is collected instead of now. */
scm_i_reset_fluid (n, SCM_BOOL_F);
scm_i_reset_fluid (n);
return fluid;
}
SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0,
(),
SCM
scm_make_fluid (void)
{
return new_fluid (SCM_BOOL_F);
}
SCM_DEFINE (scm_make_fluid_with_default, "make-fluid", 0, 1, 0,
(SCM dflt),
"Return a newly created fluid.\n"
"Fluids are objects that can hold one\n"
"value per dynamic state. That is, modifications to this value are\n"
@ -180,9 +186,9 @@ SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0,
"the modifying code. When a new dynamic state is constructed, it\n"
"inherits the values from its parent. Because each thread normally executes\n"
"with its own dynamic state, you can use fluids for thread local storage.")
#define FUNC_NAME s_scm_make_fluid
#define FUNC_NAME s_scm_make_fluid_with_default
{
return new_fluid ();
return new_fluid (SCM_UNBNDP (dflt) ? SCM_BOOL_F : dflt);
}
#undef FUNC_NAME
@ -191,9 +197,7 @@ SCM_DEFINE (scm_make_unbound_fluid, "make-unbound-fluid", 0, 0, 0,
"Make a fluid that is initially unbound.")
#define FUNC_NAME s_scm_make_unbound_fluid
{
SCM f = new_fluid ();
scm_fluid_set_x (f, SCM_UNDEFINED);
return f;
return new_fluid (SCM_UNDEFINED);
}
#undef FUNC_NAME
@ -217,6 +221,7 @@ scm_is_fluid (SCM obj)
static SCM
fluid_ref (SCM fluid)
{
SCM ret;
SCM fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state);
if (SCM_UNLIKELY (FLUID_NUM (fluid) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
@ -227,7 +232,11 @@ fluid_ref (SCM fluid)
fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state);
}
return SCM_SIMPLE_VECTOR_REF (fluids, FLUID_NUM (fluid));
ret = SCM_SIMPLE_VECTOR_REF (fluids, FLUID_NUM (fluid));
if (SCM_UNBNDP (ret))
return SCM_I_FLUID_DEFAULT (fluid);
else
return ret;
}
SCM_DEFINE (scm_fluid_ref, "fluid-ref", 1, 0, 0,
@ -274,6 +283,9 @@ SCM_DEFINE (scm_fluid_unset_x, "fluid-unset!", 1, 0, 0,
"Unset the value associated with @var{fluid}.")
#define FUNC_NAME s_scm_fluid_unset_x
{
/* FIXME: really unset the default value, too? The current test
suite demands it, but I would prefer not to. */
SCM_SET_CELL_OBJECT_1 (fluid, SCM_UNDEFINED);
return scm_fluid_set_x (fluid, SCM_UNDEFINED);
}
#undef FUNC_NAME

View file

@ -3,7 +3,7 @@
#ifndef SCM_FLUIDS_H
#define SCM_FLUIDS_H
/* Copyright (C) 1996,2000,2001, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
/* Copyright (C) 1996,2000,2001, 2006, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
@ -56,10 +56,12 @@
#define SCM_FLUID_P(x) (!SCM_IMP (x) && SCM_TYP7 (x) == scm_tc7_fluid)
#ifdef BUILDING_LIBGUILE
#define SCM_I_FLUID_NUM(x) ((size_t)SCM_CELL_WORD_1(x))
#define SCM_I_FLUID_NUM(x) ((size_t)(SCM_CELL_WORD_0 (x) >> 8))
#define SCM_I_FLUID_DEFAULT(x) (SCM_CELL_OBJECT_1 (x))
#endif
SCM_API SCM scm_make_fluid (void);
SCM_API SCM scm_make_fluid_with_default (SCM dflt);
SCM_API SCM scm_make_unbound_fluid (void);
SCM_API int scm_is_fluid (SCM obj);
SCM_API SCM scm_fluid_p (SCM fl);

View file

@ -478,7 +478,7 @@ static SCM scm_i_default_dynamic_state;
/* Run when a fluid is collected. */
void
scm_i_reset_fluid (size_t n, SCM val)
scm_i_reset_fluid (size_t n)
{
scm_i_thread *t;
@ -489,7 +489,7 @@ scm_i_reset_fluid (size_t n, SCM val)
SCM v = SCM_I_DYNAMIC_STATE_FLUIDS (t->dynamic_state);
if (n < SCM_SIMPLE_VECTOR_LENGTH (v))
SCM_SIMPLE_VECTOR_SET (v, n, val);
SCM_SIMPLE_VECTOR_SET (v, n, SCM_UNDEFINED);
}
scm_i_pthread_mutex_unlock (&thread_admin_mutex);
}

View file

@ -136,7 +136,7 @@ SCM_API SCM scm_spawn_thread (scm_t_catch_body body, void *body_data,
SCM_API void *scm_without_guile (void *(*func)(void *), void *data);
SCM_API void *scm_with_guile (void *(*func)(void *), void *data);
SCM_INTERNAL void scm_i_reset_fluid (size_t, SCM);
SCM_INTERNAL void scm_i_reset_fluid (size_t);
SCM_INTERNAL void scm_threads_prehistory (void *);
SCM_INTERNAL void scm_init_threads (void);
SCM_INTERNAL void scm_init_thread_procs (void);

View file

@ -1660,6 +1660,8 @@ VM_DEFINE_INSTRUCTION (91, fluid_ref, "fluid-ref", 0, 1, 1)
else
{
SCM val = SCM_SIMPLE_VECTOR_REF (fluids, num);
if (scm_is_eq (val, SCM_UNDEFINED))
val = SCM_I_FLUID_DEFAULT (*sp);
if (SCM_UNLIKELY (scm_is_eq (val, SCM_UNDEFINED)))
{
finish_args = *sp;

View file

@ -66,9 +66,7 @@
;;;
(define block-growth-factor
(let ((f (make-fluid)))
(fluid-set! f 2)
f))
(make-fluid 2))
(define-syntax-rule (define-inline (name formals ...) body ...)
;; Work around the lack of an inliner.