🎉
[Feature #21767] freeze されている proc を暗黙的に共有可能オブジェクトとして扱えるようにする提案
[Feature #21767] Consider procs which self is Ractor-shareable as Ractor shareable
-
Ractorでprocを参照する場合には通常Ractor.make_shareableで共有可能オブジェクトとして定義しておく必要がある
class C
ARRAY = [1, 2, 3].freeze
PROC = Ractor.make_shareable proc { ARRAY }
end
p Ractor.new { C::PROC.call }.value
# => [1, 2, 3]
- またこれは
procのselfが共有可能オブジェクトのときのみprocを共有可能オブジェクトとして扱える
ARRAY = [1, 2, 3].freeze
# self が共有可能オブジェクトでない場合はエラーになる
PROC = Ractor.make_shareable proc { ARRAY }
# => error: Proc's self is not shareable: #<Proc:0x0000751808c36500 test.rb:2> (Ractor::IsolationError)
- このチケットでは
Ractor.make_shareableで共有可能オブジェクト化するのではなくてprocがfreezeされている場合に『共有可能オブジェクトとして扱えるようにする』という提案になる
class C
ARRAY = [1, 2, 3].freeze
# Ractor.make_shareable ではなくて freeze されていれば共有可能オブジェクトとして許容する
PROC = proc { ARRAY }.freeze
end
# 現状はエラーになるがこれを許容する
p Ractor.new { C::PROC.call }.value
- 具体的には以下の条件に当てはまる場合には
procを共有可能オブジェクトとして扱えるようにする-
procがfrozenになっている -
procのselfが共有可能オブジェクトである
-
- また、以下のように
proc内で共有可能オブジェクトでないオブジェクトを参照し、それをRactorから呼び出した場合には対応前と対応後で以下のような『例外が発生するタイミング』が異なるみたいですね
class C
# 共有可能オブジェクトではない定数を proc で参照している
ARRAY = []
# 対応後は p ARRAY で例外が発生する
PROC = proc { p ARRAY }
end
# 現状では C::PROC.call で例外が発生する
Ractor.new { C::PROC.call }.value
- あとコメントで
Ractor.shareable_procと同じように『共有可能オブジェクトでない値を参照した場合』にエラーにする必要があると指摘されているんですがここでも非互換になる可能性があるみたですね - どういうことかというと以下のように
evalで外部の共有可能でないオブジェクトを参照している場合にprocを呼び出すとエラーになる
class Foo
a = "homu"
SOME_PROC = -> { eval "a" }.freeze
SOME_PROC_SHAREABLE = Ractor.shareable_proc(&SOME_PROC)
end
Foo::SOME_PROC_SHAREABLE.call
# => error: can not access variable 'a' from isolated Proc (SyntaxError)
- なので同様に
SOME_PROCが暗黙的に共有可能オブジェクトとして扱われSOME_PROC.callを呼び出すと同様にエラーになる可能性がある- これは
Ractorを使用していない場合でもエラーになってしまう
- これは
- このあたりの互換性をどこまで考慮すべきなのか、って話になりそうですがそもそも
procをfreezeしているケースは少ないだろうと言うことで無視していいんじゃないか、とも意見されてしますね
Discussion