Implantation de méthodes asynchrones dans le langage de programmation Ruby.

Par Boris Béra et François Genois

Nous voulons implanter les méthodes asynchrones dans le langage de programmation Ruby. Cela va ajouter deux mots clés (async et sync). Une méthode peux être définie comme asynchrone avec le mot clé async. Quand celle ci va être appelée elle va s'exécuter dans un nouveau thread. Le mot clé sync peux être utilisé pour attendre après une méthode asynchrone.

Voici un example:

async def foo 
  # . . .
end 

async def bar
  # . . .
end

foo()  # roule en parallèle 
sync bar()  # attend que bar finisse

# . . .

Nous voulons utiliser Ruby, car la syntaxe est très flexible. Par exemple, un appel de méthode ne demande pas l'utilisation des parenthèses. Ceci nous permet de définir des méthodes en Ruby qui peuvent être utilisés comme des mots clés et qui donne l'impression de faire partie du langage.

Nous voulons ajouter un bloc qui permet de traiter plusieurs tâches asynchrones comme un groupe. Cela peux ce faire avec un nouveau mot clé (together). Ce bloc permet d'agir sur toutes les tâches dans un groupe. Une des propriétés de ce bloc serai d'attendre que toutes les tâches démarrés dans le bloc finissent avant de sortir. Dans les exemples qui suivent nous utilisons des blocs async. Ceux-ci sont identiques au méthodes async. Au lieu que toute la méthode soit roulé en parallèle, seulement le bloc est exécuté en parallèle.

Voici quelque exemples: (en semi pseudo-code)

# produit matriciel
a = . . . # matrice
b = . . . # matrice
c = . . . # matrice<

together do
  for i = 0 to n
    for j = 0 to m
      async { c[i][y] = scalar_prod(a.row(i), b.col(j)) }  #produit scalaire
    end
  end
end  # attend que tous les async ait fini

# Jacobi
current = . . . # matrice
next    = . . . # matrice
while(!good_epsilon)
  together do
    for i = 1 to n-1
      for j = 1 to m-1
        async { next[i][j] = jacobi_op(neighbors(i,j)) } #opération de jacobi sur une cellule
      end
    end
  end  # attend que toutes les opérations aient finies
  current = next
end

Nous voulons aussi ajouter des mots clés qui permettes de contrôler les tâches dans un même groupe. Un exemple serai le mot clé stop_all qui aurai pour but d'arrêter toutes les tâches dans le groupe.

Voici un exemple avec le crack de mots de passe:

target = ". . ."  # hash recerché
possible_passwords = [ . . . ]  # liste de tous les mots de passe possible (ce ne pas efficace, mais ça simplifie l'exemple)

together do
  for group in possible_passwords.split(n)  # divise les mots de passe en n groupes
    async do  # chaque groupe est traité en parallèle
      for password in group
        hash = hash(password) #calcule la hash du mod de passe
        if hash == target
          print password
          stop_all  #tue toutes les tâches
        end
      end
    end
  end
end

Le but des ces ajouts est de rendre la programmation parallèle plus simple et de réduire le nombre d'erreurs possibles qu'un programmeur peut faire.