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