diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c index 7aa94076..d526d870 100644 --- a/ext/fiddle/closure.c +++ b/ext/fiddle/closure.c @@ -61,7 +61,7 @@ const rb_data_type_t closure_data_type = { .dfree = dealloc, .dsize = closure_memsize }, - .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, + .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS, }; struct callback_args { @@ -300,6 +300,7 @@ initialize_body(VALUE user_data) cl->argv[i] = rb_fiddle_int_to_ffi_type(NUM2INT(arg)); } cl->argv[argc] = NULL; + OBJ_FREEZE_RAW(normalized_args); ret = rb_fiddle_type_ensure(ret); rb_iv_set(data->self, "@ctype", ret); diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb index a4a7e7e1..28999806 100644 --- a/ext/fiddle/extconf.rb +++ b/ext/fiddle/extconf.rb @@ -223,6 +223,8 @@ def enable_debug_build_flag(flags) $LOCAL_LIBS.prepend("#{libffi.a} ").strip! # to exts.mk $INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)') end + +have_func("rb_str_to_interned_str") create_makefile 'fiddle' do |conf| if !libffi next conf << "LIBFFI_CLEAN = none\n" diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h index 54391b95..c0ab8a91 100644 --- a/ext/fiddle/fiddle.h +++ b/ext/fiddle/fiddle.h @@ -236,4 +236,14 @@ VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type); typedef void (*rb_fiddle_freefunc_t)(void*); VALUE rb_fiddle_ptr_new_wrap(void *ptr, long size, rb_fiddle_freefunc_t func, VALUE wrap0, VALUE wrap1); +enum { + FIDDLE_DEFAULT_TYPED_DATA_FLAGS = ( + RUBY_TYPED_FREE_IMMEDIATELY | + RUBY_TYPED_WB_PROTECTED | +#ifdef RUBY_TYPED_FROZEN_SHAREABLE + RUBY_TYPED_FROZEN_SHAREABLE | +#endif + 0) +}; + #endif diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c index 73dfb129..21a7ad6d 100644 --- a/ext/fiddle/function.c +++ b/ext/fiddle/function.c @@ -59,7 +59,7 @@ const rb_data_type_t function_data_type = { .dfree = deallocate, .dsize = function_memsize }, - .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, + .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS, }; static VALUE @@ -153,6 +153,9 @@ initialize(int argc, VALUE argv[], VALUE self) rb_get_kwargs(kwargs, kw, 0, kw_max_, args); if (args[kw_name] != Qundef) { name = args[kw_name]; +#ifdef HAVE_RB_STR_TO_INTERNED_STR + name = rb_str_to_interned_str(name); +#endif } if (args[kw_need_gvl] != Qundef) { need_gvl = args[kw_need_gvl]; diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c index 558d6d45..0d03133c 100644 --- a/ext/fiddle/handle.c +++ b/ext/fiddle/handle.c @@ -56,7 +56,8 @@ static const rb_data_type_t fiddle_handle_data_type = { .dfree = fiddle_handle_free, .dsize = fiddle_handle_memsize }, - .flags = RUBY_TYPED_WB_PROTECTED, + .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS & ~RUBY_TYPED_FREE_IMMEDIATELY, + /* keeping while its symbols are referred. */ }; /* diff --git a/ext/fiddle/memory_view.c b/ext/fiddle/memory_view.c index fa66fc2c..5fd7b9b4 100644 --- a/ext/fiddle/memory_view.c +++ b/ext/fiddle/memory_view.c @@ -64,8 +64,13 @@ fiddle_memview_memsize(const void *ptr) } static const rb_data_type_t fiddle_memview_data_type = { - "fiddle/memory_view", - {fiddle_memview_mark, fiddle_memview_free, fiddle_memview_memsize,}, + .wrap_struct_name = "fiddle/memory_view", + .function = { + .dmark = fiddle_memview_mark, + .dfree = fiddle_memview_free, + .dsize = fiddle_memview_memsize, + }, + .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS, }; static VALUE diff --git a/ext/fiddle/pinned.c b/ext/fiddle/pinned.c index 019a3020..94962b0f 100644 --- a/ext/fiddle/pinned.c +++ b/ext/fiddle/pinned.c @@ -24,9 +24,13 @@ pinned_memsize(const void *ptr) } static const rb_data_type_t pinned_data_type = { - "fiddle/pinned", - {pinned_mark, xfree, pinned_memsize, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED + .wrap_struct_name = "fiddle/pinned", + .function = { + .dmark = pinned_mark, + .dfree = RUBY_TYPED_DEFAULT_FREE, + .dsize = pinned_memsize, + }, + .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS, }; static VALUE diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c index 5c375fe9..00bd76e9 100644 --- a/ext/fiddle/pointer.c +++ b/ext/fiddle/pointer.c @@ -94,7 +94,7 @@ static const rb_data_type_t fiddle_ptr_data_type = { .dfree = fiddle_ptr_free, .dsize = fiddle_ptr_memsize, }, - .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED + .flags = FIDDLE_DEFAULT_TYPED_DATA_FLAGS, }; #ifdef HAVE_RUBY_MEMORY_VIEW_H diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb index fdac53ed..457e02f5 100644 --- a/test/fiddle/helper.rb +++ b/test/fiddle/helper.rb @@ -193,5 +193,10 @@ def under_gc_stress ensure GC.stress = stress end + + def assert_ractor_shareable(object) + Ractor.make_shareable(object) + assert_operator(Ractor, :shareable?, object) + end end end diff --git a/test/fiddle/test_closure.rb b/test/fiddle/test_closure.rb index 12194190..26cff8e5 100644 --- a/test/fiddle/test_closure.rb +++ b/test/fiddle/test_closure.rb @@ -157,5 +157,17 @@ def call end end end + + def test_ractor_shareable + omit("Need Ractor") unless defined?(Ractor) + closure_class = Class.new(Closure) do + def call + 0 + end + end + closure_class.create(:int, [:void]) do |c| + assert_ractor_shareable(c) + end + end end end if defined?(Fiddle) diff --git a/test/fiddle/test_function.rb b/test/fiddle/test_function.rb index 2822723f..6ec40bee 100644 --- a/test/fiddle/test_function.rb +++ b/test/fiddle/test_function.rb @@ -259,6 +259,11 @@ def test_no_memory_leak end end + def test_ractor_shareable + omit("Need Ractor") unless defined?(Ractor) + assert_ractor_shareable(Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE)) + end + private def perror(m) diff --git a/test/fiddle/test_handle.rb b/test/fiddle/test_handle.rb index 2b555dac..e0ad17a9 100644 --- a/test/fiddle/test_handle.rb +++ b/test/fiddle/test_handle.rb @@ -226,5 +226,10 @@ def test_fallback_to_ansi assert_equal(ansi, k["GetFileAttributes"], "should fallback to ANSI version") end end + + def test_ractor_shareable + omit("Need Ractor") unless defined?(Ractor) + assert_ractor_shareable(Fiddle::Handle.new(LIBC_SO)) + end end end if defined?(Fiddle) diff --git a/test/fiddle/test_memory_view.rb b/test/fiddle/test_memory_view.rb index d44c42d2..da00d66c 100644 --- a/test/fiddle/test_memory_view.rb +++ b/test/fiddle/test_memory_view.rb @@ -159,5 +159,17 @@ def test_to_s mview.release end end + + def test_ractor_shareable + omit("Need Ractor") unless defined?(Ractor) + ptr = Pointer["hello world"] + mview = MemoryView.new(ptr) + begin + assert_ractor_shareable(mview) + assert_predicate(ptr, :frozen?) + ensure + mview.release + end + end end end diff --git a/test/fiddle/test_pinned.rb b/test/fiddle/test_pinned.rb index f0d375b1..ad132579 100644 --- a/test/fiddle/test_pinned.rb +++ b/test/fiddle/test_pinned.rb @@ -23,6 +23,12 @@ def test_clear end assert_match "called on", ex.message end + + def test_ractor_shareable + omit("Need Ractor") unless defined?(Ractor) + obj = Object.new + assert_ractor_shareable(Pinned.new(obj)) + assert_predicate(obj, :frozen?) + end end end - diff --git a/test/fiddle/test_pointer.rb b/test/fiddle/test_pointer.rb index fb83b867..d46fb662 100644 --- a/test/fiddle/test_pointer.rb +++ b/test/fiddle/test_pointer.rb @@ -305,5 +305,13 @@ def test_null_pointer assert_raise(DLError) {nullpo[0]} assert_raise(DLError) {nullpo[0] = 1} end + + def test_ractor_shareable + omit("Need Ractor") unless defined?(Ractor) + assert_ractor_shareable(Fiddle::NULL) + ary = [0, 1, 2, 4, 5] + addr = Pointer.new(dlwrap(ary)) + assert_ractor_shareable(addr) + end end end if defined?(Fiddle)