When the UV UDP handle object receive data, UV async library calls a
callback passin gthe UV UDP handle, so in that callback I need to
retrieve the Ruby MyClass instance from the uv_handle:
VALUE instance = uv_handle->data;
// Run the Ruby callback and so...
rb_funcall(instance, xxxxxx, xxxxxx, xxxxxx);
Assuming that the created MyClass instance is not referenced in Ruby
land (it's not in a hash, array, variable...) then this code would
crash since probably GC has freed "instance". So there are (or could
be) 3 solutions:
1) Storing the instance in a Ruby hash (and yes, it works, but it's ugly).
2) In the MyClass_alloc() function, before the "return" add:
rb_gc_register_address(&instance);
But this DOES NOT work for me, I get segmentfauls !
3) Setting a mark function in Data_Wrap_Struct, and within such a mark
function do:
rb_gc_mark(uv_handle->data);
I would like to learn a bit more about rb_gc_mark(). In my experiments
such a function is never executed if the object is not assigned to a
variable or stored in a hash/array/whatever. But, in case it's stored
somewhere, then the mark() function is executed multiple times by
Ruby.
Is it the normal behavior?
···
2012/5/17 Iñaki Baz Castillo <ibc@aliax.net>:
3) Setting a mark function in Data_Wrap_Struct, and within such a mark
function do:
rb_gc_mark(uv_handle->data);
2) rb_gc_mark(VALUE object) is *required* for telling Ruby to GC
"object" (which is stored within our wrapped DATA struct) when the
owner Ruby object is GC'd.
Forget this please, this happens because I've a thread running
GC.start every 0.1 seconds. I've understood how "mark" works:
When GC runs (Ruby decides when) it checks all the allocated VALUEs
and "marks" all the values that are in the current scope or are stored
in some attribute/array/hasy. If an object out of the current scope is
not referenced it's not marked so, next to the "mark" action, Ruby
performs "sweep" action which frees all the non marked objects.
Hope this is correct
Unfortunatelly I still don't know how to translate this stuff to Ruby
C extensions. My question is very simple:
- MyClass_alloc() function mallocs a C struct.
- The C struct contains a "my_string" VALUE field and I assign there
i.e. a Ruby String (which does not exist in Ruby land).
- Of course MyClass_free() function should free the C struct.
But, what about "my_string" VALUE within the C struct?
- Let's say that I've an instance of MyClass in a global variable $my_class.
- Then I run GC.start. Would it free my_string VALUE? (yes/no)
- In case of yes, should then I provide a MyClass_mark() function
which does this?:
rb_gc_mark(data->my_string)
And then, what's the meaning of rb_gc_(un)register_address(&VALUE)?
For me it means "this VALUE will never been GC'd even if it's not
referenced in Ruby land.
Thanks a lot.
···
2012/5/17 Iñaki Baz Castillo <ibc@aliax.net>:
I would like to learn a bit more about rb_gc_mark(). In my experiments
such a function is never executed if the object is not assigned to a
variable or stored in a hash/array/whatever. But, in case it's stored
somewhere, then the mark() function is executed multiple times by
Ruby.
I can sure that rb_gc_register_address(&value) does not keep value
from being GC'd if value comes out of the scope. So, maybe
rb_gc_register_address() (which is the very same as
rb_global_variable()) is just useful when the VALUE is directly
created from C land?
···
2012/5/17 Hans Mackowiak <lists@ruby-forum.com>:
i create an hash from the C-side, mark them with rb_global_variable and
then store my objects into them ...
- While my_class instance (which wraps the C struct referencing
my_string VALUE) remains in the scope (or stored in a global variable)
my_string is NOT GC'd. I know it because I've stored its object_id and
used it in ObjectSpace._id2ref(id) and it returns my_string.
So... even if I've seen the usage of rb_gc_mark() in some C
extensions, in my experiments it does nothing. Any help would be
appreciated.
Thanks a lot.
···
2012/5/17 Iñaki Baz Castillo <ibc@aliax.net>:
- MyClass_alloc() function mallocs a C struct.
- The C struct contains a "my_string" VALUE field and I assign there
i.e. a Ruby String (which does not exist in Ruby land).
- Of course MyClass_free() function should free the C struct.
But, what about "my_string" VALUE within the C struct?
- Let's say that I've an instance of MyClass in a global variable $my_class.
- Then I run GC.start. Would it free my_string VALUE? (yes/no)
- In case of yes, should then I provide a MyClass_mark() function
which does this?:
i create an hash from the C-side, mark them with rb_global_variable and
then store my objects into them
this protects my objects from being deleted.
This is probably wrong.
By using rb_global_variable the object can never be reclaimed by the
garbage collector.
You should either:
Return a ruby object to the user that stores your Hash.
Use Data_Wrap_Struct/Data_Make_Struct to store your Hash and use
rb_gc_mark to indicate it is still alive.
Use a constant, class or instance variable on a pre-defined class to
store your Hash.
no its correct i want the control when the GC gets the object or not.
thats why i use a hash, when my binding removes the object out of the
hash, GC deleteds it. but no earlier
Forget it please! I was storing my_string in a class attribute
Yes, rb_gc_mark() stuf is fully understood. Now I will investigate
what rb_gc_(un)register does, since in my experiments it does NOTHING.
···
2012/5/17 Iñaki Baz Castillo <ibc@aliax.net>:
Ok, after some experiment I'm confused:
- I run GC.startt every 0.1 seconds.
- While my_class instance (which wraps the C struct referencing
my_string VALUE) remains in the scope (or stored in a global variable)
my_string is NOT GC'd. I know it because I've stored its object_id and
used it in ObjectSpace._id2ref(id) and it returns my_string.
So... even if I've seen the usage of rb_gc_mark() in some C
extensions, in my experiments it does nothing. Any help would be
appreciated.
I was unclear, you should probably not use rb_global_variable on your Hash. You should instead bind your Hash as a regular ruby constant, wrap it in a struct, or return it as part of a regular ruby object.
···
On May 18, 2012, at 00:20, Hans Mackowiak wrote:
Eric Hodel wrote in post #1061208:
On May 17, 2012, at 12:31, Hans Mackowiak wrote:
i create an hash from the C-side, mark them with rb_global_variable and
then store my objects into them
this protects my objects from being deleted.
This is probably wrong.
By using rb_global_variable the object can never be reclaimed by the
garbage collector.
You should either:
Return a ruby object to the user that stores your Hash.
Use Data_Wrap_Struct/Data_Make_Struct to store your Hash and use
rb_gc_mark to indicate it is still alive.
Use a constant, class or instance variable on a pre-defined class to
store your Hash.
no its correct i want the control when the GC gets the object or not.
thats why i use a hash, when my binding removes the object out of the
hash, GC deleteds it. but no earlier
You use rb_gc_mark() to mark ruby objects pointed-to by C structs that are wrapped as ruby objects.
If you have
struct my_struct {
VALUE my_string;
}
And wrap that with Data_Wrap_Struct, then you must provide a mark function that tells ruby about your string inside your struct (because ruby does not otherwise know it exists).
To do this you use rb_gc_mark(the_struct->my_string). Without calling rb_gc_mark the garbage collector may reclaim your string which can lead to a crash the next time you try to use it.
···
On May 17, 2012, at 12:24, Iñaki Baz Castillo wrote:
2012/5/17 Iñaki Baz Castillo <ibc@aliax.net>:
Ok, after some experiment I'm confused:
- I run GC.startt every 0.1 seconds.
- While my_class instance (which wraps the C struct referencing
my_string VALUE) remains in the scope (or stored in a global variable)
my_string is NOT GC'd. I know it because I've stored its object_id and
used it in ObjectSpace._id2ref(id) and it returns my_string.
So... even if I've seen the usage of rb_gc_mark() in some C
extensions, in my experiments it does nothing. Any help would be
appreciated.
Forget it please! I was storing my_string in a class attribute
Yes, rb_gc_mark() stuf is fully understood. Now I will investigate
what rb_gc_(un)register does, since in my experiments it does NOTHING.
Sure, it's fully understood now, and in fact, without the mark crashes occur.
Now my other question is about the undocumented
rb_gc_register_address(VALUE object). As per my experience, this is
only valid for VALUE created within ruby code, and not for Ruby
objects that run in Ruby land. For example, in my C extension
XXXXX_init() function I create a Ruby String which I use within my C
code:
VALUE string_aaa = rb_str_new2("aaa");
So I must add:
rb_gc_register_address(&string_aaa);
Otherwhise it's GC'd. But if I try to do the same with a previously
existing Ruby object (created in Ruby land or referenced in Ruby land)
then rb_gc_register_address does nothing. For example:
VALUE MyClass_do_domething(VALUE self)
{
rb_gc_register_address(&self);
return self;
}
This does NOTHING. The object (self) will be GC'd as usual.
···
2012/5/18 Eric Hodel <drbrain@segment7.net>:
To do this you use rb_gc_mark(the_struct->my_string). Without calling rb_gc_mark the garbage collector may reclaim your string which can lead to a crash the next time you try to use it.
rb_gc_register_address is for use with fixed memory addresses like:
static VALUE string_aaa;
Using it on pointers to the heap or stack is going to result in undefined behavior.
···
On May 17, 2012, at 15:34, Iñaki Baz Castillo wrote:
2012/5/18 Eric Hodel <drbrain@segment7.net>:
To do this you use rb_gc_mark(the_struct->my_string). Without calling rb_gc_mark the garbage collector may reclaim your string which can lead to a crash the next time you try to use it.
Sure, it's fully understood now, and in fact, without the mark crashes occur.
Now my other question is about the undocumented
rb_gc_register_address(VALUE object). As per my experience, this is
only valid for VALUE created within ruby code, and not for Ruby
objects that run in Ruby land. For example, in my C extension
XXXXX_init() function I create a Ruby String which I use within my C
code:
VALUE string_aaa = rb_str_new2("aaa");
So I must add:
rb_gc_register_address(&string_aaa);
Otherwhise it's GC'd. But if I try to do the same with a previously
existing Ruby object (created in Ruby land or referenced in Ruby land)
then rb_gc_register_address does nothing. For example:
VALUE MyClass_do_domething(VALUE self)
{
rb_gc_register_address(&self);
return self;
}
This does NOTHING. The object (self) will be GC'd as usual.