aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2020-09-25 14:06:32 +0900
committerKoichi Sasada <ko1@atdot.net>2020-09-25 16:00:13 +0900
commit96739c422206d55acab4aee917d9d965c27b6fff (patch)
treeb8163686b8f90a1776deb778be37680ff84d9614
parent97416ae54cebe8bd4c77da5301b82509ec43aaf2 (diff)
downloadruby-96739c422206d55acab4aee917d9d965c27b6fff.tar.gz
Frozen Struct can be shareable.
A frozen Struct object which refers to shareable objects should be shareable.
-rw-r--r--bootstraptest/test_ractor.rb6
-rw-r--r--ractor.c30
2 files changed, 36 insertions, 0 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index f06513a784..5ed8f63958 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -427,6 +427,7 @@ assert_equal "ok", %q{
class C; end
module M; end
+ S = Struct.new(:a, :b, :c, :d)
shareable_objects = [
true,
@@ -445,6 +446,8 @@ assert_equal "ok", %q{
[1, 2].freeze, # frozen Array which only refers to shareable
{a: 1}.freeze, # frozen Hash which only refers to shareable
[{a: 1}.freeze, 'str'.freeze].freeze, # nested frozen container
+ S.new(1, 2).freeze, # frozen Struct
+ S.new(1, 2, 3, 4).freeze, # frozen Struct
C, # class
M, # module
Ractor.current, # Ractor
@@ -454,6 +457,9 @@ assert_equal "ok", %q{
'mutable str'.dup,
[:array],
{hash: true},
+ S.new(1, 2),
+ S.new(1, 2, 3, 4),
+ S.new("a", 2).freeze, # frozen, but refers to an unshareable object
]
results = []
diff --git a/ractor.c b/ractor.c
index 382d3d5199..6ef294d135 100644
--- a/ractor.c
+++ b/ractor.c
@@ -7,6 +7,7 @@
#include "vm_sync.h"
#include "ractor.h"
#include "internal/error.h"
+#include "internal/struct.h"
static VALUE rb_cRactor;
static VALUE rb_eRactorError;
@@ -1785,6 +1786,22 @@ rb_ractor_shareable_p_hash_i(VALUE key, VALUE value, VALUE arg)
}
static bool
+ractor_struct_shareable_members_p(VALUE obj)
+{
+ VM_ASSERT(RB_TYPE_P(obj, T_STRUCT));
+
+ long len = RSTRUCT_LEN(obj);
+ const VALUE *ptr = RSTRUCT_CONST_PTR(obj);
+
+ for (long i=0; i<len; i++) {
+ if (!rb_ractor_shareable_p(ptr[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool
ractor_obj_ivars_shareable_p(VALUE obj)
{
uint32_t len = ROBJECT_NUMIV(obj);
@@ -1850,6 +1867,19 @@ rb_ractor_shareable_p_continue(VALUE obj)
return false;
}
}
+ case T_STRUCT:
+ if (!RB_OBJ_FROZEN_RAW(obj) ||
+ FL_TEST_RAW(obj, RUBY_FL_EXIVAR)) {
+ return false;
+ }
+ else {
+ if (ractor_struct_shareable_members_p(obj)) {
+ goto shareable;
+ }
+ else {
+ return false;
+ }
+ }
case T_OBJECT:
if (RB_OBJ_FROZEN_RAW(obj) && ractor_obj_ivars_shareable_p(obj)) {
goto shareable;