|
|
|
@ -2228,6 +2228,27 @@ static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) { |
|
|
|
|
VALUE args[3] = { c_only_cookie, _descriptor_pool, key }; |
|
|
|
|
def = rb_class_new_instance(3, args, klass); |
|
|
|
|
rb_hash_aset(descriptor_pool->def_to_descriptor, key, def); |
|
|
|
|
|
|
|
|
|
// For message defs, we now eagerly get/create descriptors for all
|
|
|
|
|
// submessages. We will need these anyway to parse or serialize this
|
|
|
|
|
// message type. But more importantly, we must do this now so that
|
|
|
|
|
// add_handlers_for_message() (which calls get_msgdef_obj()) does *not*
|
|
|
|
|
// need to create a Ruby object or insert into a Ruby Hash. We need to
|
|
|
|
|
// avoid triggering GC, which can switch Ruby threads and re-enter our
|
|
|
|
|
// C extension from a different thread. This wreaks havoc on our state
|
|
|
|
|
// if we were in the middle of building handlers.
|
|
|
|
|
if (klass == cDescriptor) { |
|
|
|
|
const upb_msgdef *m = ptr; |
|
|
|
|
upb_msg_field_iter it; |
|
|
|
|
for (upb_msg_field_begin(&it, m); |
|
|
|
|
!upb_msg_field_done(&it); |
|
|
|
|
upb_msg_field_next(&it)) { |
|
|
|
|
const upb_fielddef* f = upb_msg_iter_field(&it); |
|
|
|
|
if (upb_fielddef_issubmsg(f)) { |
|
|
|
|
get_msgdef_obj(_descriptor_pool, upb_fielddef_msgsubdef(f)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return def; |
|
|
|
|