J'ai essayé de faire fonctionner le code suivant avec Ractor.
r = Ractor.new do
v1, v2 = Ractor.recv
puts v1
puts v2
puts v1.class
puts v2.class
end
r.send(1, 2)
r.take
# => 1
# => 2
# => Integer
# => Integer
C'est un mécanisme pour fournir des fonctions parallèles / parallèles introduit dans Ruby3. Initialement nommée Guild, elle est discutée depuis plusieurs années.
Pour plus de détails, veuillez vous référer à la vidéo ci-dessous.
[JA] Ractor report / Koichi Sasada @ko1
Vous pouvez transmettre un objet à Ractor en utilisant la méthode send
.
r = Ractor.new do
v = Ractor.recv
puts v
puts v.class
end
r.send(1)
r.take
# => 1
# => Integer
Cependant, vous ne pouvez pas transmettre plusieurs objets comme indiqué ci-dessous.
r = Ractor.new do
v1, v2 = Ractor.recv
puts v1
puts v2
puts v1.class
puts v2.class
end
r.send(1, 2)
r.take
# =>wrong number of arguments (given 2, expected 1) (ArgumentError)
Cependant, il semble correct de le transmettre en tant que tableau.
r = Ractor.new do
v1, v2 = Ractor.recv
puts v1
puts v2
puts v1.class
puts v2.class
end
r.send([1, 2])
r.take
# => 1
# => 2
# => Integer
# => Integer
En regardant l'implémentation, cela ressemble à ceci (dans ractor.rb
dans le code source de CRuby)
La méthode send
actuelle ne prend qu'un seul objet comme argument. Vous pouvez également spécifier si vous souhaitez déplacer ou non avec l'argument de mot-clé move
.
def send obj, move: false
__builtin_cexpr! %q{
ractor_send(ec, RACTOR_PTR(self), obj, move)
}
end
La fonction C est appelée avec __builtin_cexpr!
, Et l'argument reçu par la méthode est passé à la fonction C tel quel. En passant, CRuby récent vous permet d'écrire du code qui transmet des variables Ruby aux fonctions C en tant qu'implémentation interne.
J'ai réécrit la méthode «send» de Ractor comme suit.
def send obj, *arg, move: false
obj = arg.unshift obj unless arg.empty?
__builtin_cexpr! %q{
ractor_send(ec, RACTOR_PTR(self), obj, move)
}
end
Premièrement, la méthode send
prend toujours un objet comme argument. Les arguments sont réécrits comme «obj, * arg, move: false» pour maintenir ce comportement.
Si plusieurs objets sont passés comme send (1, 2)
, l'argument est passé sous forme de tableau à * arg
.
Si ʻarg n'est pas un tableau vide, alors plusieurs objets sont passés, convertissant ʻobj
, qui est finalement passé à la fonction C, en une fusion du premier et des arguments de longueur variable. Je vais.
Tout ce que vous avez à faire est de créer le code source CRuby modifié.
Vous pouvez désormais transmettre plusieurs objets à Ractor comme suit:
r = Ractor.new do
v1, v2 = Ractor.recv
puts v1
puts v2
puts v1.class
puts v2.class
end
r.send(1, 2)
r.take
# => 1
# => 2
# => Integer
# => Integer
ref: Guild → Ractor ref: https://github.com/ko1/ruby/blob/ractor/ractor.ja.md ref: [[JA Ractor report / Koichi Sasada @ko1
En passant, si vous voulez un patch monkey, vous pouvez créer une méthode encapsulée comme suit.
class Ractor
def multi_send(obj, *args, move: true)
obj = args.unshift obj unless args.empty?
send(obj, move: move)
end
end
r = Ractor.new do
v1, v2 = Ractor.recv
puts v1
puts v2
puts v1.class
puts v2.class
end
r.multi_send(1, 2)
r.take
Puisque la gamme de patchs de singe est large, il peut être préférable d'utiliser des raffinements
car ils ont moins d'effet si vous les utilisez en pratique.
module RefineRactor
refine Ractor do
def multi_send(obj, *args, move: true)
obj = args.unshift obj unless args.empty?
send(obj, move: move)
end
end
end
using RefineRactor
r = Ractor.new do
v1, v2 = Ractor.recv
puts v1
puts v2
puts v1.class
puts v2.class
end
r.multi_send(1, 2)
r.take
Recommended Posts