-
Notifications
You must be signed in to change notification settings - Fork 5.4k
[Feature #19406] Allow declarative definition of references for rb_typed_data_struct #7153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
bc6408d
to
ee142f1
Compare
69779ab
to
e749822
Compare
56e6b0f
to
bd48a53
Compare
bd48a53
to
6515578
Compare
7b1b866
to
80c5389
Compare
7d0685f
to
c7b9830
Compare
When using rb_data_type_struct to wrap a C struct, that C struct can contain VALUE references to other Ruby objects. If this is the case then one must also define dmark and optionally dcompact callbacks in order to allow these objects to be correctly handled by the GC. This is suboptimal as it requires GC related logic to be implemented by extension developers. This can be a cause of subtle bugs when references are not marked of updated correctly inside these callbacks. This commit provides an alternative approach, useful in the simple case where the C struct contains VALUE members (ie. there isn't any conditional logic, or data structure manipulation required to traverse these references). In this case references can be defined using a declarative syntax as a list of edges (or, pointers to references). A flag can be set on the rb_data_type_struct to notify the GC that declarative references are being used, and a list of those references can be assigned to the dmark pointer instead of a function callback, on the rb_data_type_struct. Macros are also provided for simple declaration of the reference list, and building edges. To avoid having to also find space in the struct to define a length for the references list, I've chosed to always terminate the references list with RUBY_REF_END - defined as UINTPTR_MAX. My assumption is that no single struct will ever be large enough that UINTPTR_MAX is actually a valid reference.
c7b9830
to
34dff0f
Compare
#define REF_EDGE(s, p) (offsetof(struct s, p)) | ||
#define REFS_LIST_PTR(l) ((RUBY_DATA_FUNC)l) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why these are not RUBY_
prefixed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi
#define RUBY_REFERENCES_START(t) static size_t t[] = { | ||
#define RUBY_REFERENCES_END RUBY_REF_END, }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hiding braces inside macros make editors confused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi
When using rb_data_type_struct to wrap a C struct, that C struct can
contain VALUE references to other Ruby objects.
If this is the case then one must also define dmark and optionally
dcompact callbacks in order to allow these objects to be correctly
handled by the GC. This is suboptimal as it requires GC related logic to
be implemented by extension developers. This can be a cause of subtle
bugs when references are not marked of updated correctly inside these
callbacks.
This commit provides an alternative approach, useful in the simple case
where the C struct contains VALUE members (ie. there isn't any
conditional logic, or data structure manipulation required to traverse
these references).
In this case references can be defined using a declarative syntax
as a list of edges (or, pointers to references).
A flag can be set on the rb_data_type_struct to notify the GC that
declarative references are being used, and a list of those references
can be assigned to the arbitrary data pointer on the
rb_data_type_struct.
Macros are also provided for simple declaration of the reference list,
and building edges.
To avoid having to also find space in the struct to define a length for
the references list, I've chosed to always terminate the references list
with RUBY_REF_END - defined as UINTPTR_MAX. My assumption is that no
single struct will ever be large enough that UINTPTR_MAX is actually a
valid reference.
This PR also provides example implementations for
dir_data
andenumerator
TODO (Post merge)