Thomas Sondergaard wrote:
> Q1) I am wondering about the rb_gc_register_address/rb_gc_unregister_address
> function pairs.
> 
> The both take a VALUE pointer rather than a VALUE. Does that mean that to
> unregister I have to pass it the exact same VALUE pointer, or will another
> VALUE pointer pointing to the same object be equivalent. I'm asking because
> I might rb_gc_register_address and rb_gc_unregister_address multiple times
> for the same VALUE, but only once with each VALUE pointer.

It uses the address, not the value.

> Here's a scenario:
> 
> VALUE array = rb_ary_new();  // At some point this array is created
> somewhere in ruby
> 
> ... a little later ...
> 
> // I need to pass a reference of the object out of ruby's reach
> // so I 'lock' the object with rb_gc_register_address and keep the arrayRef
> // pointer with me somewhere safe
> VALUE *arrayRef = ALLOC(VALUE);
> *arrayRef = array;
> rb_gc_register_address(arrayRef)

[...snip...]

> Is this the way to do it?

That way would work fine, I think, but it seems a little convoluted.

If your C/C++ object has a VALUE member, you need only register the 
address of that just once, and unregister it in the destructor.  As long 
as your C/C++ object is around, the VALUE is registered and the object 
it is tied to will not go away.

Also, if the VALUE you need is just temporary for while you're in a C 
call, just use a regular VALUE stack variable; they're protected (see 
below) while in-use and cleaned up automatically when you're done with them.

Inversely, if you're trying to tie an C/C++ object/data to a Ruby 
object, just use malloc to allocated it and associate it with a Ruby 
object with Data_Wrap_Struct and provide a free function (use the normal 
free/malloc routines).

> Q2) Another thing that I am wondering about. Can the GC be invoked in the
> middle of my C code or does that only happen when control is in the "guts of
> ruby". What prevents the VALUEs I have on the stack from being GC'ed in that
> case?

The GC can be invoked whenever you call any Ruby function.  The Ruby GC 
scans the stack for VALUE variables and "marks" any it finds which point 
to valid objects.  So long as the current stack pointer is 
deeper/further into the stack than your VALUE variable, it is protected. 
  When your C/C++ function returns, it is eligible for collection and 
will be left unmarked during the next GC sweep.

One gotcha I learned about this is, the object must really be on the 
stack.  Compilers these days all optimize, so to be sure your variable 
actually lives on the stack and not in a register somewhere, all VALUEs 
that you want marked as in-use, you must declare it as volatile, i.e.:

volatile VALUE tempArray;


	Sean O'Dell