Project

General

Profile

Bug #7304 ยป 0001-Fix-WeakRef-finalize.patch

h.shirosaki (Hiroshi Shirosaki), 11/09/2012 06:33 PM

View differences:

gc.c
static int
wmap_final_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
{
VALUE obj, ary;
VALUE wmap, ary;
if (!existing) return ST_STOP;
obj = (VALUE)*key, ary = (VALUE)*value;
rb_ary_delete(ary, obj);
wmap = (VALUE)arg, ary = (VALUE)*value;
rb_ary_delete(ary, wmap);
if (!RARRAY_LEN(ary)) return ST_DELETE;
return ST_CONTINUE;
}
static VALUE
wmap_finalize(VALUE self, VALUE obj)
wmap_finalize(VALUE self, VALUE objid)
{
st_data_t data;
VALUE rids;
st_data_t orig, wmap, data;
VALUE obj, rids;
long i;
struct weakmap *w;
TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
obj = NUM2PTR(obj);
/* Get reference from object id. */
obj = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */
data = (st_data_t)obj;
if (st_delete(w->obj2wmap, &data, &data)) {
/* obj is original referenced object and/or weak reference. */
orig = (st_data_t)obj;
if (st_delete(w->obj2wmap, &orig, &data)) {
rids = (VALUE)data;
for (i = 0; i < RARRAY_LEN(rids); ++i) {
data = (st_data_t)RARRAY_PTR(rids)[i];
st_delete(w->wmap2obj, &data, NULL);
wmap = (st_data_t)RARRAY_PTR(rids)[i];
st_delete(w->wmap2obj, &wmap, NULL);
}
}
data = (st_data_t)obj;
if (st_delete(w->wmap2obj, &data, &data)) {
st_update(w->obj2wmap, (st_data_t)obj, wmap_final_func, 0);
wmap = (st_data_t)obj;
if (st_delete(w->wmap2obj, &wmap, &orig)) {
wmap = (st_data_t)obj;
st_update(w->obj2wmap, orig, wmap_final_func, wmap);
}
return self;
}
......
rids = rb_ary_tmp_new(1);
st_insert(w->obj2wmap, (st_data_t)orig, (st_data_t)rids);
}
rb_ary_push(rids, orig);
rb_ary_push(rids, wmap);
st_insert(w->wmap2obj, (st_data_t)wmap, (st_data_t)orig);
return nonspecial_obj_id(orig);
}
test/test_weakref.rb
ObjectSpace.garbage_collect
assert_raise(WeakRef::RefError) {weak.to_s}
end
def test_not_reference_different_object
bug7304 = '[ruby-core:49044]'
weakrefs = []
3.times do
obj = Object.new
def obj.foo; end
weakrefs << WeakRef.new(obj)
ObjectSpace.garbage_collect
end
assert_nothing_raised(NoMethodError, bug7304) {
weakrefs.each do |weak|
begin
weak.foo
rescue WeakRef::RefError
end
end
}
end
end
    (1-1/1)