Class: ObjectSpace::WeakMap
- Includes:
- Enumerable
- Defined in:
- weakmap.c,
weakmap.c
Overview
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.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Returns the value associated with the given
key
if found. -
#[]=(key) ⇒ Object
Associates the given
value
with the givenkey
. -
#delete(key) ⇒ Object
Deletes the entry for the given
key
and returns its associated value. -
#each {|key, val| ... } ⇒ self
Iterates over keys and values.
-
#each_key {|key| ... } ⇒ self
Iterates over keys.
-
#each {|key, val| ... } ⇒ self
Iterates over keys and values.
-
#each_value {|val| ... } ⇒ self
Iterates over values.
-
#key?(key) ⇒ Boolean
Returns
true
ifkey
is a key inself
, otherwisefalse
. - #inspect ⇒ Object
-
#key?(key) ⇒ Boolean
Returns
true
ifkey
is a key inself
, otherwisefalse
. -
#keys ⇒ Object
Returns a new Array containing all keys in the map.
-
#size ⇒ Numeric
Returns the number of referenced objects.
-
#key?(key) ⇒ Boolean
Returns
true
ifkey
is a key inself
, otherwisefalse
. -
#size ⇒ Numeric
Returns the number of referenced objects.
-
#values ⇒ Object
Returns a new Array containing all values in the map.
Methods included from Enumerable
#all?, #any?, #chain, #chunk, #chunk_while, #collect, #collect_concat, #compact, #count, #cycle, #detect, #drop, #drop_while, #each_cons, #each_entry, #each_slice, #each_with_index, #each_with_object, #entries, #filter, #filter_map, #find, #find_all, #find_index, #first, #flat_map, #grep, #grep_v, #group_by, #inject, #lazy, #map, #max, #max_by, #min, #min_by, #minmax, #minmax_by, #none?, #one?, #partition, #reduce, #reject, #reverse_each, #select, #slice_after, #slice_before, #slice_when, #sort, #sort_by, #sum, #take, #take_while, #tally, #to_a, #to_h, #uniq, #zip
Instance Method Details
#[](key) ⇒ Object
Returns the value associated with the given key
if found.
If key
is not found, returns nil
.
494 495 496 497 498 499 |
# File 'weakmap.c', line 494
static VALUE
wmap_aref(VALUE self, VALUE key)
{
VALUE obj = wmap_lookup(self, key);
return !UNDEF_P(obj) ? obj : Qnil;
}
|
#[]=(key) ⇒ Object
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.
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 |
# File 'weakmap.c', line 453
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) ⇒ nil #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"
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
# File 'weakmap.c', line 529
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
Iterates over keys and values. Note that unlike other collections, each
without block isn’t supported.
287 288 289 290 291 292 293 294 295 296 |
# File 'weakmap.c', line 287
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.
314 315 316 317 318 319 320 321 322 323 |
# File 'weakmap.c', line 314
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
Iterates over keys and values. Note that unlike other collections, each
without block isn’t supported.
287 288 289 290 291 292 293 294 295 296 |
# File 'weakmap.c', line 287
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_value {|val| ... } ⇒ self
Iterates over values. Note that unlike other collections, each_value
without block isn’t supported.
341 342 343 344 345 346 347 348 349 350 |
# File 'weakmap.c', line 341
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
Returns true
if key
is a key in self
, otherwise false
.
566 567 568 569 570 |
# File 'weakmap.c', line 566
static VALUE
wmap_has_key(VALUE self, VALUE key)
{
return RBOOL(!UNDEF_P(wmap_lookup(self, key)));
}
|
#inspect ⇒ Object
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'weakmap.c', line 254
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
Returns true
if key
is a key in self
, otherwise false
.
566 567 568 569 570 |
# File 'weakmap.c', line 566
static VALUE
wmap_has_key(VALUE self, VALUE key)
{
return RBOOL(!UNDEF_P(wmap_lookup(self, key)));
}
|
#keys ⇒ Object
Returns a new Array containing all keys in the map.
369 370 371 372 373 374 375 376 377 378 379 |
# File 'weakmap.c', line 369
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;
}
|
#size ⇒ Numeric
Returns the number of referenced objects
578 579 580 581 582 583 584 585 586 587 588 589 590 591 |
# File 'weakmap.c', line 578
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
Returns true
if key
is a key in self
, otherwise false
.
566 567 568 569 570 |
# File 'weakmap.c', line 566
static VALUE
wmap_has_key(VALUE self, VALUE key)
{
return RBOOL(!UNDEF_P(wmap_lookup(self, key)));
}
|
#size ⇒ Numeric
Returns the number of referenced objects
578 579 580 581 582 583 584 585 586 587 588 589 590 591 |
# File 'weakmap.c', line 578
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
}
|
#values ⇒ Object
Returns a new Array containing all values in the map.
398 399 400 401 402 403 404 405 406 407 408 |
# File 'weakmap.c', line 398
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;
}
|