123456789_123456789_123456789_123456789_123456789_

Class: ObjectSpace::WeakMap

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Instance Chain:
self, ::Enumerable
Inherits: Object
Defined in: weakmap.c,
weakmap.c

Overview

An 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 WeakKeyMap map class, which compares keys by value, and holds weak references only to the keys.

Instance Method Summary

::Enumerable - Included

#all?

Returns whether every element meets a given criterion.

#any?

Returns whether any element meets a given criterion.

#chain

Returns an enumerator object generated from this enumerator and given enumerables.

#chunk

Each element in the returned enumerator is a 2-element array consisting of:

#chunk_while

Creates an enumerator for each chunked elements.

#collect

Alias for Enumerable#map.

#collect_concat
#compact

Returns an array of all non-nil elements:

#count

Returns the count of elements, based on an argument or block criterion, if given.

#cycle

When called with positive integer argument n and a block, calls the block with each element, then does so again, until it has done so n times; returns nil:

#detect

Alias for Enumerable#find.

#drop

For positive integer n, returns an array containing all but the first n elements:

#drop_while

Calls the block with successive elements as long as the block returns a truthy value; returns an array of all elements after that point:

#each_cons

Calls the block with each successive overlapped n-tuple of elements; returns self:

#each_entry

Calls the given block with each element, converting multiple values from yield to an array; returns self:

#each_slice

Calls the block with each successive disjoint n-tuple of elements; returns self:

#each_with_index

Invoke self.each with *args.

#each_with_object

Calls the block once for each element, passing both the element and the given object:

#entries

Alias for Enumerable#to_a.

#filter

Returns an array containing elements selected by the block.

#filter_map

Returns an array containing truthy elements returned by the block.

#find

Returns the first element for which the block returns a truthy value.

#find_all
#find_index

Returns the index of the first element that meets a specified criterion, or nil if no such element is found.

#first

Returns the first element or elements.

#flat_map

Returns an array of flattened objects returned by the block.

#grep

Returns an array of objects based elements of self that match the given pattern.

#grep_v

Returns an array of objects based on elements of self that don’t match the given pattern.

#group_by

With a block given returns a hash:

#include?
#inject

Returns the result of applying a reducer to an initial value and the first element of the ::Enumerable.

#lazy

Returns an ::Enumerator::Lazy, which redefines most ::Enumerable methods to postpone enumeration and enumerate values only on an as-needed basis.

#map

Returns an array of objects returned by the block.

#max

Returns the element with the maximum element according to a given criterion.

#max_by

Returns the elements for which the block returns the maximum values.

#member?

Returns whether for any element object == element:

#min

Returns the element with the minimum element according to a given criterion.

#min_by

Returns the elements for which the block returns the minimum values.

#minmax

Returns a 2-element array containing the minimum and maximum elements according to a given criterion.

#minmax_by

Returns a 2-element array containing the elements for which the block returns minimum and maximum values:

#none?

Returns whether no element meets a given criterion.

#one?

Returns whether exactly one element meets a given criterion.

#partition

With a block given, returns an array of two arrays:

#reduce
#reject

Returns an array of objects rejected by the block.

#reverse_each

With a block given, calls the block with each element, but in reverse order; returns self:

#select
#slice_after

Creates an enumerator for each chunked elements.

#slice_before

With argument pattern, returns an enumerator that uses the pattern to partition elements into arrays (“slices”).

#slice_when

Creates an enumerator for each chunked elements.

#sort

Returns an array containing the sorted elements of self.

#sort_by

With a block given, returns an array of elements of self, sorted according to the value returned by the block for each element.

#sum

With no block given, returns the sum of initial_value and the elements:

#take

For non-negative integer n, returns the first n elements:

#take_while

Calls the block with successive elements as long as the block returns a truthy value; returns an array of all elements up to that point:

#tally

When argument hash is not given, returns a new hash whose keys are the distinct elements in self; each integer value is the count of occurrences of each element:

#to_a

Returns an array containing the items in self:

#to_h

When self consists of 2-element arrays, returns a hash each of whose entries is the key-value pair formed from one of those arrays:

#to_set

Makes a set from the enumerable object with given arguments.

#uniq

With no block, returns a new array containing only unique elements; the array has no two elements e0 and e1 such that e0.eql?(e1):

#zip

With no block given, returns a new array new_array of size self.size whose elements are arrays.

Instance Method Details

#[](key) ⇒ value

Returns the value associated with the given key if found.

If key is not found, returns nil.

[ GitHub ]

  
# File 'weakmap.c', line 526

static VALUE
wmap_aref(VALUE self, VALUE key)
{
    VALUE obj = wmap_lookup(self, key);
    return !UNDEF_P(obj) ? obj : Qnil;
}

#[]=(key, value) ⇒ value

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.

[ GitHub ]

  
# File 'weakmap.c', line 485

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? #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"
[ GitHub ]

  
# File 'weakmap.c', line 561

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

#each {|key, val| ... } ⇒ self Also known as: #each_pair

Iterates over keys and values. Note that unlike other collections, each without block isn’t supported.

[ GitHub ]

  
# File 'weakmap.c', line 319

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

#each_key {|key| ... } ⇒ self

Iterates over keys. Note that unlike other collections, each_key without block isn’t supported.

[ GitHub ]

  
# File 'weakmap.c', line 346

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 {|key, val| ... } ⇒ self #each_pair {|key, val| ... } ⇒ self

Alias for #each.

#each_value {|val| ... } ⇒ self

Iterates over values. Note that unlike other collections, each_value without block isn’t supported.

[ GitHub ]

  
# File 'weakmap.c', line 373

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

#key?(key) ⇒ Boolean #include?(key) ⇒ Boolean

Alias for #key?.

#inspect

[ GitHub ]

  
# File 'weakmap.c', line 286

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) ⇒ Boolean Also known as: #include?, #member?

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

[ GitHub ]

  
# File 'weakmap.c', line 598

static VALUE
wmap_has_key(VALUE self, VALUE key)
{
    return RBOOL(!UNDEF_P(wmap_lookup(self, key)));
}

#keysArray

Returns a new ::Array containing all keys in the map.

[ GitHub ]

  
# File 'weakmap.c', line 401

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

#lengthNumeric Also known as: #size

Returns the number of referenced objects

[ GitHub ]

  
# File 'weakmap.c', line 610

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
}

#key?(key) ⇒ Boolean #member?(key) ⇒ Boolean

Alias for #key?.

#lengthNumeric #sizeNumeric

Alias for #length.

#valuesArray

Returns a new ::Array containing all values in the map.

[ GitHub ]

  
# File 'weakmap.c', line 430

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