1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-22 04:30:19 +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. */ /* Assume the assignment below is atomic. */
len = allocated_fluids_len; 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++) for (i = 0; i < old_len; i++)
SCM_SIMPLE_VECTOR_SET (new_fluids, 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. */ /* Return a new fluid. */
static SCM static SCM
new_fluid () new_fluid (SCM init)
{ {
SCM fluid; SCM fluid;
size_t trial, n; size_t trial, n;
/* Fluids are pointerless cells: the first word is the type tag; the second /* Fluids hold the type tag and the fluid number in the first word,
word is the fluid number. */ and the default value in the second word. */
fluid = PTR2SCM (scm_gc_malloc_pointerless (sizeof (scm_t_cell), "fluid")); fluid = scm_cell (scm_tc7_fluid, SCM_UNPACK (init));
SCM_SET_CELL_TYPE (fluid, scm_tc7_fluid); SCM_SET_CELL_TYPE (fluid, scm_tc7_fluid);
scm_dynwind_begin (0); scm_dynwind_begin (0);
@ -157,7 +157,7 @@ new_fluid ()
} }
allocated_fluids[n] = SCM2PTR (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], GC_GENERAL_REGISTER_DISAPPEARING_LINK (&allocated_fluids[n],
SCM2PTR (fluid)); SCM2PTR (fluid));
@ -166,13 +166,19 @@ new_fluid ()
/* Now null out values. We could (and probably should) do this when /* Now null out values. We could (and probably should) do this when
the fluid is collected instead of now. */ the fluid is collected instead of now. */
scm_i_reset_fluid (n, SCM_BOOL_F); scm_i_reset_fluid (n);
return fluid; 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" "Return a newly created fluid.\n"
"Fluids are objects that can hold one\n" "Fluids are objects that can hold one\n"
"value per dynamic state. That is, modifications to this value are\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" "the modifying code. When a new dynamic state is constructed, it\n"
"inherits the values from its parent. Because each thread normally executes\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.") "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 #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.") "Make a fluid that is initially unbound.")
#define FUNC_NAME s_scm_make_unbound_fluid #define FUNC_NAME s_scm_make_unbound_fluid
{ {
SCM f = new_fluid (); return new_fluid (SCM_UNDEFINED);
scm_fluid_set_x (f, SCM_UNDEFINED);
return f;
} }
#undef FUNC_NAME #undef FUNC_NAME
@ -217,6 +221,7 @@ scm_is_fluid (SCM obj)
static SCM static SCM
fluid_ref (SCM fluid) fluid_ref (SCM fluid)
{ {
SCM ret;
SCM fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state); SCM fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state);
if (SCM_UNLIKELY (FLUID_NUM (fluid) >= SCM_SIMPLE_VECTOR_LENGTH (fluids))) 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); 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, 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}.") "Unset the value associated with @var{fluid}.")
#define FUNC_NAME s_scm_fluid_unset_x #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); return scm_fluid_set_x (fluid, SCM_UNDEFINED);
} }
#undef FUNC_NAME #undef FUNC_NAME

View file

@ -3,7 +3,7 @@
#ifndef SCM_FLUIDS_H #ifndef SCM_FLUIDS_H
#define 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * 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) #define SCM_FLUID_P(x) (!SCM_IMP (x) && SCM_TYP7 (x) == scm_tc7_fluid)
#ifdef BUILDING_LIBGUILE #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 #endif
SCM_API SCM scm_make_fluid (void); 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 SCM scm_make_unbound_fluid (void);
SCM_API int scm_is_fluid (SCM obj); SCM_API int scm_is_fluid (SCM obj);
SCM_API SCM scm_fluid_p (SCM fl); 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. */ /* Run when a fluid is collected. */
void void
scm_i_reset_fluid (size_t n, SCM val) scm_i_reset_fluid (size_t n)
{ {
scm_i_thread *t; 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); SCM v = SCM_I_DYNAMIC_STATE_FLUIDS (t->dynamic_state);
if (n < SCM_SIMPLE_VECTOR_LENGTH (v)) 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); 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_without_guile (void *(*func)(void *), void *data);
SCM_API void *scm_with_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_threads_prehistory (void *);
SCM_INTERNAL void scm_init_threads (void); SCM_INTERNAL void scm_init_threads (void);
SCM_INTERNAL void scm_init_thread_procs (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 else
{ {
SCM val = SCM_SIMPLE_VECTOR_REF (fluids, num); 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))) if (SCM_UNLIKELY (scm_is_eq (val, SCM_UNDEFINED)))
{ {
finish_args = *sp; finish_args = *sp;

View file

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