From: Scott Thompson Date: 2003-08-09T05:16:55+09:00 Subject: A question about Circular References Hello folks, I have a question about Circular References in classes that I create from an extension that I've been playing with. Since I'm very new to Ruby and much newer to extensions, after thinking about my problem for quite some time I decided it would probably be much more efficient to ask someone than try to figure it out myself. So here goes. At Apple's World Wide Developer's Conference in May, a presenter demonstrated a way to access the Quartz drawing system that is Part of Mac OS X from Python. I thought that was pretty neat, but was having lots of fun with Ruby and thought it would be a pain to learn another scripting language. Logically, of course, I decided that I might try to write my own extension for Ruby to do the same thing. As part of working with that I have created two classes that wrap C structures commonly found in Quartz. The first is CGSize whose C type looks something like: struct CGSize { float height; float width; }; The second is equally simple, CGPoint struct CGPoint { float x; float y; } No big deal. The problem came in when I started looking at CGRect which is defined as: struct CGRect { CGPoint origin; CGSize size; } Now it seems likely that from ruby one might want to do something like this: someRect = CGRect.make(0, 0, 100, 200); # create a CGRect with it's origin at (0,0) and it's extent 100 points wide and 200 points tall theSize = someRect.size; # Get the size out of the rectangle. When I create the CGRect object I use Data_Make_Struct. When I want to return the size object out of that rectangle, my thought was to use Data_Wrap_Struct. The thing that worries me is that the CGSize object I think I want to return from the "size()" method of the CGRect class would be wrapping a piece of the CGRect structure itself. I'm concerned that should the CGRect be garbage collected that the CGSize object, which is an object wrapper around part of the CGRect's memory, will no longer be valid because the CGRect's memory was reclaimed. In other words, the pointer to the memory that the CGSize object wraps will be halfway through the memory owned by the CGRect. I'm worried that the system might dispose of the CGRect not knowing that the CGSize object still needs that memory. I hope my concern is clear... I'm struggling to find the correct words to explain it. At any rate, this leads to the following questions: First, do I even need to worry about it? Is the Garbage Collector in ruby clever enough to see that one of my objects has a pointer into the memory that makes up the CGRect object and, therefore, will not release the memory even though the CGRect object itself is not referenced? If the Garbage Collector is not clever enough to do that, it seems reasonable that the CGRect object might create references to a CGPoint object and a CGSize object within itself. At the same time, however, the CGPoint and CGSize objects want to keep a reference to the CGRect so that it's memory won't go away until they are done with it. Will setting up that kind of circular reference prevent Ruby from being able to garbage collect the rectangle and it's point/origin pair? Any insight would be appreciated. I've you've made it this far, thank you for your time! Scott Thompson