[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Fluids
From: |
Ludovic Courtès |
Subject: |
Re: Fluids |
Date: |
Wed, 03 Mar 2010 00:52:05 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) |
Hello,
address@hidden (Ludovic Courtès) writes:
> Andy Wingo <address@hidden> writes:
>
>> But you can't / shouldn't make a new fluid every time you enter a
>> `catch', because currently fluids are never garbage collected! We really
>> need to fix this. I think it's a 1.9 regression.
>
> Indeed. We should use a weak vector or some such instead of the current
> scm_gc_malloc’d array.
Just to clarify: fluids themselves *are* GC’d, but fluid numbers aren’t
recycled so ALLOCATED_FLUIDS grows endlessly (1 byte per fluid).
The working patch below allows fluid numbers to be recycled but it’s
inefficient. Needs more thought.
Thanks,
Ludo’.
diff --git a/libguile/fluids.c b/libguile/fluids.c
index d493053..157737a 100644
--- a/libguile/fluids.c
+++ b/libguile/fluids.c
@@ -34,6 +34,7 @@
#include "libguile/deprecation.h"
#include "libguile/lang.h"
#include "libguile/validate.h"
+#include "libguile/bdw-gc.h"
#define FLUID_GROW 20
@@ -63,7 +64,7 @@ static scm_i_pthread_mutex_t fluid_admin_mutex =
SCM_I_PTHREAD_MUTEX_INITIALIZER
*/
static size_t allocated_fluids_len = 0;
static size_t allocated_fluids_num = 0;
-static char *allocated_fluids = NULL;
+static void **allocated_fluids = NULL;
#define IS_FLUID(x) SCM_I_FLUID_P (x)
#define FLUID_NUM(x) SCM_I_FLUID_NUM (x)
@@ -120,45 +121,53 @@ scm_i_dynamic_state_print (SCM exp, SCM port,
scm_print_state *pstate SCM_UNUSED
scm_putc ('>', port);
}
-static size_t
-next_fluid_num ()
+static SCM
+new_fluid ()
{
size_t n;
+ SCM fluid;
+
+ /* Fluids are 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);
+
+ /* Look for a fluid number. */
scm_dynwind_begin (0);
scm_i_dynwind_pthread_mutex_lock (&fluid_admin_mutex);
- if ((allocated_fluids_len > 0) &&
- (allocated_fluids_num == allocated_fluids_len))
- {
- /* All fluid numbers are in use. Run a GC to try to free some
- up.
- */
- scm_gc ();
- }
-
if (allocated_fluids_num < allocated_fluids_len)
+ n = allocated_fluids_num;
+ else
{
+ /* All fluid numbers are in use. Run a GC and look for a number recently
+ freed. */
+ scm_i_gc ("fluids");
+
for (n = 0; n < allocated_fluids_len; n++)
- if (allocated_fluids[n] == 0)
- break;
+ if (allocated_fluids[n] == NULL)
+ {
+ allocated_fluids_num--;
+ break;
+ }
}
- else
+
+ if (n >= allocated_fluids_len)
{
/* Grow the vector of allocated fluids. */
- /* FIXME: Since we use `scm_malloc ()', ALLOCATED_FLUIDS is scanned by
- the GC; therefore, all fluids remain reachable for the entire
- program lifetime. Hopefully this is not a problem in practice. */
- char *new_allocated_fluids =
- scm_gc_malloc (allocated_fluids_len + FLUID_GROW,
- "allocated fluids");
+ void **new_allocated_fluids =
+ scm_gc_malloc_pointerless ((allocated_fluids_len + FLUID_GROW)
+ * sizeof (*allocated_fluids),
+ "allocated fluids");
/* Copy over old values and initialize rest. GC can not run
during these two operations since there is no safe point in
- them.
- */
- memcpy (new_allocated_fluids, allocated_fluids, allocated_fluids_len);
- memset (new_allocated_fluids + allocated_fluids_len, 0, FLUID_GROW);
+ 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));
n = allocated_fluids_len;
/* Update the vector of allocated fluids. Dynamic states will
@@ -167,12 +176,16 @@ next_fluid_num ()
allocated_fluids = new_allocated_fluids;
allocated_fluids_len += FLUID_GROW;
}
-
+
allocated_fluids_num += 1;
- allocated_fluids[n] = 1;
-
+ 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));
+
scm_dynwind_end ();
- return n;
+ return fluid;
}
SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0,
@@ -186,7 +199,7 @@ SCM_DEFINE (scm_make_fluid, "make-fluid", 0, 0, 0,
"with its own dynamic state, you can use fluids for thread local
storage.")
#define FUNC_NAME s_scm_make_fluid
{
- return scm_cell (scm_tc7_fluid, (scm_t_bits) next_fluid_num ());
+ return new_fluid ();
}
#undef FUNC_NAME
- Re: Fluids,
Ludovic Courtès <=