ruby-changes:64308
From: Koichi <ko1@a...>
Date: Sat, 19 Dec 2020 05:55:28 +0900 (JST)
Subject: [ruby-changes:64308] 80cb9165fa (master): add "copy: true" option for Ractor.make_shareable
https://git.ruby-lang.org/ruby.git/commit/?id=80cb9165fa From 80cb9165fa34185b601970da407a295a78ec9eff Mon Sep 17 00:00:00 2001 From: Koichi Sasada <ko1@a...> Date: Sat, 19 Dec 2020 05:52:18 +0900 Subject: add "copy: true" option for Ractor.make_shareable Ractor.make_shareable(obj) tries to make obj a shareable object by changing the attribute of obj and traversable objects from obj (mainly freeze them). "copy: true" option is more conservative approach by make deep copied object and make it sharable. It doesn't affect any existing objects. diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index e81afb6..c587c2c 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -1176,6 +1176,22 @@ assert_equal 'can not make a Proc shareable because it accesses outer variables https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_ractor.rb#L1176 end } +# Ractor.make_shareable(obj, copy: true) makes copied shareable object. +assert_equal '[false, false, true, true]', %q{ + r = [] + o1 = [1, 2, ["3"]] + + o2 = Ractor.make_shareable(o1, copy: true) + r << Ractor.shareable?(o1) # false + r << (o1.object_id == o2.object_id) # false + + o3 = Ractor.make_shareable(o1) + r << Ractor.shareable?(o1) # true + r << (o1.object_id == o3.object_id) # false + r +} + + # Ractor deep copies frozen objects (ary) assert_equal '[true, false]', %q{ Ractor.new([[]].freeze) { |ary| diff --git a/ractor.c b/ractor.c index 89b4f68..0d850ae 100644 --- a/ractor.c +++ b/ractor.c @@ -2347,6 +2347,16 @@ rb_ractor_make_shareable(VALUE obj) https://github.com/ruby/ruby/blob/trunk/ractor.c#L2347 return obj; } +VALUE +rb_ractor_make_copy_shareable(VALUE obj) +{ + VALUE copy = ractor_copy(obj); + rb_obj_traverse(copy, + make_shareable_check_shareable, + null_leave, mark_shareable); + return copy; +} + static enum obj_traverse_iterator_result shareable_p_enter(VALUE obj) { diff --git a/ractor.rb b/ractor.rb index 2196a93..e4fbdfe 100644 --- a/ractor.rb +++ b/ractor.rb @@ -214,9 +214,28 @@ class Ractor https://github.com/ruby/ruby/blob/trunk/ractor.rb#L214 } end - def self.make_shareable obj - __builtin_cexpr! %q{ - rb_ractor_make_shareable(obj); - } + # make obj sharable. + # + # Basically, traverse referring objects from obj and freeze them. + # + # When a sharable object is found in traversing, stop traversing + # from this shareable object. + # + # If copy keyword is true, it makes a deep copied object + # and make it sharable. This is safer option (but it can take more time). + # + # Note that the specification and implementation of this method are not + # matured and can be changed in a future. + # + def self.make_shareable obj, copy: false + if copy + __builtin_cexpr! %q{ + rb_ractor_make_copy_shareable(obj); + } + else + __builtin_cexpr! %q{ + rb_ractor_make_shareable(obj); + } + end end end -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/