summaryrefslogtreecommitdiff
path: root/weakmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'weakmap.c')
-rw-r--r--weakmap.c520
1 files changed, 205 insertions, 315 deletions
diff --git a/weakmap.c b/weakmap.c
index 7125c1707a..80ef29b4cc 100644
--- a/weakmap.c
+++ b/weakmap.c
@@ -4,7 +4,6 @@
#include "internal/proc.h"
#include "internal/sanitizers.h"
#include "ruby/st.h"
-#include "ruby/st.h"
/* ===== WeakMap =====
*
@@ -30,132 +29,117 @@ struct weakmap {
st_table *table;
};
-static bool
-wmap_live_p(VALUE obj)
+struct weakmap_entry {
+ VALUE key;
+ VALUE val;
+};
+
+static void
+wmap_free(void *ptr)
{
- return !UNDEF_P(obj);
+ struct weakmap *w = ptr;
+
+ st_free_table(w->table);
}
-static void
-wmap_free_entry(VALUE *key, VALUE *val)
+static size_t
+wmap_memsize(const void *ptr)
{
- assert(key + 1 == val);
+ const struct weakmap *w = ptr;
- /* We only need to free key because val is allocated beside key on in the
- * same malloc call. */
- ruby_sized_xfree(key, sizeof(VALUE) * 2);
+ size_t size = 0;
+ if (w->table) {
+ size += st_memsize(w->table);
+ /* The key and value of the table each take sizeof(VALUE) in size. */
+ size += st_table_size(w->table) * (2 * sizeof(VALUE));
+ }
+
+ return size;
}
+struct wmap_compact_table_data {
+ st_table *table;
+ struct weakmap_entry *dead_entry;
+};
+
static int
-wmap_mark_weak_table_i(st_data_t key, st_data_t val, st_data_t _)
+wmap_compact_table_each_i(st_data_t k, st_data_t v, st_data_t d, int error)
{
- VALUE key_obj = *(VALUE *)key;
- VALUE val_obj = *(VALUE *)val;
+ st_table *table = (st_table *)d;
- if (wmap_live_p(key_obj) && wmap_live_p(val_obj)) {
- rb_gc_mark_weak((VALUE *)key);
- rb_gc_mark_weak((VALUE *)val);
+ VALUE key = (VALUE)k;
+ VALUE val = (VALUE)v;
- return ST_CONTINUE;
- }
- else {
- wmap_free_entry((VALUE *)key, (VALUE *)val);
+ VALUE moved_key = rb_gc_location(key);
+ VALUE moved_val = rb_gc_location(val);
+
+ /* If the key object moves, then we must reinsert because the hash is
+ * based on the pointer rather than the object itself. */
+ if (key != moved_key) {
+ st_insert(table, (st_data_t)moved_key, (st_data_t)moved_val);
return ST_DELETE;
}
-}
-
-static void
-wmap_mark(void *ptr)
-{
- struct weakmap *w = ptr;
- if (w->table) {
- st_foreach(w->table, wmap_mark_weak_table_i, (st_data_t)0);
+ else if (val != moved_val) {
+ return ST_REPLACE;
+ }
+ else {
+ return ST_CONTINUE;
}
}
static int
-wmap_free_table_i(st_data_t key, st_data_t val, st_data_t arg)
+wmap_compact_table_replace_i(st_data_t *k, st_data_t *v, st_data_t d, int existing)
{
- wmap_free_entry((VALUE *)key, (VALUE *)val);
+ RUBY_ASSERT((VALUE)*k == rb_gc_location((VALUE)*k));
+
+ *v = (st_data_t)rb_gc_location((VALUE)*v);
+
return ST_CONTINUE;
}
static void
-wmap_free(void *ptr)
+wmap_compact(void *ptr)
{
struct weakmap *w = ptr;
- st_foreach(w->table, wmap_free_table_i, 0);
- st_free_table(w->table);
-}
-
-static size_t
-wmap_memsize(const void *ptr)
-{
- const struct weakmap *w = ptr;
-
- size_t size = 0;
- size += st_memsize(w->table);
- /* The key and value of the table each take sizeof(VALUE) in size. */
- size += st_table_size(w->table) * (2 * sizeof(VALUE));
-
- return size;
+ if (w->table) {
+ DURING_GC_COULD_MALLOC_REGION_START();
+ {
+ st_foreach_with_replace(w->table, wmap_compact_table_each_i, wmap_compact_table_replace_i, (st_data_t)w->table);
+ }
+ DURING_GC_COULD_MALLOC_REGION_END();
+ }
}
static int
-wmap_compact_table_i(st_data_t key, st_data_t val, st_data_t data)
+rb_wmap_handle_weak_references_i(st_data_t key, st_data_t val, st_data_t arg)
{
- st_table *table = (st_table *)data;
-
- VALUE key_obj = *(VALUE *)key;
- VALUE val_obj = *(VALUE *)val;
-
- if (wmap_live_p(key_obj) && wmap_live_p(val_obj)) {
- VALUE new_key_obj = rb_gc_location(key_obj);
-
- *(VALUE *)val = rb_gc_location(val_obj);
-
- /* If the key object moves, then we must reinsert because the hash is
- * based on the pointer rather than the object itself. */
- if (key_obj != new_key_obj) {
- *(VALUE *)key = new_key_obj;
-
- DURING_GC_COULD_MALLOC_REGION_START();
- {
- st_insert(table, key, val);
- }
- DURING_GC_COULD_MALLOC_REGION_END();
-
- return ST_DELETE;
- }
+ if (rb_gc_handle_weak_references_alive_p(key) &&
+ rb_gc_handle_weak_references_alive_p(val)) {
+ return ST_CONTINUE;
}
else {
- wmap_free_entry((VALUE *)key, (VALUE *)val);
-
return ST_DELETE;
}
-
- return ST_CONTINUE;
}
static void
-wmap_compact(void *ptr)
+wmap_handle_weak_references(void *ptr)
{
struct weakmap *w = ptr;
- if (w->table) {
- st_foreach(w->table, wmap_compact_table_i, (st_data_t)w->table);
- }
+ st_foreach(w->table, rb_wmap_handle_weak_references_i, (st_data_t)0);
}
-static const rb_data_type_t weakmap_type = {
+const rb_data_type_t rb_weakmap_type = {
"weakmap",
{
- wmap_mark,
+ NULL,
wmap_free,
wmap_memsize,
wmap_compact,
+ wmap_handle_weak_references,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
@@ -163,13 +147,13 @@ static const rb_data_type_t weakmap_type = {
static int
wmap_cmp(st_data_t x, st_data_t y)
{
- return *(VALUE *)x != *(VALUE *)y;
+ return x != y;
}
static st_index_t
wmap_hash(st_data_t n)
{
- return st_numhash(*(VALUE *)n);
+ return st_numhash(n);
}
static const struct st_hash_type wmap_hash_type = {
@@ -181,47 +165,13 @@ static VALUE
wmap_allocate(VALUE klass)
{
struct weakmap *w;
- VALUE obj = TypedData_Make_Struct(klass, struct weakmap, &weakmap_type, w);
- w->table = st_init_table(&wmap_hash_type);
- return obj;
-}
-
-struct wmap_foreach_data {
- struct weakmap *w;
- void (*func)(VALUE, VALUE, st_data_t);
- st_data_t arg;
-};
-
-static int
-wmap_foreach_i(st_data_t key, st_data_t val, st_data_t arg)
-{
- struct wmap_foreach_data *data = (struct wmap_foreach_data *)arg;
-
- VALUE key_obj = *(VALUE *)key;
- VALUE val_obj = *(VALUE *)val;
+ VALUE obj = TypedData_Make_Struct(klass, struct weakmap, &rb_weakmap_type, w);
- if (wmap_live_p(key_obj) && wmap_live_p(val_obj)) {
- data->func(key_obj, val_obj, data->arg);
- }
- else {
- wmap_free_entry((VALUE *)key, (VALUE *)val);
-
- return ST_DELETE;
- }
-
- return ST_CONTINUE;
-}
+ w->table = st_init_table(&wmap_hash_type);
-static void
-wmap_foreach(struct weakmap *w, void (*func)(VALUE, VALUE, st_data_t), st_data_t arg)
-{
- struct wmap_foreach_data foreach_data = {
- .w = w,
- .func = func,
- .arg = arg,
- };
+ rb_gc_declare_weak_references(obj);
- st_foreach(w->table, wmap_foreach_i, (st_data_t)&foreach_data);
+ return obj;
}
static VALUE
@@ -235,9 +185,11 @@ wmap_inspect_append(VALUE str, VALUE obj)
}
}
-static void
-wmap_inspect_i(VALUE key, VALUE val, st_data_t data)
+static int
+wmap_inspect_i(st_data_t k, st_data_t v, st_data_t data)
{
+ VALUE key = (VALUE)k;
+ VALUE val = (VALUE)v;
VALUE str = (VALUE)data;
if (RSTRING_PTR(str)[0] == '#') {
@@ -251,18 +203,31 @@ wmap_inspect_i(VALUE key, VALUE val, st_data_t data)
wmap_inspect_append(str, key);
rb_str_cat2(str, " => ");
wmap_inspect_append(str, val);
+
+ return ST_CONTINUE;
}
+/* call-seq:
+ * inspect -> new_string
+ *
+ * Returns a new string containing the \WeakMap entries:
+ *
+ * m = ObjectSpace::WeakMap.new
+ * m["one"] = 1
+ * m["two"] = 2
+ * m.inspect
+ * # => "#<ObjectSpace::WeakMap:0x00007c457b2523e8: #<String:0x00007c457b2674f0> => 1, #<String:0x00007c457b27b8d8> => 2>"
+ */
static VALUE
wmap_inspect(VALUE self)
{
VALUE c = rb_class_name(CLASS_OF(self));
struct weakmap *w;
- TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
+ TypedData_Get_Struct(self, struct weakmap, &rb_weakmap_type, w);
VALUE str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void *)self);
- wmap_foreach(w, wmap_inspect_i, (st_data_t)str);
+ st_foreach(w->table, wmap_inspect_i, (st_data_t)str);
RSTRING_PTR(str)[0] = '#';
rb_str_cat2(str, ">");
@@ -270,10 +235,12 @@ wmap_inspect(VALUE self)
return str;
}
-static void
-wmap_each_i(VALUE key, VALUE val, st_data_t _)
+static int
+wmap_each_i(st_data_t k, st_data_t v, st_data_t _)
{
- rb_yield_values(2, key, val);
+ rb_yield_values(2, (VALUE)k, (VALUE)v);
+
+ return ST_CONTINUE;
}
/*
@@ -288,17 +255,19 @@ static VALUE
wmap_each(VALUE self)
{
struct weakmap *w;
- TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
+ TypedData_Get_Struct(self, struct weakmap, &rb_weakmap_type, w);
- wmap_foreach(w, wmap_each_i, (st_data_t)0);
+ st_foreach(w->table, wmap_each_i, (st_data_t)0);
return self;
}
-static void
-wmap_each_key_i(VALUE key, VALUE _val, st_data_t _data)
+static int
+wmap_each_key_i(st_data_t k, st_data_t _v, st_data_t _data)
{
- rb_yield(key);
+ rb_yield((VALUE)k);
+
+ return ST_CONTINUE;
}
/*
@@ -313,17 +282,19 @@ static VALUE
wmap_each_key(VALUE self)
{
struct weakmap *w;
- TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
+ TypedData_Get_Struct(self, struct weakmap, &rb_weakmap_type, w);
- wmap_foreach(w, wmap_each_key_i, (st_data_t)0);
+ st_foreach(w->table, wmap_each_key_i, (st_data_t)0);
return self;
}
-static void
-wmap_each_value_i(VALUE _key, VALUE val, st_data_t _data)
+static int
+wmap_each_value_i(st_data_t k, st_data_t v, st_data_t _data)
{
- rb_yield(val);
+ rb_yield((VALUE)v);
+
+ return ST_CONTINUE;
}
/*
@@ -338,19 +309,21 @@ static VALUE
wmap_each_value(VALUE self)
{
struct weakmap *w;
- TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
+ TypedData_Get_Struct(self, struct weakmap, &rb_weakmap_type, w);
- wmap_foreach(w, wmap_each_value_i, (st_data_t)0);
+ st_foreach(w->table, wmap_each_value_i, (st_data_t)0);
return self;
}
-static void
-wmap_keys_i(st_data_t key, st_data_t _, st_data_t arg)
+static int
+wmap_keys_i(st_data_t k, st_data_t v, st_data_t data)
{
- VALUE ary = (VALUE)arg;
+ VALUE ary = (VALUE)data;
+
+ rb_ary_push(ary, (VALUE)k);
- rb_ary_push(ary, key);
+ return ST_CONTINUE;
}
/*
@@ -364,20 +337,22 @@ static VALUE
wmap_keys(VALUE self)
{
struct weakmap *w;
- TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
+ TypedData_Get_Struct(self, struct weakmap, &rb_weakmap_type, w);
VALUE ary = rb_ary_new();
- wmap_foreach(w, wmap_keys_i, (st_data_t)ary);
+ st_foreach(w->table, wmap_keys_i, (st_data_t)ary);
return ary;
}
-static void
-wmap_values_i(st_data_t key, st_data_t val, st_data_t arg)
+static int
+wmap_values_i(st_data_t k, st_data_t v, st_data_t data)
{
- VALUE ary = (VALUE)arg;
+ VALUE ary = (VALUE)data;
- rb_ary_push(ary, (VALUE)val);
+ rb_ary_push(ary, (VALUE)v);
+
+ return ST_CONTINUE;
}
/*
@@ -391,48 +366,14 @@ static VALUE
wmap_values(VALUE self)
{
struct weakmap *w;
- TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
+ TypedData_Get_Struct(self, struct weakmap, &rb_weakmap_type, w);
VALUE ary = rb_ary_new();
- wmap_foreach(w, wmap_values_i, (st_data_t)ary);
+ st_foreach(w->table, wmap_values_i, (st_data_t)ary);
return ary;
}
-static VALUE
-nonspecial_obj_id(VALUE obj)
-{
-#if SIZEOF_LONG == SIZEOF_VOIDP
- return (VALUE)((SIGNED_VALUE)(obj)|FIXNUM_FLAG);
-#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
- return LL2NUM((SIGNED_VALUE)(obj) / 2);
-#else
-# error not supported
-#endif
-}
-
-static int
-wmap_aset_replace(st_data_t *key, st_data_t *val, st_data_t new_key_ptr, int existing)
-{
- VALUE new_key = *(VALUE *)new_key_ptr;
- VALUE new_val = *(((VALUE *)new_key_ptr) + 1);
-
- if (existing) {
- assert(*(VALUE *)*key == new_key);
- }
- else {
- VALUE *pair = xmalloc(sizeof(VALUE) * 2);
-
- *key = (st_data_t)pair;
- *val = (st_data_t)(pair + 1);
- }
-
- *(VALUE *)*key = new_key;
- *(VALUE *)*val = new_val;
-
- return ST_CONTINUE;
-}
-
/*
* call-seq:
* map[key] = value -> value
@@ -446,33 +387,27 @@ static VALUE
wmap_aset(VALUE self, VALUE key, VALUE val)
{
struct weakmap *w;
- TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
-
- VALUE pair[2] = { key, val };
+ TypedData_Get_Struct(self, struct weakmap, &rb_weakmap_type, w);
- st_update(w->table, (st_data_t)pair, wmap_aset_replace, (st_data_t)pair);
+ st_insert(w->table, (st_data_t)key, (st_data_t)val);
RB_OBJ_WRITTEN(self, Qundef, key);
RB_OBJ_WRITTEN(self, Qundef, val);
- return nonspecial_obj_id(val);
+ return Qnil;
}
/* Retrieves a weakly referenced object with the given key */
static VALUE
wmap_lookup(VALUE self, VALUE key)
{
- assert(wmap_live_p(key));
-
struct weakmap *w;
- TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
+ TypedData_Get_Struct(self, struct weakmap, &rb_weakmap_type, w);
st_data_t data;
- if (!st_lookup(w->table, (st_data_t)&key, &data)) return Qundef;
-
- if (!wmap_live_p(*(VALUE *)data)) return Qundef;
+ if (!st_lookup(w->table, (st_data_t)key, &data)) return Qundef;
- return *(VALUE *)data;
+ return (VALUE)data;
}
/*
@@ -522,22 +457,12 @@ static VALUE
wmap_delete(VALUE self, VALUE key)
{
struct weakmap *w;
- TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
+ TypedData_Get_Struct(self, struct weakmap, &rb_weakmap_type, w);
- VALUE orig_key = key;
- st_data_t orig_key_data = (st_data_t)&orig_key;
- st_data_t orig_val_data;
- if (st_delete(w->table, &orig_key_data, &orig_val_data)) {
- VALUE orig_val = *(VALUE *)orig_val_data;
-
- rb_gc_remove_weak(self, (VALUE *)orig_key_data);
- rb_gc_remove_weak(self, (VALUE *)orig_val_data);
-
- wmap_free_entry((VALUE *)orig_key_data, (VALUE *)orig_val_data);
-
- if (wmap_live_p(orig_val)) {
- return orig_val;
- }
+ st_data_t orig_key = (st_data_t)key;
+ st_data_t orig_val;
+ if (st_delete(w->table, &orig_key, &orig_val)) {
+ return (VALUE)orig_val;
}
if (rb_block_given_p()) {
@@ -570,7 +495,7 @@ static VALUE
wmap_size(VALUE self)
{
struct weakmap *w;
- TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
+ TypedData_Get_Struct(self, struct weakmap, &rb_weakmap_type, w);
st_index_t n = st_table_size(w->table);
@@ -587,7 +512,7 @@ wmap_size(VALUE self)
* the key and the object as the value. This means that the key is of the type
* `VALUE *` while the value is of the type `VALUE`.
*
- * The object is not not directly stored as keys in the table because
+ * The object is not directly stored as keys in the table because
* `rb_gc_mark_weak` requires a pointer to the memory location to overwrite
* when the object is reclaimed. Using a pointer into the ST table entry is not
* safe because the pointer can change when the ST table is resized.
@@ -604,21 +529,11 @@ struct weakkeymap {
};
static int
-wkmap_mark_table_i(st_data_t key, st_data_t val_obj, st_data_t _)
+wkmap_mark_table_i(st_data_t key, st_data_t val_obj, st_data_t _data)
{
- VALUE key_obj = *(VALUE *)key;
-
- if (wmap_live_p(key_obj)) {
- rb_gc_mark_weak((VALUE *)key);
- rb_gc_mark_movable((VALUE)val_obj);
-
- return ST_CONTINUE;
- }
- else {
- ruby_sized_xfree((VALUE *)key, sizeof(VALUE));
+ rb_gc_mark_movable((VALUE)val_obj);
- return ST_DELETE;
- }
+ return ST_CONTINUE;
}
static void
@@ -630,19 +545,11 @@ wkmap_mark(void *ptr)
}
}
-static int
-wkmap_free_table_i(st_data_t key, st_data_t _val, st_data_t _arg)
-{
- ruby_sized_xfree((VALUE *)key, sizeof(VALUE));
- return ST_CONTINUE;
-}
-
static void
wkmap_free(void *ptr)
{
struct weakkeymap *w = ptr;
- st_foreach(w->table, wkmap_free_table_i, 0);
st_free_table(w->table);
}
@@ -652,27 +559,20 @@ wkmap_memsize(const void *ptr)
const struct weakkeymap *w = ptr;
size_t size = 0;
- size += st_memsize(w->table);
- /* Each key of the table takes sizeof(VALUE) in size. */
- size += st_table_size(w->table) * sizeof(VALUE);
+ if (w->table) {
+ size += st_memsize(w->table);
+ /* Each key of the table takes sizeof(VALUE) in size. */
+ size += st_table_size(w->table) * sizeof(VALUE);
+ }
return size;
}
static int
-wkmap_compact_table_i(st_data_t key, st_data_t val_obj, st_data_t _data, int _error)
+wkmap_compact_table_i(st_data_t key, st_data_t val, st_data_t _data, int _error)
{
- VALUE key_obj = *(VALUE *)key;
-
- if (wmap_live_p(key_obj)) {
- if (key_obj != rb_gc_location(key_obj) || val_obj != rb_gc_location(val_obj)) {
- return ST_REPLACE;
- }
- }
- else {
- ruby_sized_xfree((VALUE *)key, sizeof(VALUE));
-
- return ST_DELETE;
+ if ((VALUE)key != rb_gc_location((VALUE)key) || (VALUE)val != rb_gc_location((VALUE)val)) {
+ return ST_REPLACE;
}
return ST_CONTINUE;
@@ -681,9 +581,9 @@ wkmap_compact_table_i(st_data_t key, st_data_t val_obj, st_data_t _data, int _er
static int
wkmap_compact_table_replace(st_data_t *key_ptr, st_data_t *val_ptr, st_data_t _data, int existing)
{
- assert(existing);
+ RUBY_ASSERT(existing);
- *(VALUE *)*key_ptr = rb_gc_location(*(VALUE *)*key_ptr);
+ *key_ptr = (st_data_t)rb_gc_location((VALUE)*key_ptr);
*val_ptr = (st_data_t)rb_gc_location((VALUE)*val_ptr);
return ST_CONTINUE;
@@ -699,13 +599,33 @@ wkmap_compact(void *ptr)
}
}
-static const rb_data_type_t weakkeymap_type = {
+static int
+rb_wkmap_handle_weak_references_i(st_data_t key, st_data_t val, st_data_t arg)
+{
+ if (rb_gc_handle_weak_references_alive_p(key)) {
+ return ST_CONTINUE;
+ }
+ else {
+ return ST_DELETE;
+ }
+}
+
+static void
+wkmap_handle_weak_references(void *ptr)
+{
+ struct weakkeymap *w = ptr;
+
+ st_foreach(w->table, rb_wkmap_handle_weak_references_i, (st_data_t)0);
+}
+
+static const rb_data_type_t rb_weakkeymap_type = {
"weakkeymap",
{
wkmap_mark,
wkmap_free,
wkmap_memsize,
wkmap_compact,
+ wkmap_handle_weak_references,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
@@ -713,23 +633,16 @@ static const rb_data_type_t weakkeymap_type = {
static int
wkmap_cmp(st_data_t x, st_data_t y)
{
- VALUE x_obj = *(VALUE *)x;
- VALUE y_obj = *(VALUE *)y;
+ VALUE x_obj = (VALUE)x;
+ VALUE y_obj = (VALUE)y;
- if (wmap_live_p(x_obj) && wmap_live_p(y_obj)) {
- return rb_any_cmp(x_obj, y_obj);
- }
- else {
- /* If one of the objects is dead, then they cannot be the same. */
- return 1;
- }
+ return rb_any_cmp(x_obj, y_obj);
}
static st_index_t
wkmap_hash(st_data_t n)
{
- VALUE obj = *(VALUE *)n;
- assert(wmap_live_p(obj));
+ VALUE obj = (VALUE)n;
return rb_any_hash(obj);
}
@@ -743,8 +656,13 @@ static VALUE
wkmap_allocate(VALUE klass)
{
struct weakkeymap *w;
- VALUE obj = TypedData_Make_Struct(klass, struct weakkeymap, &weakkeymap_type, w);
+
+ VALUE obj = TypedData_Make_Struct(klass, struct weakkeymap, &rb_weakkeymap_type, w);
+
w->table = st_init_table(&wkmap_hash_type);
+
+ rb_gc_declare_weak_references(obj);
+
return obj;
}
@@ -752,10 +670,10 @@ static VALUE
wkmap_lookup(VALUE self, VALUE key)
{
struct weakkeymap *w;
- TypedData_Get_Struct(self, struct weakkeymap, &weakkeymap_type, w);
+ TypedData_Get_Struct(self, struct weakkeymap, &rb_weakkeymap_type, w);
st_data_t data;
- if (!st_lookup(w->table, (st_data_t)&key, &data)) return Qundef;
+ if (!st_lookup(w->table, (st_data_t)key, &data)) return Qundef;
return (VALUE)data;
}
@@ -772,7 +690,7 @@ static VALUE
wkmap_aref(VALUE self, VALUE key)
{
VALUE obj = wkmap_lookup(self, key);
- return obj != Qundef ? obj : Qnil;
+ return !UNDEF_P(obj) ? obj : Qnil;
}
struct wkmap_aset_args {
@@ -780,21 +698,6 @@ struct wkmap_aset_args {
VALUE new_val;
};
-static int
-wkmap_aset_replace(st_data_t *key, st_data_t *val, st_data_t data_args, int existing)
-{
- struct wkmap_aset_args *args = (struct wkmap_aset_args *)data_args;
-
- if (!existing) {
- *key = (st_data_t)xmalloc(sizeof(VALUE));
- }
-
- *(VALUE *)*key = args->new_key;
- *val = (st_data_t)args->new_val;
-
- return ST_CONTINUE;
-}
-
/*
* call-seq:
* map[key] = value -> value
@@ -811,19 +714,14 @@ static VALUE
wkmap_aset(VALUE self, VALUE key, VALUE val)
{
struct weakkeymap *w;
- TypedData_Get_Struct(self, struct weakkeymap, &weakkeymap_type, w);
+ TypedData_Get_Struct(self, struct weakkeymap, &rb_weakkeymap_type, w);
if (!FL_ABLE(key) || SYMBOL_P(key) || RB_BIGNUM_TYPE_P(key) || RB_TYPE_P(key, T_FLOAT)) {
- rb_raise(rb_eArgError, "WeakKeyMap must be garbage collectable");
+ rb_raise(rb_eArgError, "WeakKeyMap keys must be garbage collectable");
UNREACHABLE_RETURN(Qnil);
}
- struct wkmap_aset_args args = {
- .new_key = key,
- .new_val = val,
- };
-
- st_update(w->table, (st_data_t)&key, wkmap_aset_replace, (st_data_t)&args);
+ st_insert(w->table, (st_data_t)key, (st_data_t)val);
RB_OBJ_WRITTEN(self, Qundef, key);
RB_OBJ_WRITTEN(self, Qundef, val);
@@ -864,19 +762,12 @@ static VALUE
wkmap_delete(VALUE self, VALUE key)
{
struct weakkeymap *w;
- TypedData_Get_Struct(self, struct weakkeymap, &weakkeymap_type, w);
-
- VALUE orig_key = key;
- st_data_t orig_key_data = (st_data_t)&orig_key;
- st_data_t orig_val_data;
- if (st_delete(w->table, &orig_key_data, &orig_val_data)) {
- VALUE orig_val = (VALUE)orig_val_data;
-
- rb_gc_remove_weak(self, (VALUE *)orig_key_data);
-
- ruby_sized_xfree((VALUE *)orig_key_data, sizeof(VALUE));
+ TypedData_Get_Struct(self, struct weakkeymap, &rb_weakkeymap_type, w);
- return orig_val;
+ st_data_t orig_key = (st_data_t)key;
+ st_data_t orig_val;
+ if (st_delete(w->table, &orig_key, &orig_val)) {
+ return (VALUE)orig_val;
}
if (rb_block_given_p()) {
@@ -910,12 +801,12 @@ static VALUE
wkmap_getkey(VALUE self, VALUE key)
{
struct weakkeymap *w;
- TypedData_Get_Struct(self, struct weakkeymap, &weakkeymap_type, w);
+ TypedData_Get_Struct(self, struct weakkeymap, &rb_weakkeymap_type, w);
st_data_t orig_key;
- if (!st_get_key(w->table, (st_data_t)&key, &orig_key)) return Qnil;
+ if (!st_get_key(w->table, (st_data_t)key, &orig_key)) return Qnil;
- return *(VALUE *)orig_key;
+ return (VALUE)orig_key;
}
/*
@@ -927,7 +818,7 @@ wkmap_getkey(VALUE self, VALUE key)
static VALUE
wkmap_has_key(VALUE self, VALUE key)
{
- return RBOOL(wkmap_lookup(self, key) != Qundef);
+ return RBOOL(!UNDEF_P(wkmap_lookup(self, key)));
}
/*
@@ -940,9 +831,8 @@ static VALUE
wkmap_clear(VALUE self)
{
struct weakkeymap *w;
- TypedData_Get_Struct(self, struct weakkeymap, &weakkeymap_type, w);
+ TypedData_Get_Struct(self, struct weakkeymap, &rb_weakkeymap_type, w);
- st_foreach(w->table, wkmap_free_table_i, 0);
st_clear(w->table);
return self;
@@ -963,7 +853,7 @@ static VALUE
wkmap_inspect(VALUE self)
{
struct weakkeymap *w;
- TypedData_Get_Struct(self, struct weakkeymap, &weakkeymap_type, w);
+ TypedData_Get_Struct(self, struct weakkeymap, &rb_weakkeymap_type, w);
st_index_t n = st_table_size(w->table);
@@ -986,12 +876,12 @@ wkmap_inspect(VALUE self)
*
* Keys in the map are compared by identity.
*
- * m = ObjectSpace::WeekMap.new
+ * m = ObjectSpace::WeakMap.new
* key1 = "foo"
* val1 = Object.new
* m[key1] = val1
*
- * key2 = "foo"
+ * key2 = "bar"
* val2 = Object.new
* m[key2] = val2
*
@@ -1042,13 +932,13 @@ wkmap_inspect(VALUE self)
*
* val = nil
* GC.start
- * # There is no more references to `val`, yet the pair isn't
+ * # There are no more references to `val`, yet the pair isn't
* # garbage-collected.
* map["name"] #=> 2023-12-07 00:00:00 +0200
*
* key = nil
* GC.start
- * # There is no more references to `key`, key and value are
+ * # There are no more references to `key`, key and value are
* # garbage-collected.
* map["name"] #=> nil
*
@@ -1074,7 +964,7 @@ wkmap_inspect(VALUE self)
* end
*
* This will result in +make_value+ returning the same object for same set of attributes
- * always, but the values that aren't needed anymore woudn't be sitting in the cache forever.
+ * always, but the values that aren't needed anymore wouldn't be sitting in the cache forever.
*/
void