2010-02-18 17:10:29 +01:00
|
|
|
|
/* Copyright (C) 1996,1997,2000,2001, 2004, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
1997-07-18 16:26:47 +00:00
|
|
|
|
*
|
2003-04-05 19:15:35 +00:00
|
|
|
|
* This library is free software; you can redistribute it and/or
|
2009-06-17 00:22:09 +01:00
|
|
|
|
* modify it under the terms of the GNU Lesser General Public License
|
|
|
|
|
|
* as published by the Free Software Foundation; either version 3 of
|
|
|
|
|
|
* the License, or (at your option) any later version.
|
1997-07-18 16:26:47 +00:00
|
|
|
|
*
|
2009-06-17 00:22:09 +01:00
|
|
|
|
* This library is distributed in the hope that it will be useful, but
|
|
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
2003-04-05 19:15:35 +00:00
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
|
* Lesser General Public License for more details.
|
1997-07-18 16:26:47 +00:00
|
|
|
|
*
|
2003-04-05 19:15:35 +00:00
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2009-06-17 00:22:09 +01:00
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
|
|
|
|
* 02110-1301 USA
|
2003-04-05 19:15:35 +00:00
|
|
|
|
*/
|
1997-07-18 16:26:47 +00:00
|
|
|
|
|
2008-09-13 15:35:27 +02:00
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
|
# include <config.h>
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
2005-03-02 20:42:01 +00:00
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
#include <string.h>
|
1999-12-12 02:36:16 +00:00
|
|
|
|
|
2000-04-21 14:16:44 +00:00
|
|
|
|
#include "libguile/_scm.h"
|
|
|
|
|
|
#include "libguile/print.h"
|
|
|
|
|
|
#include "libguile/dynwind.h"
|
|
|
|
|
|
#include "libguile/fluids.h"
|
|
|
|
|
|
#include "libguile/alist.h"
|
|
|
|
|
|
#include "libguile/eval.h"
|
|
|
|
|
|
#include "libguile/ports.h"
|
2001-05-19 00:36:22 +00:00
|
|
|
|
#include "libguile/deprecation.h"
|
2000-04-21 14:16:44 +00:00
|
|
|
|
#include "libguile/validate.h"
|
2010-03-05 13:38:28 +01:00
|
|
|
|
#include "libguile/bdw-gc.h"
|
1997-07-18 16:26:47 +00:00
|
|
|
|
|
2010-03-05 13:38:28 +01:00
|
|
|
|
/* Number of additional slots to allocate when ALLOCATED_FLUIDS is full. */
|
|
|
|
|
|
#define FLUID_GROW 128
|
2005-03-02 20:42:01 +00:00
|
|
|
|
|
2010-03-05 13:38:28 +01:00
|
|
|
|
/* Vector of allocated fluids indexed by fluid numbers. Access is protected by
|
|
|
|
|
|
FLUID_ADMIN_MUTEX. */
|
|
|
|
|
|
static void **allocated_fluids = NULL;
|
|
|
|
|
|
static size_t allocated_fluids_len = 0;
|
1997-07-18 16:26:47 +00:00
|
|
|
|
|
2005-03-02 20:42:01 +00:00
|
|
|
|
static scm_i_pthread_mutex_t fluid_admin_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
|
|
|
2010-07-17 12:10:52 +02:00
|
|
|
|
#define IS_FLUID(x) SCM_FLUID_P (x)
|
2010-02-19 11:39:44 +01:00
|
|
|
|
#define FLUID_NUM(x) SCM_I_FLUID_NUM (x)
|
2005-03-02 20:42:01 +00:00
|
|
|
|
|
2010-02-19 11:39:44 +01:00
|
|
|
|
#define IS_DYNAMIC_STATE(x) SCM_I_DYNAMIC_STATE_P (x)
|
|
|
|
|
|
#define DYNAMIC_STATE_FLUIDS(x) SCM_I_DYNAMIC_STATE_FLUIDS (x)
|
fluids are tc7 objects
If you're wondering what I'm doing, I'm trying to eventually reimplement
smobs in terms of structs, so that applicable smobs can just follow the
applicable struct dispatch path. But to do that I have to get structs
initialized before things that use smobs, which means transforming a
bunch of smobby things to tc7 things. But this transformation is good
for performance anyway, and we currently have a glut of unused tc7s,
so here we go...
* libguile/tags.h (scm_tc7_fluid, scm_tc7_dynamic_state): Fluids (and
dynamic states) now have tc7s.
* libguile/fluids.h: Remove scm_fluids_prehistory, and add internal
scm_i_fluid_print. Update a comment.
* libguile/fluids.c: Update for tc7 representation. Also remove the next
pointers while we're at it, as they aren't used in the new BDW GC.
* libguile/eq.c (scm_equal_p): Remove the hashtable case. Hashtables
could never be equal? before, I don't see why to add stubs doing the
same thing now.
* libguile/print.c (iprin1):
* libguile/gc.c (scm_i_tag_name):
* libguile/evalext.c (scm_self_evaluating_p): Add fluid and
dynamic_state cases.
* libguile/goops.h: Remove scm_class_hashtable; it will be static.
* libguile/goops.c: Make <hashtable> static, and add <fluid> and
<dynamic-state> classes.
* libguile/hashtab.h:
* libguile/hashtab.c: Remove scm_i_hashtable_equal_p.
* libguile/init.c (scm_i_init_guile): Remove call to fluids_prehistory.
2009-12-05 10:52:18 +01:00
|
|
|
|
#define SET_DYNAMIC_STATE_FLUIDS(x, y) SCM_SET_CELL_WORD_1 ((x), (SCM_UNPACK (y)))
|
2005-03-02 20:42:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
Remove GC-related code from fluids.
* libguile/fluids.c (all_dynamic_states, all_fluids): Remove. Together,
they prevented dynamic states and fluids to be collected. Callers no
longer use them.
(resize_all_states): Remove.
(grow_dynamic_state): New function.
(next_fluid_num): Don't call `resize_all_states ()'.
(scm_i_fluid_num, scm_i_fast_fluid_ref, scm_i_fast_fluid_set_x): Remove,
as they broke encapsulation and would have needed duplication of the lazy
dynamic state growing code.
(scm_fluid_ref, scm_fluid_set_x): Lazily grow the dynamic state's fluid
vector.
(scm_fluids_prehistory): Don't set an `scm_after_sweep_c_hook'.
* libguile/fluids.h (SCM_FLUID_NUM, SCM_FAST_FLUID_REF, SCM_FAST_FLUID_SET_X,
scm_i_fluid_num, scm_i_fast_fluid_set_x, scm_i_fast_fluid_ref): Remove.
* libguile/load.c (the_reader_fluid_num): Remove.
(scm_primitive_load): Use `scm_fluid_ref ()' instead of
`SCM_FAST_FLUID_REF ()'.
(scm_init_load): Likewise.
2008-09-17 00:25:03 +02:00
|
|
|
|
|
2010-03-05 13:38:28 +01:00
|
|
|
|
/* Grow STATE so that it can hold up to ALLOCATED_FLUIDS_LEN fluids. This may
|
|
|
|
|
|
be more than necessary since ALLOCATED_FLUIDS is sparse and the current
|
|
|
|
|
|
thread may not access all the fluids anyway. Memory usage could be improved
|
|
|
|
|
|
by using a 2-level array as is done in glibc for pthread keys (TODO). */
|
1997-07-18 16:26:47 +00:00
|
|
|
|
static void
|
Remove GC-related code from fluids.
* libguile/fluids.c (all_dynamic_states, all_fluids): Remove. Together,
they prevented dynamic states and fluids to be collected. Callers no
longer use them.
(resize_all_states): Remove.
(grow_dynamic_state): New function.
(next_fluid_num): Don't call `resize_all_states ()'.
(scm_i_fluid_num, scm_i_fast_fluid_ref, scm_i_fast_fluid_set_x): Remove,
as they broke encapsulation and would have needed duplication of the lazy
dynamic state growing code.
(scm_fluid_ref, scm_fluid_set_x): Lazily grow the dynamic state's fluid
vector.
(scm_fluids_prehistory): Don't set an `scm_after_sweep_c_hook'.
* libguile/fluids.h (SCM_FLUID_NUM, SCM_FAST_FLUID_REF, SCM_FAST_FLUID_SET_X,
scm_i_fluid_num, scm_i_fast_fluid_set_x, scm_i_fast_fluid_ref): Remove.
* libguile/load.c (the_reader_fluid_num): Remove.
(scm_primitive_load): Use `scm_fluid_ref ()' instead of
`SCM_FAST_FLUID_REF ()'.
(scm_init_load): Likewise.
2008-09-17 00:25:03 +02:00
|
|
|
|
grow_dynamic_state (SCM state)
|
2005-03-02 20:42:01 +00:00
|
|
|
|
{
|
Remove GC-related code from fluids.
* libguile/fluids.c (all_dynamic_states, all_fluids): Remove. Together,
they prevented dynamic states and fluids to be collected. Callers no
longer use them.
(resize_all_states): Remove.
(grow_dynamic_state): New function.
(next_fluid_num): Don't call `resize_all_states ()'.
(scm_i_fluid_num, scm_i_fast_fluid_ref, scm_i_fast_fluid_set_x): Remove,
as they broke encapsulation and would have needed duplication of the lazy
dynamic state growing code.
(scm_fluid_ref, scm_fluid_set_x): Lazily grow the dynamic state's fluid
vector.
(scm_fluids_prehistory): Don't set an `scm_after_sweep_c_hook'.
* libguile/fluids.h (SCM_FLUID_NUM, SCM_FAST_FLUID_REF, SCM_FAST_FLUID_SET_X,
scm_i_fluid_num, scm_i_fast_fluid_set_x, scm_i_fast_fluid_ref): Remove.
* libguile/load.c (the_reader_fluid_num): Remove.
(scm_primitive_load): Use `scm_fluid_ref ()' instead of
`SCM_FAST_FLUID_REF ()'.
(scm_init_load): Likewise.
2008-09-17 00:25:03 +02:00
|
|
|
|
SCM new_fluids;
|
|
|
|
|
|
SCM old_fluids = DYNAMIC_STATE_FLUIDS (state);
|
2010-03-05 13:38:28 +01:00
|
|
|
|
size_t i, len, old_len = SCM_SIMPLE_VECTOR_LENGTH (old_fluids);
|
2005-03-02 20:42:01 +00:00
|
|
|
|
|
2010-03-05 13:38:28 +01:00
|
|
|
|
/* Assume the assignment below is atomic. */
|
|
|
|
|
|
len = allocated_fluids_len;
|
2005-03-02 20:42:01 +00:00
|
|
|
|
|
2010-03-05 13:38:28 +01:00
|
|
|
|
new_fluids = scm_c_make_vector (len, SCM_BOOL_F);
|
Remove GC-related code from fluids.
* libguile/fluids.c (all_dynamic_states, all_fluids): Remove. Together,
they prevented dynamic states and fluids to be collected. Callers no
longer use them.
(resize_all_states): Remove.
(grow_dynamic_state): New function.
(next_fluid_num): Don't call `resize_all_states ()'.
(scm_i_fluid_num, scm_i_fast_fluid_ref, scm_i_fast_fluid_set_x): Remove,
as they broke encapsulation and would have needed duplication of the lazy
dynamic state growing code.
(scm_fluid_ref, scm_fluid_set_x): Lazily grow the dynamic state's fluid
vector.
(scm_fluids_prehistory): Don't set an `scm_after_sweep_c_hook'.
* libguile/fluids.h (SCM_FLUID_NUM, SCM_FAST_FLUID_REF, SCM_FAST_FLUID_SET_X,
scm_i_fluid_num, scm_i_fast_fluid_set_x, scm_i_fast_fluid_ref): Remove.
* libguile/load.c (the_reader_fluid_num): Remove.
(scm_primitive_load): Use `scm_fluid_ref ()' instead of
`SCM_FAST_FLUID_REF ()'.
(scm_init_load): Likewise.
2008-09-17 00:25:03 +02:00
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < old_len; i++)
|
|
|
|
|
|
SCM_SIMPLE_VECTOR_SET (new_fluids, i,
|
|
|
|
|
|
SCM_SIMPLE_VECTOR_REF (old_fluids, i));
|
|
|
|
|
|
SET_DYNAMIC_STATE_FLUIDS (state, new_fluids);
|
1997-07-18 16:26:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
fluids are tc7 objects
If you're wondering what I'm doing, I'm trying to eventually reimplement
smobs in terms of structs, so that applicable smobs can just follow the
applicable struct dispatch path. But to do that I have to get structs
initialized before things that use smobs, which means transforming a
bunch of smobby things to tc7 things. But this transformation is good
for performance anyway, and we currently have a glut of unused tc7s,
so here we go...
* libguile/tags.h (scm_tc7_fluid, scm_tc7_dynamic_state): Fluids (and
dynamic states) now have tc7s.
* libguile/fluids.h: Remove scm_fluids_prehistory, and add internal
scm_i_fluid_print. Update a comment.
* libguile/fluids.c: Update for tc7 representation. Also remove the next
pointers while we're at it, as they aren't used in the new BDW GC.
* libguile/eq.c (scm_equal_p): Remove the hashtable case. Hashtables
could never be equal? before, I don't see why to add stubs doing the
same thing now.
* libguile/print.c (iprin1):
* libguile/gc.c (scm_i_tag_name):
* libguile/evalext.c (scm_self_evaluating_p): Add fluid and
dynamic_state cases.
* libguile/goops.h: Remove scm_class_hashtable; it will be static.
* libguile/goops.c: Make <hashtable> static, and add <fluid> and
<dynamic-state> classes.
* libguile/hashtab.h:
* libguile/hashtab.c: Remove scm_i_hashtable_equal_p.
* libguile/init.c (scm_i_init_guile): Remove call to fluids_prehistory.
2009-12-05 10:52:18 +01:00
|
|
|
|
void
|
|
|
|
|
|
scm_i_fluid_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
|
1997-07-18 16:26:47 +00:00
|
|
|
|
{
|
2000-03-15 16:28:13 +00:00
|
|
|
|
scm_puts ("#<fluid ", port);
|
2005-03-02 20:42:01 +00:00
|
|
|
|
scm_intprint ((int) FLUID_NUM (exp), 10, port);
|
2000-03-15 16:28:13 +00:00
|
|
|
|
scm_putc ('>', port);
|
1997-07-18 16:26:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2009-12-05 10:55:37 +01:00
|
|
|
|
void
|
|
|
|
|
|
scm_i_dynamic_state_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
|
|
|
|
|
|
{
|
|
|
|
|
|
scm_puts ("#<dynamic-state ", port);
|
|
|
|
|
|
scm_intprint (SCM_UNPACK (exp), 16, port);
|
|
|
|
|
|
scm_putc ('>', port);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2010-03-04 11:25:22 +01:00
|
|
|
|
void
|
|
|
|
|
|
scm_i_with_fluids_print (SCM exp, SCM port, scm_print_state *pstate SCM_UNUSED)
|
|
|
|
|
|
{
|
|
|
|
|
|
scm_puts ("#<with-fluids ", port);
|
|
|
|
|
|
scm_intprint (SCM_UNPACK (exp), 16, port);
|
|
|
|
|
|
scm_putc ('>', port);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2010-03-05 13:38:28 +01:00
|
|
|
|
|
|
|
|
|
|
/* Return a new fluid. */
|
|
|
|
|
|
static SCM
|
|
|
|
|
|
new_fluid ()
|
1997-07-18 16:26:47 +00:00
|
|
|
|
{
|
2010-03-05 13:38:28 +01:00
|
|
|
|
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"));
|
|
|
|
|
|
SCM_SET_CELL_TYPE (fluid, scm_tc7_fluid);
|
2005-03-02 20:42:01 +00:00
|
|
|
|
|
2006-01-29 00:23:28 +00:00
|
|
|
|
scm_dynwind_begin (0);
|
|
|
|
|
|
scm_i_dynwind_pthread_mutex_lock (&fluid_admin_mutex);
|
2005-03-02 20:42:01 +00:00
|
|
|
|
|
2010-03-05 13:38:28 +01:00
|
|
|
|
for (trial = 0; trial < 2; trial++)
|
2005-03-02 20:42:01 +00:00
|
|
|
|
{
|
2010-03-05 13:38:28 +01:00
|
|
|
|
/* Look for a free fluid number. */
|
2005-03-02 20:42:01 +00:00
|
|
|
|
for (n = 0; n < allocated_fluids_len; n++)
|
2010-03-05 13:38:28 +01:00
|
|
|
|
/* TODO: Use `__sync_bool_compare_and_swap' where available. */
|
|
|
|
|
|
if (allocated_fluids[n] == NULL)
|
2005-03-02 20:42:01 +00:00
|
|
|
|
break;
|
2010-03-05 13:38:28 +01:00
|
|
|
|
|
|
|
|
|
|
if (trial == 0 && n >= allocated_fluids_len)
|
|
|
|
|
|
/* All fluid numbers are in use. Run a GC and retry. Explicitly
|
|
|
|
|
|
running the GC is costly and bad-style. We only do this because
|
|
|
|
|
|
dynamic state fluid vectors would grow unreasonably if fluid numbers
|
|
|
|
|
|
weren't reused. */
|
|
|
|
|
|
scm_i_gc ("fluids");
|
2005-03-02 20:42:01 +00:00
|
|
|
|
}
|
2010-03-05 13:38:28 +01:00
|
|
|
|
|
|
|
|
|
|
if (n >= allocated_fluids_len)
|
2005-03-02 20:42:01 +00:00
|
|
|
|
{
|
Remove GC-related code from fluids.
* libguile/fluids.c (all_dynamic_states, all_fluids): Remove. Together,
they prevented dynamic states and fluids to be collected. Callers no
longer use them.
(resize_all_states): Remove.
(grow_dynamic_state): New function.
(next_fluid_num): Don't call `resize_all_states ()'.
(scm_i_fluid_num, scm_i_fast_fluid_ref, scm_i_fast_fluid_set_x): Remove,
as they broke encapsulation and would have needed duplication of the lazy
dynamic state growing code.
(scm_fluid_ref, scm_fluid_set_x): Lazily grow the dynamic state's fluid
vector.
(scm_fluids_prehistory): Don't set an `scm_after_sweep_c_hook'.
* libguile/fluids.h (SCM_FLUID_NUM, SCM_FAST_FLUID_REF, SCM_FAST_FLUID_SET_X,
scm_i_fluid_num, scm_i_fast_fluid_set_x, scm_i_fast_fluid_ref): Remove.
* libguile/load.c (the_reader_fluid_num): Remove.
(scm_primitive_load): Use `scm_fluid_ref ()' instead of
`SCM_FAST_FLUID_REF ()'.
(scm_init_load): Likewise.
2008-09-17 00:25:03 +02:00
|
|
|
|
/* Grow the vector of allocated fluids. */
|
2010-03-05 13:38:28 +01:00
|
|
|
|
void **new_allocated_fluids =
|
|
|
|
|
|
scm_gc_malloc_pointerless ((allocated_fluids_len + FLUID_GROW)
|
|
|
|
|
|
* sizeof (*allocated_fluids),
|
|
|
|
|
|
"allocated fluids");
|
2005-03-02 20:42:01 +00:00
|
|
|
|
|
|
|
|
|
|
/* Copy over old values and initialize rest. GC can not run
|
|
|
|
|
|
during these two operations since there is no safe point in
|
2010-03-05 13:38:28 +01:00
|
|
|
|
them. */
|
|
|
|
|
|
memcpy (new_allocated_fluids, allocated_fluids,
|
|
|
|
|
|
allocated_fluids_len * sizeof (*allocated_fluids));
|
|
|
|
|
|
memset (new_allocated_fluids + allocated_fluids_len, 0,
|
|
|
|
|
|
FLUID_GROW * sizeof (*allocated_fluids));
|
2005-03-02 20:42:01 +00:00
|
|
|
|
n = allocated_fluids_len;
|
2007-06-25 22:25:22 +00:00
|
|
|
|
|
Remove GC-related code from fluids.
* libguile/fluids.c (all_dynamic_states, all_fluids): Remove. Together,
they prevented dynamic states and fluids to be collected. Callers no
longer use them.
(resize_all_states): Remove.
(grow_dynamic_state): New function.
(next_fluid_num): Don't call `resize_all_states ()'.
(scm_i_fluid_num, scm_i_fast_fluid_ref, scm_i_fast_fluid_set_x): Remove,
as they broke encapsulation and would have needed duplication of the lazy
dynamic state growing code.
(scm_fluid_ref, scm_fluid_set_x): Lazily grow the dynamic state's fluid
vector.
(scm_fluids_prehistory): Don't set an `scm_after_sweep_c_hook'.
* libguile/fluids.h (SCM_FLUID_NUM, SCM_FAST_FLUID_REF, SCM_FAST_FLUID_SET_X,
scm_i_fluid_num, scm_i_fast_fluid_set_x, scm_i_fast_fluid_ref): Remove.
* libguile/load.c (the_reader_fluid_num): Remove.
(scm_primitive_load): Use `scm_fluid_ref ()' instead of
`SCM_FAST_FLUID_REF ()'.
(scm_init_load): Likewise.
2008-09-17 00:25:03 +02:00
|
|
|
|
/* Update the vector of allocated fluids. Dynamic states will
|
|
|
|
|
|
eventually be lazily grown to accomodate the new value of
|
|
|
|
|
|
ALLOCATED_FLUIDS_LEN in `fluid-ref' and `fluid-set!'. */
|
2005-03-02 20:42:01 +00:00
|
|
|
|
allocated_fluids = new_allocated_fluids;
|
|
|
|
|
|
allocated_fluids_len += FLUID_GROW;
|
|
|
|
|
|
}
|
2010-03-05 13:38:28 +01:00
|
|
|
|
|
|
|
|
|
|
allocated_fluids[n] = SCM2PTR (fluid);
|
|
|
|
|
|
SCM_SET_CELL_WORD_1 (fluid, (scm_t_bits) n);
|
|
|
|
|
|
|
|
|
|
|
|
GC_GENERAL_REGISTER_DISAPPEARING_LINK (&allocated_fluids[n],
|
|
|
|
|
|
SCM2PTR (fluid));
|
|
|
|
|
|
|
2006-01-29 00:23:28 +00:00
|
|
|
|
scm_dynwind_end ();
|
2010-03-05 13:38:28 +01:00
|
|
|
|
return fluid;
|
1997-07-18 16:26:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2000-01-05 19:05:23 +00:00
|
|
|
|
SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0,
|
2000-03-15 16:28:13 +00:00
|
|
|
|
(),
|
|
|
|
|
|
"Return a newly created fluid.\n"
|
2005-03-02 20:42:01 +00:00
|
|
|
|
"Fluids are objects that can hold one\n"
|
|
|
|
|
|
"value per dynamic state. That is, modifications to this value are\n"
|
|
|
|
|
|
"only visible to code that executes with the same dynamic state as\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"
|
|
|
|
|
|
"with its own dynamic state, you can use fluids for thread local storage.")
|
1999-12-12 02:36:16 +00:00
|
|
|
|
#define FUNC_NAME s_scm_make_fluid
|
1997-07-18 16:26:47 +00:00
|
|
|
|
{
|
2010-03-05 13:38:28 +01:00
|
|
|
|
return new_fluid ();
|
1997-07-18 16:26:47 +00:00
|
|
|
|
}
|
1999-12-12 02:36:16 +00:00
|
|
|
|
#undef FUNC_NAME
|
1997-07-18 16:26:47 +00:00
|
|
|
|
|
2000-01-05 19:05:23 +00:00
|
|
|
|
SCM_DEFINE (scm_fluid_p, "fluid?", 1, 0, 0,
|
2000-03-15 16:28:13 +00:00
|
|
|
|
(SCM obj),
|
2001-04-03 13:19:05 +00:00
|
|
|
|
"Return @code{#t} iff @var{obj} is a fluid; otherwise, return\n"
|
|
|
|
|
|
"@code{#f}.")
|
1999-12-12 02:36:16 +00:00
|
|
|
|
#define FUNC_NAME s_scm_fluid_p
|
1997-07-26 20:08:42 +00:00
|
|
|
|
{
|
2005-03-02 20:42:01 +00:00
|
|
|
|
return scm_from_bool (IS_FLUID (obj));
|
1997-07-26 20:08:42 +00:00
|
|
|
|
}
|
1999-12-12 02:36:16 +00:00
|
|
|
|
#undef FUNC_NAME
|
1997-07-26 20:08:42 +00:00
|
|
|
|
|
2005-03-02 20:42:01 +00:00
|
|
|
|
int
|
|
|
|
|
|
scm_is_fluid (SCM obj)
|
|
|
|
|
|
{
|
|
|
|
|
|
return IS_FLUID (obj);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
Remove GC-related code from fluids.
* libguile/fluids.c (all_dynamic_states, all_fluids): Remove. Together,
they prevented dynamic states and fluids to be collected. Callers no
longer use them.
(resize_all_states): Remove.
(grow_dynamic_state): New function.
(next_fluid_num): Don't call `resize_all_states ()'.
(scm_i_fluid_num, scm_i_fast_fluid_ref, scm_i_fast_fluid_set_x): Remove,
as they broke encapsulation and would have needed duplication of the lazy
dynamic state growing code.
(scm_fluid_ref, scm_fluid_set_x): Lazily grow the dynamic state's fluid
vector.
(scm_fluids_prehistory): Don't set an `scm_after_sweep_c_hook'.
* libguile/fluids.h (SCM_FLUID_NUM, SCM_FAST_FLUID_REF, SCM_FAST_FLUID_SET_X,
scm_i_fluid_num, scm_i_fast_fluid_set_x, scm_i_fast_fluid_ref): Remove.
* libguile/load.c (the_reader_fluid_num): Remove.
(scm_primitive_load): Use `scm_fluid_ref ()' instead of
`SCM_FAST_FLUID_REF ()'.
(scm_init_load): Likewise.
2008-09-17 00:25:03 +02:00
|
|
|
|
|
2005-03-02 20:42:01 +00:00
|
|
|
|
|
2000-01-05 19:05:23 +00:00
|
|
|
|
SCM_DEFINE (scm_fluid_ref, "fluid-ref", 1, 0, 0,
|
2000-03-15 16:28:13 +00:00
|
|
|
|
(SCM fluid),
|
2001-04-03 13:19:05 +00:00
|
|
|
|
"Return the value associated with @var{fluid} in the current\n"
|
|
|
|
|
|
"dynamic root. If @var{fluid} has not been set, then return\n"
|
|
|
|
|
|
"@code{#f}.")
|
1999-12-12 02:36:16 +00:00
|
|
|
|
#define FUNC_NAME s_scm_fluid_ref
|
1997-07-18 16:26:47 +00:00
|
|
|
|
{
|
2005-03-02 20:42:01 +00:00
|
|
|
|
SCM fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state);
|
1997-07-18 16:26:47 +00:00
|
|
|
|
|
2000-03-15 16:28:13 +00:00
|
|
|
|
SCM_VALIDATE_FLUID (1, fluid);
|
Remove GC-related code from fluids.
* libguile/fluids.c (all_dynamic_states, all_fluids): Remove. Together,
they prevented dynamic states and fluids to be collected. Callers no
longer use them.
(resize_all_states): Remove.
(grow_dynamic_state): New function.
(next_fluid_num): Don't call `resize_all_states ()'.
(scm_i_fluid_num, scm_i_fast_fluid_ref, scm_i_fast_fluid_set_x): Remove,
as they broke encapsulation and would have needed duplication of the lazy
dynamic state growing code.
(scm_fluid_ref, scm_fluid_set_x): Lazily grow the dynamic state's fluid
vector.
(scm_fluids_prehistory): Don't set an `scm_after_sweep_c_hook'.
* libguile/fluids.h (SCM_FLUID_NUM, SCM_FAST_FLUID_REF, SCM_FAST_FLUID_SET_X,
scm_i_fluid_num, scm_i_fast_fluid_set_x, scm_i_fast_fluid_ref): Remove.
* libguile/load.c (the_reader_fluid_num): Remove.
(scm_primitive_load): Use `scm_fluid_ref ()' instead of
`SCM_FAST_FLUID_REF ()'.
(scm_init_load): Likewise.
2008-09-17 00:25:03 +02:00
|
|
|
|
|
|
|
|
|
|
if (SCM_UNLIKELY (FLUID_NUM (fluid) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
|
|
|
|
|
|
{
|
|
|
|
|
|
/* Lazily grow the current thread's dynamic state. */
|
|
|
|
|
|
grow_dynamic_state (SCM_I_CURRENT_THREAD->dynamic_state);
|
|
|
|
|
|
|
|
|
|
|
|
fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2005-03-02 20:42:01 +00:00
|
|
|
|
return SCM_SIMPLE_VECTOR_REF (fluids, FLUID_NUM (fluid));
|
1997-07-18 16:26:47 +00:00
|
|
|
|
}
|
1999-12-12 02:36:16 +00:00
|
|
|
|
#undef FUNC_NAME
|
1997-07-18 16:26:47 +00:00
|
|
|
|
|
2000-01-05 19:05:23 +00:00
|
|
|
|
SCM_DEFINE (scm_fluid_set_x, "fluid-set!", 2, 0, 0,
|
2000-03-15 16:28:13 +00:00
|
|
|
|
(SCM fluid, SCM value),
|
|
|
|
|
|
"Set the value associated with @var{fluid} in the current dynamic root.")
|
1999-12-12 02:36:16 +00:00
|
|
|
|
#define FUNC_NAME s_scm_fluid_set_x
|
1997-07-18 16:26:47 +00:00
|
|
|
|
{
|
2005-03-02 20:42:01 +00:00
|
|
|
|
SCM fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state);
|
1997-07-18 16:26:47 +00:00
|
|
|
|
|
2000-03-15 16:28:13 +00:00
|
|
|
|
SCM_VALIDATE_FLUID (1, fluid);
|
Remove GC-related code from fluids.
* libguile/fluids.c (all_dynamic_states, all_fluids): Remove. Together,
they prevented dynamic states and fluids to be collected. Callers no
longer use them.
(resize_all_states): Remove.
(grow_dynamic_state): New function.
(next_fluid_num): Don't call `resize_all_states ()'.
(scm_i_fluid_num, scm_i_fast_fluid_ref, scm_i_fast_fluid_set_x): Remove,
as they broke encapsulation and would have needed duplication of the lazy
dynamic state growing code.
(scm_fluid_ref, scm_fluid_set_x): Lazily grow the dynamic state's fluid
vector.
(scm_fluids_prehistory): Don't set an `scm_after_sweep_c_hook'.
* libguile/fluids.h (SCM_FLUID_NUM, SCM_FAST_FLUID_REF, SCM_FAST_FLUID_SET_X,
scm_i_fluid_num, scm_i_fast_fluid_set_x, scm_i_fast_fluid_ref): Remove.
* libguile/load.c (the_reader_fluid_num): Remove.
(scm_primitive_load): Use `scm_fluid_ref ()' instead of
`SCM_FAST_FLUID_REF ()'.
(scm_init_load): Likewise.
2008-09-17 00:25:03 +02:00
|
|
|
|
|
|
|
|
|
|
if (SCM_UNLIKELY (FLUID_NUM (fluid) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
|
|
|
|
|
|
{
|
|
|
|
|
|
/* Lazily grow the current thread's dynamic state. */
|
|
|
|
|
|
grow_dynamic_state (SCM_I_CURRENT_THREAD->dynamic_state);
|
|
|
|
|
|
|
|
|
|
|
|
fluids = DYNAMIC_STATE_FLUIDS (SCM_I_CURRENT_THREAD->dynamic_state);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2005-03-02 20:42:01 +00:00
|
|
|
|
SCM_SIMPLE_VECTOR_SET (fluids, FLUID_NUM (fluid), value);
|
2000-08-24 00:23:19 +00:00
|
|
|
|
return SCM_UNSPECIFIED;
|
1997-07-18 16:26:47 +00:00
|
|
|
|
}
|
1999-12-12 02:36:16 +00:00
|
|
|
|
#undef FUNC_NAME
|
1997-07-18 16:26:47 +00:00
|
|
|
|
|
2010-02-18 17:10:29 +01:00
|
|
|
|
static SCM
|
|
|
|
|
|
apply_thunk (void *thunk)
|
1997-07-26 20:08:42 +00:00
|
|
|
|
{
|
2010-02-18 17:10:29 +01:00
|
|
|
|
return scm_call_0 (SCM_PACK (thunk));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM
|
|
|
|
|
|
scm_i_make_with_fluids (size_t n, SCM *fluids, SCM *vals)
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM ret;
|
|
|
|
|
|
|
|
|
|
|
|
/* Ensure that there are no duplicates in the fluids set -- an N^2 operation,
|
|
|
|
|
|
but N will usually be small, so perhaps that's OK. */
|
|
|
|
|
|
{
|
|
|
|
|
|
size_t i, j = n;
|
|
|
|
|
|
|
|
|
|
|
|
while (j--)
|
|
|
|
|
|
for (i = 0; i < j; i++)
|
|
|
|
|
|
if (fluids[i] == fluids[j])
|
|
|
|
|
|
{
|
|
|
|
|
|
vals[i] = vals[j]; /* later bindings win */
|
|
|
|
|
|
n--;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ret = scm_words (scm_tc7_with_fluids | (n << 8), 1 + n*2);
|
|
|
|
|
|
SCM_SET_CELL_WORD_1 (ret, n);
|
|
|
|
|
|
|
|
|
|
|
|
while (n--)
|
1997-07-26 20:08:42 +00:00
|
|
|
|
{
|
2010-02-18 17:10:29 +01:00
|
|
|
|
if (SCM_UNLIKELY (!IS_FLUID (fluids[n])))
|
|
|
|
|
|
scm_wrong_type_arg ("with-fluids", 0, fluids[n]);
|
|
|
|
|
|
SCM_SET_CELL_OBJECT (ret, 1 + n * 2, fluids[n]);
|
|
|
|
|
|
SCM_SET_CELL_OBJECT (ret, 2 + n * 2, vals[n]);
|
1997-07-26 20:08:42 +00:00
|
|
|
|
}
|
2010-02-18 17:10:29 +01:00
|
|
|
|
|
|
|
|
|
|
return ret;
|
1997-07-26 20:08:42 +00:00
|
|
|
|
}
|
2010-02-18 17:10:29 +01:00
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
|
scm_i_swap_with_fluids (SCM wf, SCM dynstate)
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM fluids;
|
|
|
|
|
|
size_t i, max = 0;
|
1997-07-26 20:08:42 +00:00
|
|
|
|
|
2010-02-18 17:10:29 +01:00
|
|
|
|
fluids = DYNAMIC_STATE_FLUIDS (dynstate);
|
1997-07-26 20:08:42 +00:00
|
|
|
|
|
2010-02-18 17:10:29 +01:00
|
|
|
|
/* We could cache the max in the with-fluids, but that would take more mem,
|
|
|
|
|
|
and we're touching all the fluids anyway, so this per-swap traversal should
|
|
|
|
|
|
be OK. */
|
|
|
|
|
|
for (i = 0; i < SCM_WITH_FLUIDS_LEN (wf); i++)
|
1997-07-26 20:08:42 +00:00
|
|
|
|
{
|
2010-02-18 17:10:29 +01:00
|
|
|
|
size_t num = FLUID_NUM (SCM_WITH_FLUIDS_NTH_FLUID (wf, i));
|
|
|
|
|
|
max = (max > num) ? max : num;
|
1997-07-26 20:08:42 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2010-02-18 17:10:29 +01:00
|
|
|
|
if (SCM_UNLIKELY (max >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
|
|
|
|
|
|
{
|
|
|
|
|
|
/* Lazily grow the current thread's dynamic state. */
|
|
|
|
|
|
grow_dynamic_state (dynstate);
|
|
|
|
|
|
|
|
|
|
|
|
fluids = DYNAMIC_STATE_FLUIDS (dynstate);
|
|
|
|
|
|
}
|
1999-12-12 02:36:16 +00:00
|
|
|
|
|
2010-02-18 17:10:29 +01:00
|
|
|
|
/* Bind the fluids. Order doesn't matter, as all fluids are distinct. */
|
|
|
|
|
|
for (i = 0; i < SCM_WITH_FLUIDS_LEN (wf); i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
size_t fluid_num;
|
|
|
|
|
|
SCM x;
|
|
|
|
|
|
|
|
|
|
|
|
fluid_num = FLUID_NUM (SCM_WITH_FLUIDS_NTH_FLUID (wf, i));
|
|
|
|
|
|
x = SCM_SIMPLE_VECTOR_REF (fluids, fluid_num);
|
|
|
|
|
|
SCM_SIMPLE_VECTOR_SET (fluids, fluid_num,
|
|
|
|
|
|
SCM_WITH_FLUIDS_NTH_VAL (wf, i));
|
|
|
|
|
|
SCM_WITH_FLUIDS_SET_NTH_VAL (wf, i, x);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2000-01-05 19:05:23 +00:00
|
|
|
|
SCM_DEFINE (scm_with_fluids, "with-fluids*", 3, 0, 0,
|
2000-03-15 16:28:13 +00:00
|
|
|
|
(SCM fluids, SCM values, SCM thunk),
|
|
|
|
|
|
"Set @var{fluids} to @var{values} temporary, and call @var{thunk}.\n"
|
|
|
|
|
|
"@var{fluids} must be a list of fluids and @var{values} must be the same\n"
|
|
|
|
|
|
"number of their values to be applied. Each substitution is done\n"
|
|
|
|
|
|
"one after another. @var{thunk} must be a procedure with no argument.")
|
1999-12-12 02:36:16 +00:00
|
|
|
|
#define FUNC_NAME s_scm_with_fluids
|
|
|
|
|
|
{
|
2004-01-07 19:47:18 +00:00
|
|
|
|
return scm_c_with_fluids (fluids, values,
|
|
|
|
|
|
apply_thunk, (void *) SCM_UNPACK (thunk));
|
1999-12-12 02:36:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
1997-07-26 20:08:42 +00:00
|
|
|
|
|
|
|
|
|
|
SCM
|
2001-05-19 00:36:22 +00:00
|
|
|
|
scm_c_with_fluids (SCM fluids, SCM values, SCM (*cproc) (), void *cdata)
|
|
|
|
|
|
#define FUNC_NAME "scm_c_with_fluids"
|
1997-07-26 20:08:42 +00:00
|
|
|
|
{
|
2010-02-18 17:10:29 +01:00
|
|
|
|
SCM wf, ans;
|
|
|
|
|
|
long flen, vlen, i;
|
|
|
|
|
|
SCM *fluidsv, *valuesv;
|
1997-07-26 20:08:42 +00:00
|
|
|
|
|
2000-01-12 01:51:18 +00:00
|
|
|
|
SCM_VALIDATE_LIST_COPYLEN (1, fluids, flen);
|
2000-03-15 16:28:13 +00:00
|
|
|
|
SCM_VALIDATE_LIST_COPYLEN (2, values, vlen);
|
1997-07-26 20:08:42 +00:00
|
|
|
|
if (flen != vlen)
|
2000-03-15 16:28:13 +00:00
|
|
|
|
scm_out_of_range (s_scm_with_fluids, values);
|
1997-07-26 20:08:42 +00:00
|
|
|
|
|
2010-02-18 17:10:29 +01:00
|
|
|
|
if (SCM_UNLIKELY (flen == 0))
|
|
|
|
|
|
return cproc (cdata);
|
|
|
|
|
|
|
|
|
|
|
|
fluidsv = alloca (sizeof(SCM)*flen);
|
|
|
|
|
|
valuesv = alloca (sizeof(SCM)*flen);
|
2004-01-07 19:47:18 +00:00
|
|
|
|
|
2010-02-18 17:10:29 +01:00
|
|
|
|
for (i = 0; i < flen; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
fluidsv[i] = SCM_CAR (fluids);
|
|
|
|
|
|
fluids = SCM_CDR (fluids);
|
|
|
|
|
|
valuesv[i] = SCM_CAR (values);
|
|
|
|
|
|
values = SCM_CDR (values);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
wf = scm_i_make_with_fluids (flen, fluidsv, valuesv);
|
|
|
|
|
|
scm_i_swap_with_fluids (wf, SCM_I_CURRENT_THREAD->dynamic_state);
|
|
|
|
|
|
scm_i_set_dynwinds (scm_cons (wf, scm_i_dynwinds ()));
|
1997-07-26 20:08:42 +00:00
|
|
|
|
ans = cproc (cdata);
|
2010-02-18 17:10:29 +01:00
|
|
|
|
scm_i_swap_with_fluids (wf, SCM_I_CURRENT_THREAD->dynamic_state);
|
|
|
|
|
|
scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
|
|
|
|
|
|
|
1997-07-26 20:08:42 +00:00
|
|
|
|
return ans;
|
|
|
|
|
|
}
|
2000-01-12 01:51:18 +00:00
|
|
|
|
#undef FUNC_NAME
|
1997-07-26 20:08:42 +00:00
|
|
|
|
|
2004-01-07 19:47:18 +00:00
|
|
|
|
SCM_DEFINE (scm_with_fluid, "with-fluid*", 3, 0, 0,
|
|
|
|
|
|
(SCM fluid, SCM value, SCM thunk),
|
|
|
|
|
|
"Set @var{fluid} to @var{value} temporarily, and call @var{thunk}.\n"
|
|
|
|
|
|
"@var{thunk} must be a procedure with no argument.")
|
|
|
|
|
|
#define FUNC_NAME s_scm_with_fluid
|
|
|
|
|
|
{
|
|
|
|
|
|
return scm_c_with_fluid (fluid, value,
|
|
|
|
|
|
apply_thunk, (void *) SCM_UNPACK (thunk));
|
|
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
|
2001-05-19 00:36:22 +00:00
|
|
|
|
SCM
|
|
|
|
|
|
scm_c_with_fluid (SCM fluid, SCM value, SCM (*cproc) (), void *cdata)
|
|
|
|
|
|
#define FUNC_NAME "scm_c_with_fluid"
|
|
|
|
|
|
{
|
2010-02-18 17:10:29 +01:00
|
|
|
|
SCM ans, wf;
|
2004-01-07 19:47:18 +00:00
|
|
|
|
|
2010-02-18 17:10:29 +01:00
|
|
|
|
wf = scm_i_make_with_fluids (1, &fluid, &value);
|
|
|
|
|
|
scm_i_swap_with_fluids (wf, SCM_I_CURRENT_THREAD->dynamic_state);
|
|
|
|
|
|
scm_i_set_dynwinds (scm_cons (wf, scm_i_dynwinds ()));
|
2004-01-07 19:47:18 +00:00
|
|
|
|
ans = cproc (cdata);
|
2010-02-18 17:10:29 +01:00
|
|
|
|
scm_i_swap_with_fluids (wf, SCM_I_CURRENT_THREAD->dynamic_state);
|
|
|
|
|
|
scm_i_set_dynwinds (scm_cdr (scm_i_dynwinds ()));
|
|
|
|
|
|
|
2004-01-07 19:47:18 +00:00
|
|
|
|
return ans;
|
2001-05-19 00:36:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
1997-07-26 20:08:42 +00:00
|
|
|
|
|
2004-01-07 18:08:52 +00:00
|
|
|
|
static void
|
|
|
|
|
|
swap_fluid (SCM data)
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM f = SCM_CAR (data);
|
|
|
|
|
|
SCM t = scm_fluid_ref (f);
|
|
|
|
|
|
scm_fluid_set_x (f, SCM_CDR (data));
|
|
|
|
|
|
SCM_SETCDR (data, t);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2006-01-29 00:23:28 +00:00
|
|
|
|
scm_dynwind_fluid (SCM fluid, SCM value)
|
2004-01-07 18:08:52 +00:00
|
|
|
|
{
|
|
|
|
|
|
SCM data = scm_cons (fluid, value);
|
2006-01-29 00:23:28 +00:00
|
|
|
|
scm_dynwind_rewind_handler_with_scm (swap_fluid, data, SCM_F_WIND_EXPLICITLY);
|
|
|
|
|
|
scm_dynwind_unwind_handler_with_scm (swap_fluid, data, SCM_F_WIND_EXPLICITLY);
|
2004-01-07 18:08:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2005-03-02 20:42:01 +00:00
|
|
|
|
SCM
|
|
|
|
|
|
scm_i_make_initial_dynamic_state ()
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM fluids = scm_c_make_vector (allocated_fluids_len, SCM_BOOL_F);
|
fluids are tc7 objects
If you're wondering what I'm doing, I'm trying to eventually reimplement
smobs in terms of structs, so that applicable smobs can just follow the
applicable struct dispatch path. But to do that I have to get structs
initialized before things that use smobs, which means transforming a
bunch of smobby things to tc7 things. But this transformation is good
for performance anyway, and we currently have a glut of unused tc7s,
so here we go...
* libguile/tags.h (scm_tc7_fluid, scm_tc7_dynamic_state): Fluids (and
dynamic states) now have tc7s.
* libguile/fluids.h: Remove scm_fluids_prehistory, and add internal
scm_i_fluid_print. Update a comment.
* libguile/fluids.c: Update for tc7 representation. Also remove the next
pointers while we're at it, as they aren't used in the new BDW GC.
* libguile/eq.c (scm_equal_p): Remove the hashtable case. Hashtables
could never be equal? before, I don't see why to add stubs doing the
same thing now.
* libguile/print.c (iprin1):
* libguile/gc.c (scm_i_tag_name):
* libguile/evalext.c (scm_self_evaluating_p): Add fluid and
dynamic_state cases.
* libguile/goops.h: Remove scm_class_hashtable; it will be static.
* libguile/goops.c: Make <hashtable> static, and add <fluid> and
<dynamic-state> classes.
* libguile/hashtab.h:
* libguile/hashtab.c: Remove scm_i_hashtable_equal_p.
* libguile/init.c (scm_i_init_guile): Remove call to fluids_prehistory.
2009-12-05 10:52:18 +01:00
|
|
|
|
return scm_cell (scm_tc7_dynamic_state, SCM_UNPACK (fluids));
|
2005-03-02 20:42:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_DEFINE (scm_make_dynamic_state, "make-dynamic-state", 0, 1, 0,
|
|
|
|
|
|
(SCM parent),
|
|
|
|
|
|
"Return a copy of the dynamic state object @var{parent}\n"
|
|
|
|
|
|
"or of the current dynamic state when @var{parent} is omitted.")
|
|
|
|
|
|
#define FUNC_NAME s_scm_make_dynamic_state
|
|
|
|
|
|
{
|
fluids are tc7 objects
If you're wondering what I'm doing, I'm trying to eventually reimplement
smobs in terms of structs, so that applicable smobs can just follow the
applicable struct dispatch path. But to do that I have to get structs
initialized before things that use smobs, which means transforming a
bunch of smobby things to tc7 things. But this transformation is good
for performance anyway, and we currently have a glut of unused tc7s,
so here we go...
* libguile/tags.h (scm_tc7_fluid, scm_tc7_dynamic_state): Fluids (and
dynamic states) now have tc7s.
* libguile/fluids.h: Remove scm_fluids_prehistory, and add internal
scm_i_fluid_print. Update a comment.
* libguile/fluids.c: Update for tc7 representation. Also remove the next
pointers while we're at it, as they aren't used in the new BDW GC.
* libguile/eq.c (scm_equal_p): Remove the hashtable case. Hashtables
could never be equal? before, I don't see why to add stubs doing the
same thing now.
* libguile/print.c (iprin1):
* libguile/gc.c (scm_i_tag_name):
* libguile/evalext.c (scm_self_evaluating_p): Add fluid and
dynamic_state cases.
* libguile/goops.h: Remove scm_class_hashtable; it will be static.
* libguile/goops.c: Make <hashtable> static, and add <fluid> and
<dynamic-state> classes.
* libguile/hashtab.h:
* libguile/hashtab.c: Remove scm_i_hashtable_equal_p.
* libguile/init.c (scm_i_init_guile): Remove call to fluids_prehistory.
2009-12-05 10:52:18 +01:00
|
|
|
|
SCM fluids;
|
2005-03-02 20:42:01 +00:00
|
|
|
|
|
|
|
|
|
|
if (SCM_UNBNDP (parent))
|
|
|
|
|
|
parent = scm_current_dynamic_state ();
|
|
|
|
|
|
|
fluids are tc7 objects
If you're wondering what I'm doing, I'm trying to eventually reimplement
smobs in terms of structs, so that applicable smobs can just follow the
applicable struct dispatch path. But to do that I have to get structs
initialized before things that use smobs, which means transforming a
bunch of smobby things to tc7 things. But this transformation is good
for performance anyway, and we currently have a glut of unused tc7s,
so here we go...
* libguile/tags.h (scm_tc7_fluid, scm_tc7_dynamic_state): Fluids (and
dynamic states) now have tc7s.
* libguile/fluids.h: Remove scm_fluids_prehistory, and add internal
scm_i_fluid_print. Update a comment.
* libguile/fluids.c: Update for tc7 representation. Also remove the next
pointers while we're at it, as they aren't used in the new BDW GC.
* libguile/eq.c (scm_equal_p): Remove the hashtable case. Hashtables
could never be equal? before, I don't see why to add stubs doing the
same thing now.
* libguile/print.c (iprin1):
* libguile/gc.c (scm_i_tag_name):
* libguile/evalext.c (scm_self_evaluating_p): Add fluid and
dynamic_state cases.
* libguile/goops.h: Remove scm_class_hashtable; it will be static.
* libguile/goops.c: Make <hashtable> static, and add <fluid> and
<dynamic-state> classes.
* libguile/hashtab.h:
* libguile/hashtab.c: Remove scm_i_hashtable_equal_p.
* libguile/init.c (scm_i_init_guile): Remove call to fluids_prehistory.
2009-12-05 10:52:18 +01:00
|
|
|
|
SCM_ASSERT (IS_DYNAMIC_STATE (parent), parent, SCM_ARG1, FUNC_NAME);
|
2005-03-02 20:42:01 +00:00
|
|
|
|
fluids = scm_vector_copy (DYNAMIC_STATE_FLUIDS (parent));
|
fluids are tc7 objects
If you're wondering what I'm doing, I'm trying to eventually reimplement
smobs in terms of structs, so that applicable smobs can just follow the
applicable struct dispatch path. But to do that I have to get structs
initialized before things that use smobs, which means transforming a
bunch of smobby things to tc7 things. But this transformation is good
for performance anyway, and we currently have a glut of unused tc7s,
so here we go...
* libguile/tags.h (scm_tc7_fluid, scm_tc7_dynamic_state): Fluids (and
dynamic states) now have tc7s.
* libguile/fluids.h: Remove scm_fluids_prehistory, and add internal
scm_i_fluid_print. Update a comment.
* libguile/fluids.c: Update for tc7 representation. Also remove the next
pointers while we're at it, as they aren't used in the new BDW GC.
* libguile/eq.c (scm_equal_p): Remove the hashtable case. Hashtables
could never be equal? before, I don't see why to add stubs doing the
same thing now.
* libguile/print.c (iprin1):
* libguile/gc.c (scm_i_tag_name):
* libguile/evalext.c (scm_self_evaluating_p): Add fluid and
dynamic_state cases.
* libguile/goops.h: Remove scm_class_hashtable; it will be static.
* libguile/goops.c: Make <hashtable> static, and add <fluid> and
<dynamic-state> classes.
* libguile/hashtab.h:
* libguile/hashtab.c: Remove scm_i_hashtable_equal_p.
* libguile/init.c (scm_i_init_guile): Remove call to fluids_prehistory.
2009-12-05 10:52:18 +01:00
|
|
|
|
return scm_cell (scm_tc7_dynamic_state, SCM_UNPACK (fluids));
|
2005-03-02 20:42:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
|
|
|
|
|
|
SCM_DEFINE (scm_dynamic_state_p, "dynamic-state?", 1, 0, 0,
|
|
|
|
|
|
(SCM obj),
|
|
|
|
|
|
"Return @code{#t} if @var{obj} is a dynamic state object;\n"
|
|
|
|
|
|
"return @code{#f} otherwise")
|
|
|
|
|
|
#define FUNC_NAME s_scm_dynamic_state_p
|
|
|
|
|
|
{
|
|
|
|
|
|
return scm_from_bool (IS_DYNAMIC_STATE (obj));
|
|
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
|
scm_is_dynamic_state (SCM obj)
|
|
|
|
|
|
{
|
|
|
|
|
|
return IS_DYNAMIC_STATE (obj);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_DEFINE (scm_current_dynamic_state, "current-dynamic-state", 0, 0, 0,
|
|
|
|
|
|
(),
|
|
|
|
|
|
"Return the current dynamic state object.")
|
|
|
|
|
|
#define FUNC_NAME s_scm_current_dynamic_state
|
|
|
|
|
|
{
|
|
|
|
|
|
return SCM_I_CURRENT_THREAD->dynamic_state;
|
|
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
|
|
|
|
|
|
SCM_DEFINE (scm_set_current_dynamic_state, "set-current-dynamic-state", 1,0,0,
|
|
|
|
|
|
(SCM state),
|
|
|
|
|
|
"Set the current dynamic state object to @var{state}\n"
|
|
|
|
|
|
"and return the previous current dynamic state object.")
|
|
|
|
|
|
#define FUNC_NAME s_scm_set_current_dynamic_state
|
|
|
|
|
|
{
|
|
|
|
|
|
scm_i_thread *t = SCM_I_CURRENT_THREAD;
|
|
|
|
|
|
SCM old = t->dynamic_state;
|
fluids are tc7 objects
If you're wondering what I'm doing, I'm trying to eventually reimplement
smobs in terms of structs, so that applicable smobs can just follow the
applicable struct dispatch path. But to do that I have to get structs
initialized before things that use smobs, which means transforming a
bunch of smobby things to tc7 things. But this transformation is good
for performance anyway, and we currently have a glut of unused tc7s,
so here we go...
* libguile/tags.h (scm_tc7_fluid, scm_tc7_dynamic_state): Fluids (and
dynamic states) now have tc7s.
* libguile/fluids.h: Remove scm_fluids_prehistory, and add internal
scm_i_fluid_print. Update a comment.
* libguile/fluids.c: Update for tc7 representation. Also remove the next
pointers while we're at it, as they aren't used in the new BDW GC.
* libguile/eq.c (scm_equal_p): Remove the hashtable case. Hashtables
could never be equal? before, I don't see why to add stubs doing the
same thing now.
* libguile/print.c (iprin1):
* libguile/gc.c (scm_i_tag_name):
* libguile/evalext.c (scm_self_evaluating_p): Add fluid and
dynamic_state cases.
* libguile/goops.h: Remove scm_class_hashtable; it will be static.
* libguile/goops.c: Make <hashtable> static, and add <fluid> and
<dynamic-state> classes.
* libguile/hashtab.h:
* libguile/hashtab.c: Remove scm_i_hashtable_equal_p.
* libguile/init.c (scm_i_init_guile): Remove call to fluids_prehistory.
2009-12-05 10:52:18 +01:00
|
|
|
|
SCM_ASSERT (IS_DYNAMIC_STATE (state), state, SCM_ARG1, FUNC_NAME);
|
2005-03-02 20:42:01 +00:00
|
|
|
|
t->dynamic_state = state;
|
|
|
|
|
|
return old;
|
|
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
|
swap_dynamic_state (SCM loc)
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM_SETCAR (loc, scm_set_current_dynamic_state (SCM_CAR (loc)));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2006-01-29 00:23:28 +00:00
|
|
|
|
scm_dynwind_current_dynamic_state (SCM state)
|
2005-03-02 20:42:01 +00:00
|
|
|
|
{
|
|
|
|
|
|
SCM loc = scm_cons (state, SCM_EOL);
|
fluids are tc7 objects
If you're wondering what I'm doing, I'm trying to eventually reimplement
smobs in terms of structs, so that applicable smobs can just follow the
applicable struct dispatch path. But to do that I have to get structs
initialized before things that use smobs, which means transforming a
bunch of smobby things to tc7 things. But this transformation is good
for performance anyway, and we currently have a glut of unused tc7s,
so here we go...
* libguile/tags.h (scm_tc7_fluid, scm_tc7_dynamic_state): Fluids (and
dynamic states) now have tc7s.
* libguile/fluids.h: Remove scm_fluids_prehistory, and add internal
scm_i_fluid_print. Update a comment.
* libguile/fluids.c: Update for tc7 representation. Also remove the next
pointers while we're at it, as they aren't used in the new BDW GC.
* libguile/eq.c (scm_equal_p): Remove the hashtable case. Hashtables
could never be equal? before, I don't see why to add stubs doing the
same thing now.
* libguile/print.c (iprin1):
* libguile/gc.c (scm_i_tag_name):
* libguile/evalext.c (scm_self_evaluating_p): Add fluid and
dynamic_state cases.
* libguile/goops.h: Remove scm_class_hashtable; it will be static.
* libguile/goops.c: Make <hashtable> static, and add <fluid> and
<dynamic-state> classes.
* libguile/hashtab.h:
* libguile/hashtab.c: Remove scm_i_hashtable_equal_p.
* libguile/init.c (scm_i_init_guile): Remove call to fluids_prehistory.
2009-12-05 10:52:18 +01:00
|
|
|
|
SCM_ASSERT (IS_DYNAMIC_STATE (state), state, SCM_ARG1, NULL);
|
2006-01-29 00:23:28 +00:00
|
|
|
|
scm_dynwind_rewind_handler_with_scm (swap_dynamic_state, loc,
|
2005-03-02 20:42:01 +00:00
|
|
|
|
SCM_F_WIND_EXPLICITLY);
|
2006-01-29 00:23:28 +00:00
|
|
|
|
scm_dynwind_unwind_handler_with_scm (swap_dynamic_state, loc,
|
2005-03-02 20:42:01 +00:00
|
|
|
|
SCM_F_WIND_EXPLICITLY);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void *
|
|
|
|
|
|
scm_c_with_dynamic_state (SCM state, void *(*func)(void *), void *data)
|
|
|
|
|
|
{
|
|
|
|
|
|
void *result;
|
2006-01-29 00:23:28 +00:00
|
|
|
|
scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
|
|
|
|
|
|
scm_dynwind_current_dynamic_state (state);
|
2005-03-02 20:42:01 +00:00
|
|
|
|
result = func (data);
|
2006-01-29 00:23:28 +00:00
|
|
|
|
scm_dynwind_end ();
|
2005-03-02 20:42:01 +00:00
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SCM_DEFINE (scm_with_dynamic_state, "with-dynamic-state", 2, 0, 0,
|
|
|
|
|
|
(SCM state, SCM proc),
|
|
|
|
|
|
"Call @var{proc} while @var{state} is the current dynamic\n"
|
|
|
|
|
|
"state object.")
|
|
|
|
|
|
#define FUNC_NAME s_scm_with_dynamic_state
|
|
|
|
|
|
{
|
|
|
|
|
|
SCM result;
|
2006-01-29 00:23:28 +00:00
|
|
|
|
scm_dynwind_begin (SCM_F_DYNWIND_REWINDABLE);
|
|
|
|
|
|
scm_dynwind_current_dynamic_state (state);
|
2005-03-02 20:42:01 +00:00
|
|
|
|
result = scm_call_0 (proc);
|
2006-01-29 00:23:28 +00:00
|
|
|
|
scm_dynwind_end ();
|
2005-03-02 20:42:01 +00:00
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
#undef FUNC_NAME
|
|
|
|
|
|
|
|
|
|
|
|
|
1997-07-18 16:26:47 +00:00
|
|
|
|
void
|
|
|
|
|
|
scm_init_fluids ()
|
|
|
|
|
|
{
|
2000-04-21 14:16:44 +00:00
|
|
|
|
#include "libguile/fluids.x"
|
1997-07-18 16:26:47 +00:00
|
|
|
|
}
|
2000-03-19 19:01:16 +00:00
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
Local Variables:
|
|
|
|
|
|
c-file-style: "gnu"
|
|
|
|
|
|
End:
|
|
|
|
|
|
*/
|