Professional Web Applications Themes

A question about Circular References - Ruby

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 ...

  1. #1

    Default 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


    Scott Thompson Guest

  2. #2

    Default Re: A question about Circular References

    Scott Thompson wrote:
    > 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.
    Yes.
    > 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.
    Correct. When the CGRect Ruby instance is garbage-collected, the CGRect
    C struct that it "wraps" will be free'd as well. And that in turn
    invalidates the pointers to its contained CGPoint and CGSize structs,
    even if there are still outstanding Ruby objects that wrap those structs.
    > 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.
    Yes, this is a good thing to worry about ;)
    > 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?
    No. This is your responsibility.
    > 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...
    Not sure I follow you here. Ruby only knows what you tell it about your
    extension module's classes. For example, even though /you/ know that a
    CGRect object contains references to a CGPoint and a CGSize, Ruby
    doesn't deduce that. This is part of the motivation for writing a "mark"
    function for your extension objects; the garbage collector calls that
    mark function to ask, say, your CGRect object what /other/ Ruby objects
    are reachable from there. In your case, you'd want to be sure to call
    rb_gc_mark() for the Ruby objects that are wrapping the CGPoint and
    CGSize objects:

    void mark_CGRect(CGRect *rect)
    {
    VALUE pointObj, sizeObj;
    pointObj = rubyObjectFor(rect->origin);
    sizeObj = rubyObjectFor(rect->size);
    rb_gc_mark(pointObj);
    rb_gc_mark(sizeObj);
    }

    > At the same time, however, the CGPoint and CGSize objects want
    > to keep a reference to the CGRect so that its 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 its point/origin pair?
    No, not as long as the mark functions for CGSize and CGPoint mark their
    parent CGRect as still being "reachable". If you still have some
    outstanding references to the point or size objects for a given
    rectangle, their mark functions will get called and thus the rectangle
    won't get garbage-collected.

    Yes, it is a little complicated ;)

    Hope this helps,

    Lyle

    Lyle Johnson Guest

  3. Moderated Post

    Default Re: A question about Circular References

    Removed by Administrator
    Lyle Johnson Guest
    Moderated Post

  4. #4

    Default Re: A question about Circular References

    >>>>> "L" == Lyle Johnson <lyleknology.net> writes:

    L> I'm not sure that this is in fact true for "Data" objects like these. I
    L> took a quick look at the Ruby source code (see rb_gc_mark_children() in
    L> gc.c) and it's not clear to me that instance variables for Data
    L> (extension) objects get marked automatically. You should add some
    L> debugging statements (or whatever) to convince yourself that this is
    L> what actually happens.

    line 622 in gc.c (ruby 1.8.0)


    Guy Decoux

    ts Guest

  5. #5

    Default Re: A question about Circular References

    > L> I'm not sure that this is in fact true for "Data" objects like
    > these. I
    > L> took a quick look at the Ruby source code (see
    > rb_gc_mark_children() in
    > L> gc.c) and it's not clear to me that instance variables for Data
    > L> (extension) objects get marked automatically. You should add some
    > L> debugging statements (or whatever) to convince yourself that this is
    > L> what actually happens.
    >
    > line 622 in gc.c (ruby 1.8.0)
    >
    > Guy Decoux
    Do you really mean line 662 (two 6's not two 2's)? On that line if a
    ruby object has any "generic instance variables" then those variables
    are marked. Then after that, 'round line 846, the mark routine for the
    data pointer is called.

    Looks like my stragegy will work. Thank you both for your time and
    expertise!

    Scott


    Scott Thompson Guest

Similar Threads

  1. #39046 [NEW]: double free on circular references
    By checat at yandex dot ru in forum PHP Bugs
    Replies: 4
    Last Post: October 5th, 03:40 PM
  2. Quotes and circular references
    By JR in forum PERL Miscellaneous
    Replies: 3
    Last Post: September 9th, 04:26 PM
  3. circular use bug?
    By Jim Thomason in forum PERL Miscellaneous
    Replies: 2
    Last Post: September 3rd, 01:32 AM
  4. Circular references are not supported
    By Dan C Douglas in forum ASP.NET Building Controls
    Replies: 3
    Last Post: August 13th, 09:21 PM
  5. Another reference question (hash of hash references)
    By Tim Musson in forum PERL Beginners
    Replies: 2
    Last Post: August 8th, 01:11 PM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139