# 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::WeekMap.new
    key1 = "foo"
    val1 = Object.new
    m[key1] = val1

    key2 = "foo"
    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

map[key] → value click to toggle source

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;
    }

map[key] = value → value click to toggle source

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);
    }

delete(key) → value or nil click to toggle source
delete(key) {|key| ... } → object

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);

            wmap_free_entry((VALUE *)orig_key_data, (VALUE *)orig_val_data);

            if (wmap_live_p(orig_val)) {
                return orig_val;
            }
        }

        if (rb_block_given_p()) {
            return rb_yield(key);
        }
        else {
            return Qnil;
        }
    }

each {|key, val| ... } → self click to toggle source

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;
    }

Also aliased as: each_pair
each_key {|key| ... } → self click to toggle source

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;
    }

each_pair
Alias for: each
each_value {|val| ... } → self click to toggle source

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;
    }

include?
Also aliased as: member?, key?
inspect() click to toggle source

    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;
    }

key?(key) → true or false

Returns `true` if `key` is a key in `self`, otherwise `false`.

Alias for: include?
keys → new_array click to toggle source

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;
    }

length
Alias for: size
member?
Alias for: include?
size → number click to toggle source

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
    }

Also aliased as: length
values → new_array click to toggle source

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;
    }