class ObjectSpace::WeakMap
An ObjectSpace::WeakMap
is a key-value map that holds weak references to its keys and values, so they can be garbage-collected when there are no more references left.
Keys in the map are compared by identity.
m = ObjectSpace::WeakMap.new key1 = "foo" val1 = Object.new m[key1] = val1 key2 = "bar" val2 = Object.new m[key2] = val2 m[key1] #=> #<Object:0x0...> m[key2] #=> #<Object:0x0...> val1 = nil # remove the other reference to value GC.start m[key1] #=> nil m.keys #=> ["bar"] key2 = nil # remove the other reference to key GC.start m[key2] #=> nil m.keys #=> []
(Note that GC.start
is used here only for demonstrational purposes and might not always lead to demonstrated results.)
See also ObjectSpace::WeakKeyMap
map class, which compares keys by value, and holds weak references only to the keys.
Public Instance Methods
Returns the value associated with the given key
if found.
If key
is not found, returns nil
.
static VALUE wmap_aref(VALUE self, VALUE key) { VALUE obj = wmap_lookup(self, key); return !UNDEF_P(obj) ? obj : Qnil; }
Associates the given value
with the given key
.
If the given key
exists, replaces its value with the given value
; the ordering is not affected.
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 }; st_update(w->table, (st_data_t)pair, wmap_aset_replace, (st_data_t)pair); RB_OBJ_WRITTEN(self, Qundef, key); RB_OBJ_WRITTEN(self, Qundef, val); return nonspecial_obj_id(val); }
Deletes the entry for the given key
and returns its associated value.
If no block is given and key
is found, deletes the entry and returns the associated value:
m = ObjectSpace::WeakMap.new key = "foo" m[key] = 1 m.delete(key) # => 1 m[key] # => nil
If no block is given and key
is not found, returns nil
.
If a block is given and key
is found, ignores the block, deletes the entry, and returns the associated value:
m = ObjectSpace::WeakMap.new key = "foo" m[key] = 2 m.delete(key) { |key| raise 'Will never happen'} # => 2
If a block is given and key
is not found, yields the key
to the block and returns the block’s return value:
m = ObjectSpace::WeakMap.new m.delete("nosuch") { |key| "Key #{key} not found" } # => "Key nosuch not found"
static VALUE wmap_delete(VALUE self, VALUE key) { struct weakmap *w; TypedData_Get_Struct(self, struct weakmap, &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); struct weakmap_entry *entry = (struct weakmap_entry *)orig_key_data; ruby_sized_xfree(entry, sizeof(struct weakmap_entry)); if (wmap_live_p(orig_val)) { return orig_val; } } if (rb_block_given_p()) { return rb_yield(key); } else { return Qnil; } }
Iterates over keys and values. Note that unlike other collections, each
without block isn’t supported.
static VALUE wmap_each(VALUE self) { struct weakmap *w; TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w); wmap_foreach(w, wmap_each_i, (st_data_t)0); return self; }
Iterates over keys. Note that unlike other collections, each_key
without block isn’t supported.
static VALUE wmap_each_key(VALUE self) { struct weakmap *w; TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w); wmap_foreach(w, wmap_each_key_i, (st_data_t)0); return self; }
Iterates over values. Note that unlike other collections, each_value
without block isn’t supported.
static VALUE wmap_each_value(VALUE self) { struct weakmap *w; TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w); wmap_foreach(w, wmap_each_value_i, (st_data_t)0); return self; }
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); VALUE str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void *)self); wmap_foreach(w, wmap_inspect_i, (st_data_t)str); RSTRING_PTR(str)[0] = '#'; rb_str_cat2(str, ">"); return str; }
Returns true
if key
is a key in self
, otherwise false
.
Returns a new Array
containing all keys in the map.
static VALUE wmap_keys(VALUE self) { struct weakmap *w; TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w); VALUE ary = rb_ary_new(); wmap_foreach(w, wmap_keys_i, (st_data_t)ary); return ary; }
Returns the number of referenced objects
static VALUE wmap_size(VALUE self) { struct weakmap *w; TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w); st_index_t n = st_table_size(w->table); #if SIZEOF_ST_INDEX_T <= SIZEOF_LONG return ULONG2NUM(n); #else return ULL2NUM(n); #endif }
Returns a new Array
containing all values in the map.
static VALUE wmap_values(VALUE self) { struct weakmap *w; TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w); VALUE ary = rb_ary_new(); wmap_foreach(w, wmap_values_i, (st_data_t)ary); return ary; }