diff options
Diffstat (limited to 'weakmap.c')
| -rw-r--r-- | weakmap.c | 520 |
1 files changed, 205 insertions, 315 deletions
@@ -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 |
