Holding a reference to a ruby object outside the interpreter

T

Thomas

How can I hold a reference to a ruby object outside the interpreter?
Ie, how can I prevent it from being garbage collected if my (external)
reference is the only one.

In .net I can use a System.Runtime.InteropServices.GCHandle if I want
to hold a reference to a managed object in unmanaged code. Calling
GCHandle.Alloc(object anObject) pins the objects address so the GC
will never move it and prevents the object from being gc'ed before the
handle is release by calling its Free() method.

What is the equivalent technique in ruby?

/Thomas
 
S

Sean O'Dell

Thomas said:
How can I hold a reference to a ruby object outside the interpreter?
Ie, how can I prevent it from being garbage collected if my (external)
reference is the only one.

In .net I can use a System.Runtime.InteropServices.GCHandle if I want
to hold a reference to a managed object in unmanaged code. Calling
GCHandle.Alloc(object anObject) pins the objects address so the GC
will never move it and prevents the object from being gc'ed before the
handle is release by calling its Free() method.

What is the equivalent technique in ruby?

There are several ways you can do this:

If the VALUE (which is the C data type that points to a Ruby object) is
on the stack, so long as it doesn't go out of scope, Ruby will not
collect the object. This means that, for objects you create for use
during a function call, you don't need to do ANYTHING; Ruby protects it
until your function returns.

Another way to do it is to create a C VALUE variable globally or as part
of a class. You can call rb_gc_register_address to register the memory
space holding the VALUE. So long as your variable exists, Ruby protects
the object it points to. When you are done with the object, call
rb_gc_unregister_address.

If you don't have a fixed memory location holding a VALUE, you can just
called rb_global_variable to register the object as an unnamed global,
and it will NEVER get collected. This is sort of brutal and can lead to
memory leaks because the object never goes away.

The last way I know of is if you use Data_Make_Struct or
Data_Wrap_Struct to wrap your own C data type (a struct or whatever) as
a Ruby object, and your data type has VALUEs pointing to objects and you
want them to be treated as "children" to your object. You must provide
a "mark" function which marks those VALUEs when your object gets marked
(making them ineligible for collection).

Sean O'Dell
 
T

Thomas

If the VALUE (which is the C data type that points to a Ruby object) is
on the stack, so long as it doesn't go out of scope, Ruby will not
collect the object. This means that, for objects you create for use
during a function call, you don't need to do ANYTHING; Ruby protects it
until your function returns.

My reference will be stored on the managed heap in .net and will not
be on the stack.
Another way to do it is to create a C VALUE variable globally or as part
of a class. You can call rb_gc_register_address to register the memory
space holding the VALUE. So long as your variable exists, Ruby protects
the object it points to. When you are done with the object, call
rb_gc_unregister_address.

Well this interests me. You say I need to allocate it globally? Can I
store it on the (unmanaged) heap?

I dug out the source for rb_register_address

void
rb_gc_register_address(addr)
VALUE *addr;
{
struct gc_list *tmp;

tmp = ALLOC(struct gc_list);
tmp->next = global_List;
tmp->varptr = addr;
global_List = tmp;
}

And it seems it adds the VALUE *addr to a linked list, which I guess
will then be protected from gc'ing. It seems allocating the VALUE on
the heap should be perfectly safe. Is it?

This would work for me, as I can keep a reference to the unmanaged
heap object from managed space. and clean it up when the managed
reference goes away.

Cheers,

Thomas
 
S

Sean O'Dell

Thomas said:
My reference will be stored on the managed heap in .net and will not
be on the stack.




Well this interests me. You say I need to allocate it globally? Can I
store it on the (unmanaged) heap?

I dug out the source for rb_register_address

void
rb_gc_register_address(addr)
VALUE *addr;
{
struct gc_list *tmp;

tmp = ALLOC(struct gc_list);
tmp->next = global_List;
tmp->varptr = addr;
global_List = tmp;
}

And it seems it adds the VALUE *addr to a linked list, which I guess
will then be protected from gc'ing. It seems allocating the VALUE on
the heap should be perfectly safe. Is it?

This would work for me, as I can keep a reference to the unmanaged
heap object from managed space. and clean it up when the managed
reference goes away.

That should work just fine; with register_address, it's only important
that the memory space for the VALUE doesn't go away, so any memory heap
should do (assuming .net doesn't do some sort of weird virtual memory
thing where the memory space you allocate can move around).

Sean O'Dell
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top