Thread: [Rubydotnet-developer] GC ideas
Status: Alpha
Brought to you by:
thomas
From: Tim S. <ti...@ih...> - 2004-01-08 11:40:10
|
Hello. I changed the way I deal with the GC in my rubydotnetproxy object. (I haven't uploaded a version using these new changes.) I was previously using reference counting[*]. This was error prone and ugly. (It was not easy to be sure that I hadn't made a mistake somewhere.) [*] This would all be easy if I had a rule like "for each VALUE, there is at most one RbType wrapping it", but then I couldn't use implicit constructors for type conversions. Now for .NET calling Ruby: In .NET I have a collection of weakreferences of RbTypes. (I add to it whenever a RbType is constructed.) Whenever Ruby's GC is running, I call rb_gc_mark for each VALUE where the RbType has not yet been collected. (And remove those which have been collected.) In this way, as long as .NET has access to the RbType, Ruby will not collect the associated VALUE. For Ruby calling .NET In .NET I have a hashtable from .NET OBJ id => object. Roughly as often as the .NET GC is run, I create a C array of OBJs, assign it to a global variable and then rb_gc_start(). My mark_DotNetData() function adds its type_id/instance_id to the array. Then I pass this array to .NET and it removes all objects from the hashtable whose ids don't appear in the array. This still suffers from the circular references memory leak that reference counting had. BTW: I saw (on a webpage somewhere? I seem to recall it was Thomas') someone say they added a feature to allow you to do things like the following Ruby require 'dotnet' class Foo end foo = Foo.new h = Hashtable.new h[foo] = 12345 i.e. have arbitrary Ruby objects as arguments to .NET methods by wrapping them up as `.NET wrapper around Ruby object` and unwrapping on the other end. This seems like a really great idea. It does raise issues like "should we still convert arguments which are Ruby strings into .NET strings automatically. Similarly for integers etc. -- Q: What is normed, complete, and yellow? A: A Bananach space... |
From: Thomas S. <th...@th...> - 2004-01-12 12:33:03
|
I don't really understand how reference counting is error prone? Speaking for my own implementation I use a System.Runtime.InteropServices.GCHandle in the ruby-proxy-object to keep the .net object reference. The GCHandle mechanism is a reference counting scheme for referencing .net objects outside of the .net runtime. Similary, I use rb_gc_register_address in the .net-proxy constructor to tell ruby that there is an external reference to that object. I don't see any significant potential for forgetting to update the reference count, the major problem is the circular references problem. Cheers, Thomas ---------- Original Message ----------- From: Tim Sutherland <ti...@ih...> To: rub...@li... Sent: Fri, 9 Jan 2004 00:40:10 +1300 Subject: [Rubydotnet-developer] GC ideas > Hello. I changed the way I deal with the GC in my rubydotnetproxy > object. (I haven't uploaded a version using these new changes.) > > I was previously using reference counting[*]. This was error prone > and ugly. (It was not easy to be sure that I hadn't made a mistake > somewhere.) > > [*] This would all be easy if I had a rule like "for each VALUE, > there is at most one RbType wrapping it", but then I couldn't use implicit > constructors for type conversions. > > Now for .NET calling Ruby: > In .NET I have a collection of weakreferences of RbTypes. (I add > to it whenever a RbType is constructed.) > > Whenever Ruby's GC is running, I call rb_gc_mark for each VALUE > where the RbType has not yet been collected. (And remove those > which have been collected.) > > In this way, as long as .NET has access to the RbType, Ruby will > not collect the associated VALUE. > > For Ruby calling .NET > In .NET I have a hashtable from .NET OBJ id => object. > > Roughly as often as the .NET GC is run, I create a C array of > OBJs, assign it to a global variable and then rb_gc_start(). > > My mark_DotNetData() function adds its type_id/instance_id to > the array. > > Then I pass this array to .NET and it removes all objects from > the hashtable whose ids don't appear in the array. > > This still suffers from the circular references memory leak that > reference counting had. > > BTW: I saw (on a webpage somewhere? I seem to recall it was Thomas') > someone say they added a feature to allow you to do things like the > following Ruby > require 'dotnet' > > class Foo > end > foo = Foo.new > > h = Hashtable.new > h[foo] = 12345 > > i.e. have arbitrary Ruby objects as arguments to .NET methods by > wrapping them up as `.NET wrapper around Ruby object` and unwrapping > on the other end. > > This seems like a really great idea. It does raise issues like > "should we still convert arguments which are Ruby strings into .NET strings > automatically. Similarly for integers etc. > > -- > Q: What is normed, complete, and yellow? > A: A Bananach space... > > ------------------------------------------------------- > This SF.net email is sponsored by: Perforce Software. > Perforce is the Fast Software Configuration Management System > offering advanced branching capabilities and atomic changes on 50+ platforms. > Free Eval! http://www.perforce.com/perforce/loadprog.html > _______________________________________________ > Rubydotnet-developer mailing list > Rub...@li... > https://lists.sourceforge.net/lists/listinfo/rubydotnet-developer ------- End of Original Message ------- |
From: Tim S. <ti...@ih...> - 2004-01-13 01:10:35
|
On Mon, Jan 12, 2004 at 01:32:58PM +0100, Thomas Sondergaard wrote: > I don't really understand how reference counting is error prone? Speaking > for my own implementation I use a System.Runtime.InteropServices.GCHandle in > the ruby-proxy-object to keep the .net object reference. The GCHandle > mechanism is a reference counting scheme for referencing .net objects > outside of the .net runtime. Similary, I use rb_gc_register_address in > the .net-proxy constructor to tell ruby that there is an external reference > to that object. I don't see any significant potential for forgetting to > update the reference count, the major problem is the circular references > problem. [...] Okay, I was exaggerating :) Reference counting was working perfectly well for me too. The hard part is avoiding race conditions with the garbage collector(s) [System.GC.KeepAlive etc.], and my idea doesn't help with this. However, when I was using reference counting I had (for Ruby calling .NET) about 7 C# methods which would increase a reference count and return an OBJ. It was assumed that the C code would store this in a struct DotNetData and decrease the reference count when freed. I didn't like that these methods depended on their callers to do the right thing. -- The pigeonhole principle: If you have N pigeons and drill at least N + 1 holes in them, you will have at least one pigeon with at least two holes in it. |