Made hash store a counter to the ruby VALUE object.

This should avoid a potential subtle bug when
using operator=.



git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9829 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Gonzalo Garramuno 2007-05-23 11:54:36 +00:00
commit 776398cd1d

View file

@ -136,10 +136,8 @@ namespace swig {
rb_gc_unregister_address( &_hash ); rb_gc_unregister_address( &_hash );
} }
GC_VALUE() : _obj( Qnil )
GC_VALUE() :_obj( Qnil )
{ {
GC_register();
} }
GC_VALUE(const GC_VALUE& item) : _obj(item._obj) GC_VALUE(const GC_VALUE& item) : _obj(item._obj)
@ -159,23 +157,37 @@ namespace swig {
GC_VALUE & operator=(const GC_VALUE& item) GC_VALUE & operator=(const GC_VALUE& item)
{ {
GC_unregister();
_obj = item._obj; _obj = item._obj;
GC_register();
return *this; return *this;
} }
void GC_register() void GC_register()
{ {
if ( FIXNUM_P(_obj) || SPECIAL_CONST_P(_obj) || SYMBOL_P(_obj) ) return; if ( FIXNUM_P(_obj) || SPECIAL_CONST_P(_obj) || SYMBOL_P(_obj) )
rb_hash_aset( _hash, _obj, Qtrue ); return;
VALUE val = rb_hash_aref( _hash, _obj );
unsigned n = FIXNUM_P(val) ? NUM2UINT(val) : 0;
++n;
rb_hash_aset( _hash, _obj, INT2NUM(n) );
} }
void GC_unregister() void GC_unregister()
{ {
if ( FIXNUM_P(_obj) || SPECIAL_CONST_P(_obj) || SYMBOL_P(_obj) ) return; if ( FIXNUM_P(_obj) || SPECIAL_CONST_P(_obj) || SYMBOL_P(_obj) )
return;
// this test should not be needed but I've noticed some very erratic // this test should not be needed but I've noticed some very erratic
// behavior of none being unregistered in some very rare situations. // behavior of none being unregistered in some very rare situations.
if ( BUILTIN_TYPE(_obj) == T_NONE ) return; if ( BUILTIN_TYPE(_obj) == T_NONE ) return;
rb_hash_delete( _hash, _obj );
VALUE val = rb_hash_aref( _hash, _obj );
unsigned n = FIXNUM_P(val) ? NUM2UINT(val) : 1;
--n;
if ( n )
rb_hash_aset( _hash, _obj, INT2NUM(n) );
else
rb_hash_delete( _hash, _obj );
} }
operator VALUE() const operator VALUE() const
@ -214,8 +226,8 @@ namespace swig {
args.id = op_id; \ args.id = op_id; \
args.nargs = 1; \ args.nargs = 1; \
args.target = VALUE(other); \ args.target = VALUE(other); \
ret = rb_protect( PROTECTFUNC(swig_protect_funcall), VALUE(&args), \ ret = rb_protect( PROTECTFUNC(swig_protect_funcall), \
&status ); \ VALUE(&args), &status ); \
} \ } \
if ( ret == Qnil ) { \ if ( ret == Qnil ) { \
VALUE a = rb_funcall( _obj, hash_id, 0 ); \ VALUE a = rb_funcall( _obj, hash_id, 0 ); \