diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c index 2b4cdb66..35930815 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_FALGS, }; 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 2d85b3ee..14758237 100644 --- a/ext/fiddle/extconf.rb +++ b/ext/fiddle/extconf.rb @@ -218,6 +218,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 348baa9a..83ddc7b1 100644 --- a/ext/fiddle/fiddle.h +++ b/ext/fiddle/fiddle.h @@ -236,5 +236,15 @@ 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_FALGS = ( + RUBY_TYPED_FREE_IMMEDIATELY | + RUBY_TYPED_WB_PROTECTED | +#ifdef RUBY_TYPED_FROZEN_SHAREABLE + RUBY_TYPED_FROZEN_SHAREABLE | +#endif + 0) +}; + #endif /* vim: set noet sws=4 sw=4: */ diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c index 5469e09e..a8acddbe 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_FALGS, }; 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 8ba41695..808e44e2 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_FALGS & ~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..140c8efe 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_FALGS, }; static VALUE diff --git a/ext/fiddle/pinned.c b/ext/fiddle/pinned.c index 019a3020..fb03405a 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_FALGS, }; static VALUE diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c index 1b7d7a69..cc780be6 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_FALGS, }; #ifdef HAVE_RUBY_MEMORY_VIEW_H diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb index e470f5a2..cf4e41cf 100644 --- a/test/fiddle/helper.rb +++ b/test/fiddle/helper.rb @@ -180,5 +180,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 abb6bdbd..0adf02d9 100644 --- a/test/fiddle/test_closure.rb +++ b/test/fiddle/test_closure.rb @@ -149,5 +149,11 @@ def test_memsize_ruby_dev_42480 end end end + + ractor def test_ractor_shareable + Closure.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 847df379..9879a774 100644 --- a/test/fiddle/test_function.rb +++ b/test/fiddle/test_function.rb @@ -225,6 +225,10 @@ def test_no_memory_leak end end + ractor def test_ractor_shareable + 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 412c10e0..764f6069 100644 --- a/test/fiddle/test_handle.rb +++ b/test/fiddle/test_handle.rb @@ -214,5 +214,9 @@ def test_fallback_to_ansi assert_equal(ansi, k["GetFileAttributes"], "should fallback to ANSI version") end end + + ractor def test_ractor_shareable + 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 240cda37..bd45f405 100644 --- a/test/fiddle/test_memory_view.rb +++ b/test/fiddle/test_memory_view.rb @@ -139,5 +139,11 @@ def test_to_s assert_equal([data.b, true], [string, string.frozen?]) end + + ractor def test_ractor_shareable + ptr = Pointer["hello world"] + assert_ractor_shareable MemoryView.new(ptr) + assert_predicate ptr, :frozen? + end end end diff --git a/test/fiddle/test_pinned.rb b/test/fiddle/test_pinned.rb index f0d375b1..93deaf8c 100644 --- a/test/fiddle/test_pinned.rb +++ b/test/fiddle/test_pinned.rb @@ -23,6 +23,11 @@ def test_clear end assert_match "called on", ex.message end + + ractor def test_ractor_shareable + 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 f2c1d285..68197b41 100644 --- a/test/fiddle/test_pointer.rb +++ b/test/fiddle/test_pointer.rb @@ -302,5 +302,12 @@ def test_no_memory_leak assert_no_memory_leak(%w[-W0 -rfiddle.so], '', '100_000.times {Fiddle::Pointer.allocate}', rss: true) end end + + ractor def test_ractor_shareable + 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)