class ObjectSpace::WeakKeyMap

An ObjectSpace::WeakKeyMap object holds references to any objects, but objects uses as keys can be garbage collected.

Objects used as values can’t be garbage collected until the key is.

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
wkmap_aref(VALUE self, VALUE key)
{
    VALUE obj = wkmap_lookup(self, key);
    return obj != Qundef ? obj : Qnil;
}
map[key] = value → value click to toggle source

Associates the given value with the given key; returns value.

The reference to key is weak, so when there is no other reference to key it may be garbage collected.

If the given key exists, replaces its value with the given value; the ordering is not affected

static VALUE
wkmap_aset(VALUE self, VALUE key, VALUE value)
{
    struct weakkeymap *w;
    TypedData_Get_Struct(self, struct weakkeymap, &weakkeymap_type, w);

    if (!(FL_ABLE(key) && !SYMBOL_P(key) && !RB_BIGNUM_TYPE_P(key))) {
        rb_raise(rb_eArgError, "WeakKeyMap must be garbage collectable");
    }

    st_index_t hash = wkmap_lookup_hash(w, key);
    weakkeymap_entry_t *key_entry = wkmap_lookup_entry(w, key, hash);

    if (!key_entry) {
        key_entry = ALLOC(weakkeymap_entry_t);
        key_entry->obj = key;
        key_entry->hash = hash;
    }

    if (!st_insert(w->map, (st_data_t)key_entry, (st_data_t)value)) {
        st_insert(w->obj2hash, (st_data_t)key, (st_data_t)hash);
        rb_define_finalizer_no_check(key, w->final);
    }

    RB_OBJ_WRITTEN(self, Qundef, value);

    return value;
}
clear → self click to toggle source

Removes all map entries; returns self.

static VALUE
wkmap_clear(VALUE self)
{
    struct weakkeymap *w;
    TypedData_Get_Struct(self, struct weakkeymap, &weakkeymap_type, w);
    if (w->map) {
        st_clear(w->map);
    }
    if (w->obj2hash) {
        st_clear(w->obj2hash);
    }
    return self;
}
getkey(key) → existing_key or nil click to toggle source

Returns the existing equal key if it exists, otherwise returns nil.

static VALUE
wkmap_getkey(VALUE self, VALUE key)
{
    struct weakkeymap *w;
    TypedData_Get_Struct(self, struct weakkeymap, &weakkeymap_type, w);

    st_index_t hash = rb_any_hash(key);
    weakkeymap_entry_t lookup_entry = {key, hash};

    weakkeymap_entry_t *key_entry = NULL;
    if (st_get_key(w->map, (st_data_t)&lookup_entry, (st_data_t *)&key_entry)) {
        assert(key_entry != NULL);

        VALUE obj = key_entry->obj;
        if (wmap_live_p(obj)) {
            return obj;
        }
    }
    return Qnil;
}
inspect → new_string click to toggle source

Returns a new String containing informations about the map:

m = ObjectSpace::WeakKeyMap.new
m[key] = value
m.inspect # => "#<ObjectSpace::WeakKeyMap:0x00000001028dcba8 size=1>"
static VALUE
wkmap_inspect(VALUE self)
{
    struct weakkeymap *w;
    TypedData_Get_Struct(self, struct weakkeymap, &weakkeymap_type, w);

    st_index_t n = 0;
    if (w->map) {
        n = w->map->num_entries;
    }

#if SIZEOF_ST_INDEX_T <= SIZEOF_LONG
    const char * format = "#<%"PRIsVALUE":%p size=%lu>";
#else
    const char * format = "#<%"PRIsVALUE":%p size=%llu>";
#endif

    VALUE str = rb_sprintf(format, rb_class_name(CLASS_OF(self)), (void *)self, n);
    return str;
}
key?(key) → true or false click to toggle source

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

static VALUE
wkmap_has_key(VALUE self, VALUE key)
{
    return RBOOL(wkmap_lookup(self, key) != Qundef);
}