aboutsummaryrefslogtreecommitdiffstats
path: root/ractor.c
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2020-10-30 00:32:53 +0900
committerKoichi Sasada <ko1@atdot.net>2020-10-30 03:12:09 +0900
commit5d97bdc2dcb835c877010daa033cc2b1dfeb86d6 (patch)
tree147bbd2e687a9db2bbd5fede670690eae644ebe1 /ractor.c
parent502d6d845946f367ffb6e972e9c4ac401da94e99 (diff)
downloadruby-5d97bdc2dcb835c877010daa033cc2b1dfeb86d6.tar.gz
Ractor.make_shareable(a_proc)
Ractor.make_shareable() supports Proc object if (1) a Proc only read outer local variables (no assignments) (2) read outer local variables are shareable. Read local variables are stored in a snapshot, so after making shareable Proc, any assignments are not affeect like that: ```ruby a = 1 pr = Ractor.make_shareable(Proc.new{p a}) pr.call #=> 1 a = 2 pr.call #=> 1 # `a = 2` doesn't affect ``` [Feature #17284]
Diffstat (limited to 'ractor.c')
-rw-r--r--ractor.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/ractor.c b/ractor.c
index 272a4bc3b7..a89da04b33 100644
--- a/ractor.c
+++ b/ractor.c
@@ -21,6 +21,12 @@ static VALUE rb_eRactorMovedError;
static VALUE rb_eRactorClosedError;
static VALUE rb_cRactorMovedObject;
+VALUE
+rb_ractor_error_class(void)
+{
+ return rb_eRactorError;
+}
+
RUBY_SYMBOL_EXPORT_BEGIN
// to share with MJIT
bool ruby_multi_ractor;
@@ -2069,28 +2075,44 @@ rb_obj_traverse(VALUE obj,
}
static int
-frozen_shareable_p(VALUE obj)
+frozen_shareable_p(VALUE obj, bool *made_shareable)
{
- if (!RB_TYPE_P(obj, T_DATA) ||
- (RTYPEDDATA_P(obj) &&
- RTYPEDDATA_TYPE(obj)->flags & RUBY_TYPED_FROZEN_SHAREABLE)) {
+ if (!RB_TYPE_P(obj, T_DATA)) {
return true;
}
- else {
- return false;
+ else if (RTYPEDDATA_P(obj)) {
+ const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
+ if (type->flags & RUBY_TYPED_FROZEN_SHAREABLE) {
+ return true;
+ }
+ else if (made_shareable && rb_obj_is_proc(obj)) {
+ // special path to make shareable Proc.
+ rb_proc_ractor_make_shareable(obj);
+ *made_shareable = true;
+ VM_ASSERT(RB_OBJ_SHAREABLE_P(obj));
+ return false;
+ }
}
+
+ return false;
}
static enum obj_traverse_iterator_result
make_shareable_check_shareable(VALUE obj)
{
VM_ASSERT(!SPECIAL_CONST_P(obj));
+ bool made_shareable = false;
if (RB_OBJ_SHAREABLE_P(obj)) {
return traverse_skip;
}
- else if (!frozen_shareable_p(obj)) {
- rb_raise(rb_eRactorError, "can not make shareable object for %"PRIsVALUE, obj);
+ else if (!frozen_shareable_p(obj, &made_shareable)) {
+ if (made_shareable) {
+ return traverse_skip;
+ }
+ else {
+ rb_raise(rb_eRactorError, "can not make shareable object for %"PRIsVALUE, obj);
+ }
}
if (!RB_OBJ_FROZEN_RAW(obj)) {
@@ -2099,6 +2121,10 @@ make_shareable_check_shareable(VALUE obj)
if (UNLIKELY(!RB_OBJ_FROZEN_RAW(obj))) {
rb_raise(rb_eRactorError, "#freeze does not freeze object correctly");
}
+
+ if (RB_OBJ_SHAREABLE_P(obj)) {
+ return traverse_skip;
+ }
}
return traverse_cont;
@@ -2134,7 +2160,7 @@ shareable_p_enter(VALUE obj)
return traverse_skip;
}
else if (RB_OBJ_FROZEN_RAW(obj) &&
- frozen_shareable_p(obj)) {
+ frozen_shareable_p(obj, NULL)) {
return traverse_cont;
}