summaryrefslogtreecommitdiff
path: root/libguile/goops.c
diff options
context:
space:
mode:
Diffstat (limited to 'libguile/goops.c')
-rw-r--r--libguile/goops.c48
1 files changed, 28 insertions, 20 deletions
diff --git a/libguile/goops.c b/libguile/goops.c
index 2f1dc7e5c..975c3dd29 100644
--- a/libguile/goops.c
+++ b/libguile/goops.c
@@ -33,6 +33,7 @@
#include "boolean.h"
#include "chars.h"
#include "dynwind.h"
+#include "ephemerons.h"
#include "eval.h"
#include "extensions.h"
#include "foreign.h"
@@ -54,7 +55,6 @@
#include "variable.h"
#include "vectors.h"
#include "version.h"
-#include "weak-table.h"
#include "goops.h"
@@ -136,8 +136,10 @@ static SCM class_thread;
static SCM class_bitvector;
static SCM class_finalizer;
static SCM class_ephemeron;
+static SCM class_ephemeron_table;
-static SCM vtable_class_map = SCM_BOOL_F;
+static struct scm_ephemeron_table *vtable_class_map;
+static SCM pre_goops_vtables = SCM_EOL;
/* SMOB classes. */
SCM scm_i_smob_class[SCM_I_MAX_SMOB_TYPE_COUNT];
@@ -262,6 +264,8 @@ SCM_DEFINE (scm_class_of, "class-of", 1, 0, 0,
return class_finalizer;
case scm_tc7_ephemeron:
return class_ephemeron;
+ case scm_tc7_ephemeron_table:
+ return class_ephemeron_table;
case scm_tc7_thread:
return class_thread;
case scm_tc7_string:
@@ -776,15 +780,21 @@ scm_i_define_class_for_vtable (SCM vtable)
{
SCM class;
- scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
- if (scm_is_false (vtable_class_map))
- vtable_class_map = scm_c_make_weak_table (0, SCM_WEAK_TABLE_KIND_KEY);
- scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
+ if (!SCM_UNPACK (class_class))
+ {
+ // FIXME: Race condition between one thread booting GOOPS
+ // (definining class_class) and another defining vtables.
+ scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
+ pre_goops_vtables = scm_cons (vtable, pre_goops_vtables);
+ scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
+ return SCM_BOOL_F;
+ }
if (scm_is_false (scm_struct_vtable_p (vtable)))
abort ();
- class = scm_weak_table_refq (vtable_class_map, vtable, SCM_BOOL_F);
+ class = scm_c_ephemeron_hash_table_refq (vtable_class_map, vtable,
+ SCM_BOOL_F);
if (scm_is_false (class))
{
@@ -827,27 +837,23 @@ scm_i_define_class_for_vtable (SCM vtable)
/* Don't worry about races. This only happens when creating a
vtable, which happens by definition in one thread. */
- scm_weak_table_putq_x (vtable_class_map, vtable, class);
+ scm_c_ephemeron_hash_table_setq_x (vtable_class_map, vtable, class);
}
return class;
}
-static SCM
-make_struct_class (void *closure SCM_UNUSED,
- SCM vtable, SCM data, SCM prev SCM_UNUSED)
-{
- if (scm_is_false (data))
- scm_i_define_class_for_vtable (vtable);
- return SCM_UNSPECIFIED;
-}
-
static void
create_struct_classes (void)
{
- /* FIXME: take the vtable_class_map while initializing goops? */
- scm_internal_hash_fold (make_struct_class, 0, SCM_BOOL_F,
- vtable_class_map);
+ scm_i_pthread_mutex_lock (&scm_i_misc_mutex);
+ SCM vtables = pre_goops_vtables;
+ pre_goops_vtables = SCM_EOL;
+ vtable_class_map = scm_c_make_ephemeron_table (255);
+ scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
+
+ for (; scm_is_pair (vtables); vtables = scm_cdr (vtables))
+ scm_i_define_class_for_vtable (scm_car (vtables));
}
@@ -958,6 +964,8 @@ SCM_DEFINE (scm_sys_goops_early_init, "%goops-early-init", 0, 0, 0,
class_input_port = scm_variable_ref (scm_c_lookup ("<input-port>"));
class_output_port = scm_variable_ref (scm_c_lookup ("<output-port>"));
class_input_output_port = scm_variable_ref (scm_c_lookup ("<input-output-port>"));
+ class_ephemeron = scm_variable_ref (scm_c_lookup ("<ephemeron>"));
+ class_ephemeron_table = scm_variable_ref (scm_c_lookup ("<ephemeron-table>"));
create_smob_classes ();
create_struct_classes ();