diff options
Diffstat (limited to 'libguile/goops.c')
-rw-r--r-- | libguile/goops.c | 48 |
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 (); |