diff options
Diffstat (limited to 'ext/ffi_c/Type.c')
-rw-r--r-- | ext/ffi_c/Type.c | 140 |
1 files changed, 104 insertions, 36 deletions
diff --git a/ext/ffi_c/Type.c b/ext/ffi_c/Type.c index 7776bb0..a94c009 100644 --- a/ext/ffi_c/Type.c +++ b/ext/ffi_c/Type.c @@ -14,7 +14,7 @@ * * Neither the name of the Ruby FFI project nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -33,36 +33,74 @@ #include <sys/types.h> #include <ruby.h> +#if HAVE_RB_EXT_RACTOR_SAFE +#include <ruby/ractor.h> +#endif #include <ffi.h> #include "rbffi.h" #include "compat.h" #include "Types.h" #include "Type.h" +static size_t type_memsize(const void *); typedef struct BuiltinType_ { Type type; - char* name; + const char* name; } BuiltinType; -static void builtin_type_free(BuiltinType *); +static size_t builtin_type_memsize(const void *); VALUE rbffi_TypeClass = Qnil; static VALUE classBuiltinType = Qnil; static VALUE moduleNativeType = Qnil; -static VALUE typeMap = Qnil, sizeMap = Qnil; -static ID id_find_type = 0, id_type_size = 0, id_size = 0; +static VALUE typeMap = Qnil; +static ID id_type_size = 0, id_size = 0; +#if HAVE_RB_EXT_RACTOR_SAFE +static rb_ractor_local_key_t custom_typedefs_key; +#endif + +const rb_data_type_t rbffi_type_data_type = { /* extern */ + .wrap_struct_name = "FFI::Type", + .function = { + .dmark = NULL, + .dfree = RUBY_TYPED_DEFAULT_FREE, + .dsize = type_memsize, + }, + // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() + // macro to update VALUE references, as to trigger write barriers. + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | FFI_RUBY_TYPED_FROZEN_SHAREABLE +}; + +static const rb_data_type_t builtin_type_data_type = { + .wrap_struct_name = "FFI::Type::Builtin", + .function = { + .dmark = NULL, + .dfree = RUBY_TYPED_DEFAULT_FREE, + .dsize = builtin_type_memsize, + }, + .parent = &rbffi_type_data_type, + // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE() + // macro to update VALUE references, as to trigger write barriers. + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | FFI_RUBY_TYPED_FROZEN_SHAREABLE +}; + +static size_t +type_memsize(const void *data) +{ + return sizeof(Type); +} static VALUE type_allocate(VALUE klass) { Type* type; - VALUE obj = Data_Make_Struct(klass, Type, NULL, -1, type); + VALUE obj = TypedData_Make_Struct(klass, Type, &rbffi_type_data_type, type); type->nativeType = -1; type->ffiType = &ffi_type_void; - + return obj; } @@ -78,18 +116,20 @@ type_initialize(VALUE self, VALUE value) Type* type; Type* other; - Data_Get_Struct(self, Type, type); + TypedData_Get_Struct(self, Type, &rbffi_type_data_type, type); if (FIXNUM_P(value)) { type->nativeType = FIX2INT(value); } else if (rb_obj_is_kind_of(value, rbffi_TypeClass)) { - Data_Get_Struct(value, Type, other); + TypedData_Get_Struct(value, Type, &rbffi_type_data_type, other); type->nativeType = other->nativeType; type->ffiType = other->ffiType; } else { rb_raise(rb_eArgError, "wrong type"); } - + + rb_obj_freeze(self); + return self; } @@ -103,7 +143,7 @@ type_size(VALUE self) { Type *type; - Data_Get_Struct(self, Type, type); + TypedData_Get_Struct(self, Type, &rbffi_type_data_type, type); return INT2FIX(type->ffiType->size); } @@ -118,7 +158,7 @@ type_alignment(VALUE self) { Type *type; - Data_Get_Struct(self, Type, type); + TypedData_Get_Struct(self, Type, &rbffi_type_data_type, type); return INT2FIX(type->ffiType->alignment); } @@ -134,9 +174,9 @@ type_inspect(VALUE self) char buf[100]; Type *type; - Data_Get_Struct(self, Type, type); + TypedData_Get_Struct(self, Type, &rbffi_type_data_type, type); - snprintf(buf, sizeof(buf), "#<%s:%p size=%d alignment=%d>", + snprintf(buf, sizeof(buf), "#<%s::%p size=%d alignment=%d>", rb_obj_classname(self), type, (int) type->ffiType->size, (int) type->ffiType->alignment); return rb_str_new2(buf); @@ -148,20 +188,21 @@ builtin_type_new(VALUE klass, int nativeType, ffi_type* ffiType, const char* nam BuiltinType* type; VALUE obj = Qnil; - obj = Data_Make_Struct(klass, BuiltinType, NULL, builtin_type_free, type); - - type->name = strdup(name); + obj = TypedData_Make_Struct(klass, BuiltinType, &builtin_type_data_type, type); + + type->name = name; type->type.nativeType = nativeType; type->type.ffiType = ffiType; + rb_obj_freeze(obj); + return obj; } -static void -builtin_type_free(BuiltinType *type) +static size_t +builtin_type_memsize(const void *data) { - free(type->name); - xfree(type); + return sizeof(BuiltinType) + sizeof(ffi_type); } /* @@ -175,8 +216,8 @@ builtin_type_inspect(VALUE self) char buf[100]; BuiltinType *type; - Data_Get_Struct(self, BuiltinType, type); - snprintf(buf, sizeof(buf), "#<%s:%s size=%d alignment=%d>", + TypedData_Get_Struct(self, BuiltinType, &builtin_type_data_type, type); + snprintf(buf, sizeof(buf), "#<%s::%s size=%d alignment=%d>", rb_obj_classname(self), type->name, (int) type->type.ffiType->size, type->type.ffiType->alignment); return rb_str_new2(buf); @@ -186,21 +227,21 @@ int rbffi_type_size(VALUE type) { int t = TYPE(type); - + if (t == T_FIXNUM || t == T_BIGNUM) { return NUM2INT(type); - + } else if (t == T_SYMBOL) { /* - * Try looking up directly in the type and size maps + * Try looking up directly in the type map */ VALUE nType; if ((nType = rb_hash_lookup(typeMap, type)) != Qnil) { if (rb_obj_is_kind_of(nType, rbffi_TypeClass)) { Type* type; - Data_Get_Struct(nType, Type, type); + TypedData_Get_Struct(nType, Type, &rbffi_type_data_type, type); return (int) type->ffiType->size; - + } else if (rb_respond_to(nType, id_size)) { return NUM2INT(rb_funcall2(nType, id_size, 0, NULL)); } @@ -208,26 +249,51 @@ rbffi_type_size(VALUE type) /* Not found - call up to the ruby version to resolve */ return NUM2INT(rb_funcall2(rbffi_FFIModule, id_type_size, 1, &type)); - + } else { return NUM2INT(rb_funcall2(type, id_size, 0, NULL)); } } +static VALUE +custom_typedefs(VALUE self) +{ +#if HAVE_RB_EXT_RACTOR_SAFE + VALUE hash = rb_ractor_local_storage_value(custom_typedefs_key); + if (hash == Qnil) { + hash = rb_hash_new(); + rb_ractor_local_storage_value_set(custom_typedefs_key, hash); + } +#else + static VALUE hash = Qundef; + if (hash == Qundef) { + rb_global_variable(&hash); + hash = rb_hash_new(); + } +#endif + return hash; +} + VALUE rbffi_Type_Lookup(VALUE name) { int t = TYPE(name); if (t == T_SYMBOL || t == T_STRING) { /* - * Try looking up directly in the type Map + * Try looking up directly in the type map */ VALUE nType; + VALUE cust = custom_typedefs(Qnil); + + if ((nType = rb_hash_lookup(cust, name)) != Qnil && rb_obj_is_kind_of(nType, rbffi_TypeClass)) { + return nType; + } + if ((nType = rb_hash_lookup(typeMap, name)) != Qnil && rb_obj_is_kind_of(nType, rbffi_TypeClass)) { return nType; } } else if (rb_obj_is_kind_of(name, rbffi_TypeClass)) { - + return name; } @@ -251,13 +317,15 @@ rbffi_Type_Init(VALUE moduleFFI) * Document-constant: FFI::TypeDefs */ rb_define_const(moduleFFI, "TypeDefs", typeMap = rb_hash_new()); - rb_define_const(moduleFFI, "SizeTypes", sizeMap = rb_hash_new()); rb_global_variable(&typeMap); - rb_global_variable(&sizeMap); - id_find_type = rb_intern("find_type"); id_type_size = rb_intern("type_size"); id_size = rb_intern("size"); +#if HAVE_RB_EXT_RACTOR_SAFE + custom_typedefs_key = rb_ractor_local_storage_value_newkey(); +#endif + rb_define_module_function(moduleFFI, "custom_typedefs", custom_typedefs, 0); + /* * Document-class: FFI::Type::Builtin * Class for Built-in types. @@ -297,7 +365,7 @@ rbffi_Type_Init(VALUE moduleFFI) * * BUFFER_OUT * * VARARGS (function takes a variable number of arguments) * - * All these constants are exported to {FFI} module prefixed with "TYPE_". + * All these constants are exported to {FFI} module prefixed with "TYPE_". * They are objets from {FFI::Type::Builtin} class. */ moduleNativeType = rb_define_module_under(moduleFFI, "NativeType"); @@ -318,7 +386,7 @@ rbffi_Type_Init(VALUE moduleFFI) /* Make Type::Builtin non-allocatable */ rb_undef_method(CLASS_OF(classBuiltinType), "new"); rb_define_method(classBuiltinType, "inspect", builtin_type_inspect, 0); - + rb_global_variable(&rbffi_TypeClass); rb_global_variable(&classBuiltinType); |