0001-Fix-WeakRef-finalize.patch

Hiroshi Shirosaki, 11/09/2012 06:33 PM

Download (3.42 KB)

View differences:

gc.c
3748 3748
static int
3749 3749
wmap_final_func(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
3750 3750
{
3751
    VALUE obj, ary;
3751
    VALUE wmap, ary;
3752 3752
    if (!existing) return ST_STOP;
3753
    obj = (VALUE)*key, ary = (VALUE)*value;
3754
    rb_ary_delete(ary, obj);
3753
    wmap = (VALUE)arg, ary = (VALUE)*value;
3754
    rb_ary_delete(ary, wmap);
3755 3755
    if (!RARRAY_LEN(ary)) return ST_DELETE;
3756 3756
    return ST_CONTINUE;
3757 3757
}
3758 3758

  
3759 3759
static VALUE
3760
wmap_finalize(VALUE self, VALUE obj)
3760
wmap_finalize(VALUE self, VALUE objid)
3761 3761
{
3762
    st_data_t data;
3763
    VALUE rids;
3762
    st_data_t orig, wmap, data;
3763
    VALUE obj, rids;
3764 3764
    long i;
3765 3765
    struct weakmap *w;
3766 3766

  
3767 3767
    TypedData_Get_Struct(self, struct weakmap, &weakmap_type, w);
3768
    obj = NUM2PTR(obj);
3768
    /* Get reference from object id. */
3769
    obj = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */
3769 3770

  
3770
    data = (st_data_t)obj;
3771
    if (st_delete(w->obj2wmap, &data, &data)) {
3771
    /* obj is original referenced object and/or weak reference. */
3772
    orig = (st_data_t)obj;
3773
    if (st_delete(w->obj2wmap, &orig, &data)) {
3772 3774
	rids = (VALUE)data;
3773 3775
	for (i = 0; i < RARRAY_LEN(rids); ++i) {
3774
	    data = (st_data_t)RARRAY_PTR(rids)[i];
3775
	    st_delete(w->wmap2obj, &data, NULL);
3776
	    wmap = (st_data_t)RARRAY_PTR(rids)[i];
3777
	    st_delete(w->wmap2obj, &wmap, NULL);
3776 3778
	}
3777 3779
    }
3778 3780

  
3779
    data = (st_data_t)obj;
3780
    if (st_delete(w->wmap2obj, &data, &data)) {
3781
	st_update(w->obj2wmap, (st_data_t)obj, wmap_final_func, 0);
3781
    wmap = (st_data_t)obj;
3782
    if (st_delete(w->wmap2obj, &wmap, &orig)) {
3783
	wmap = (st_data_t)obj;
3784
	st_update(w->obj2wmap, orig, wmap_final_func, wmap);
3782 3785
    }
3783 3786
    return self;
3784 3787
}
......
3800 3803
	rids = rb_ary_tmp_new(1);
3801 3804
	st_insert(w->obj2wmap, (st_data_t)orig, (st_data_t)rids);
3802 3805
    }
3803
    rb_ary_push(rids, orig);
3806
    rb_ary_push(rids, wmap);
3804 3807
    st_insert(w->wmap2obj, (st_data_t)wmap, (st_data_t)orig);
3805 3808
    return nonspecial_obj_id(orig);
3806 3809
}
test/test_weakref.rb
21 21
    ObjectSpace.garbage_collect
22 22
    assert_raise(WeakRef::RefError) {weak.to_s}
23 23
  end
24

  
25
  def test_not_reference_different_object
26
    bug7304 = '[ruby-core:49044]'
27
    weakrefs = []
28
    3.times do
29
      obj = Object.new
30
      def obj.foo; end
31
      weakrefs << WeakRef.new(obj)
32
      ObjectSpace.garbage_collect
33
    end
34
    assert_nothing_raised(NoMethodError, bug7304) {
35
      weakrefs.each do |weak|
36
        begin
37
          weak.foo
38
        rescue WeakRef::RefError
39
        end
40
      end
41
    }
42
  end
24 43
end
25
-