Feature #20627
open`require` on Ractor should run on the main Ractor
Description
Now require
on main Ractor is not allowed (raising error) but it is hard, especially for autoload
.
So let's allow require
by running it on the main Ractor.
Background¶
On many libraries it is needed to run loading on the main Ractors because:
- Setup constants with unshareable objects (such as
C = []
) are not allowed on non main Ractors. - Setup global variables and class variables are not allowed.
$LOADED_FEATURES
is also untouchable. - (maybe more reasons)
So the require
on non main Ractors is not allowed.
However it is hard to program especially on autoload
.
Also dynamic require
(require
in methods) are not allowed too (pp
method, for example).
Proposal¶
Allow require
on non main Ractors by running require
process on the main Ractor.
(quoted on my talk at RubyKaigi 2024)
rb_ractor_interrupt_exec(target_ractor, func)
C-API
Make a thread on target_ractor
and run func
(C function) on it.
I think it is safe to expose on Ruby API because running func
on a newly created thread (do not disturb running target threads). But now it is proposed as only (hidden) C-API.
New Ractor methods¶
-
Ractor.main?
returns Ractors -
Ractor.require(feature)
dorequire
on the main Ractor
These new methods are useful for users who override require
method like RubyGems.
alias orig_require require
def require feature
return Rator.require(feature) if defined?(Ractor.main?) && !Ractor.main?
# overriding require code
end
Or we can prepend a module like:
Module.new do
def require(feature)
return Rator.require(feature) if defined?(Ractor.main?) && !Ractor.main?
super(feature)
end
Kernel.prepend self
end
will support ractors for all overgrinding methods. But not sure it is acceptable to add additional one modules in ancestors by prepend
.
Also this technique doesn't support require overriding by prepending.
Implementation¶
https://github.com/ruby/ruby/pull/11142 (not matured yet)
Files