mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Allow non-finalizable objects in ObjectSpace::WeakMap
[feature #16035] This goes one step farther than what nobu did in [feature #13498] With this patch, special objects such as static symbols, integers, etc can be used as either key or values inside WeakMap. They simply don't have a finalizer defined on them. This is useful if you need to deduplicate value objects
This commit is contained in:
parent
e4be2fda3d
commit
a4a19b114b
Notes:
git
2019-08-31 04:40:14 +09:00
2 changed files with 30 additions and 21 deletions
16
gc.c
16
gc.c
|
@ -2986,18 +2986,12 @@ should_be_callable(VALUE block)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
should_be_finalizable_internal(VALUE obj)
|
should_be_finalizable(VALUE obj)
|
||||||
{
|
{
|
||||||
if (!FL_ABLE(obj)) {
|
if (!FL_ABLE(obj)) {
|
||||||
rb_raise(rb_eArgError, "cannot define finalizer for %s",
|
rb_raise(rb_eArgError, "cannot define finalizer for %s",
|
||||||
rb_obj_classname(obj));
|
rb_obj_classname(obj));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
should_be_finalizable(VALUE obj)
|
|
||||||
{
|
|
||||||
should_be_finalizable_internal(obj);
|
|
||||||
rb_check_frozen(obj);
|
rb_check_frozen(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10253,6 +10247,7 @@ wmap_allocate(VALUE klass)
|
||||||
static int
|
static int
|
||||||
wmap_live_p(rb_objspace_t *objspace, VALUE obj)
|
wmap_live_p(rb_objspace_t *objspace, VALUE obj)
|
||||||
{
|
{
|
||||||
|
if (!FL_ABLE(obj)) return TRUE;
|
||||||
if (!is_id_value(objspace, obj)) return FALSE;
|
if (!is_id_value(objspace, obj)) return FALSE;
|
||||||
if (!is_live_object(objspace, obj)) return FALSE;
|
if (!is_live_object(objspace, obj)) return FALSE;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -10510,10 +10505,13 @@ wmap_aset(VALUE self, VALUE wmap, VALUE orig)
|
||||||
struct weakmap *w;
|
struct weakmap *w;
|
||||||
|
|
||||||
TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
|
TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
|
||||||
should_be_finalizable_internal(orig);
|
if (FL_ABLE(orig)) {
|
||||||
should_be_finalizable_internal(wmap);
|
|
||||||
define_final0(orig, w->final);
|
define_final0(orig, w->final);
|
||||||
|
}
|
||||||
|
if (FL_ABLE(wmap)) {
|
||||||
define_final0(wmap, w->final);
|
define_final0(wmap, w->final);
|
||||||
|
}
|
||||||
|
|
||||||
st_update(w->obj2wmap, (st_data_t)orig, wmap_aset_update, wmap);
|
st_update(w->obj2wmap, (st_data_t)orig, wmap_aset_update, wmap);
|
||||||
st_insert(w->wmap2obj, (st_data_t)wmap, (st_data_t)orig);
|
st_insert(w->wmap2obj, (st_data_t)wmap, (st_data_t)orig);
|
||||||
return nonspecial_obj_id(orig);
|
return nonspecial_obj_id(orig);
|
||||||
|
|
|
@ -16,16 +16,27 @@ class TestWeakMap < Test::Unit::TestCase
|
||||||
|
|
||||||
def test_aset_const
|
def test_aset_const
|
||||||
x = Object.new
|
x = Object.new
|
||||||
assert_raise(ArgumentError) {@wm[true] = x}
|
@wm[true] = x
|
||||||
assert_raise(ArgumentError) {@wm[false] = x}
|
assert_same(x, @wm[true])
|
||||||
assert_raise(ArgumentError) {@wm[nil] = x}
|
@wm[false] = x
|
||||||
assert_raise(ArgumentError) {@wm[42] = x}
|
assert_same(x, @wm[false])
|
||||||
assert_raise(ArgumentError) {@wm[:foo] = x}
|
@wm[nil] = x
|
||||||
assert_raise(ArgumentError) {@wm[x] = true}
|
assert_same(x, @wm[nil])
|
||||||
assert_raise(ArgumentError) {@wm[x] = false}
|
@wm[42] = x
|
||||||
assert_raise(ArgumentError) {@wm[x] = nil}
|
assert_same(x, @wm[42])
|
||||||
assert_raise(ArgumentError) {@wm[x] = 42}
|
@wm[:foo] = x
|
||||||
assert_raise(ArgumentError) {@wm[x] = :foo}
|
assert_same(x, @wm[:foo])
|
||||||
|
|
||||||
|
@wm[x] = true
|
||||||
|
assert_same(true, @wm[x])
|
||||||
|
@wm[x] = false
|
||||||
|
assert_same(false, @wm[x])
|
||||||
|
@wm[x] = nil
|
||||||
|
assert_same(nil, @wm[x])
|
||||||
|
@wm[x] = 42
|
||||||
|
assert_same(42, @wm[x])
|
||||||
|
@wm[x] = :foo
|
||||||
|
assert_same(:foo, @wm[x])
|
||||||
end
|
end
|
||||||
|
|
||||||
def assert_weak_include(m, k, n = 100)
|
def assert_weak_include(m, k, n = 100)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue