“doc” (Col. : Science Sup 17x24) — 2007/7/19 — 18:18 — page 196 — #206
i
i
i
i
i
i
i
i
196
4
• La programmation concurrente dataflow
declare L in
thread {ForAll L Browse} end
Si L est non liée, l’exécution suspendra tout de suite. Nous pouvons lier L dans d’autres
fils :
declare L1 L2 in
thread L=1|L1 end
thread L1=2|3|L2 end
thread L2=4|nil end
Quel est le résultat final ? Est-ce différent du résultat de l’appel séquentiel {ForAll
[1 2 3 4] Browse} ? Quel est le comportement de ForAll dans un contexte
concurrent ?
Une fonction concurrente sur les listes
Voici une version concurrente de la fonction Map qui permet d’appliquer une fonction
F à chaque membre d’une liste Xs :
fun {Map Xs F}
case Xs of nil then nil
[] X|Xr then thread {F X} end|{Map Xr F} end
end
L’instruction thread est utilisée comme une expression. Explorons le comportement
de ce programme. Si nous exécutons l’instruction suivante :
declare F Xs Ys Zs
{Browse thread {Map Xs F} end}
un nouveau fil sera créé qui contient {Map Xs F}. Il suspend immédiatement dans
l’instruction case parce que Xs est non liée. Si nous exécutons les instructions
suivantes (sans declare !) :
Xs=1|2|Ys
fun {F X} X * X end
le fil principal traversera la liste, ce qui créera deux fils pour les deux premiers arguments de la liste, thread {F 1} end et thread {F 2} end, et ensuite il
suspendra de nouveau sur la queue Ys. Enfin, l’exécution de
Ys=3|Zs
Zs=nil
crée un troisième fil avec thread {F 3} end et termine le calcul du fil principal.
Les trois fils termineront, donnant la liste finale [1 4 9]. Remarquez que le résultat
est le même que celui de la fonction Map séquentielle, sauf qu’il pourra être obtenu de
façon incrémentale si l’entrée est incrémentale. La fonction Map séquentielle s’exécute
par lots : le calcul ne donne aucun résultat avant que l’entrée complète soit donnée,
c’est seulement ensuite qu’il donne le résultat complet.
i
i
i
i
i
i
i
i
196
4
• La programmation concurrente dataflow
declare L in
thread {ForAll L Browse} end
Si L est non liée, l’exécution suspendra tout de suite. Nous pouvons lier L dans d’autres
fils :
declare L1 L2 in
thread L=1|L1 end
thread L1=2|3|L2 end
thread L2=4|nil end
Quel est le résultat final ? Est-ce différent du résultat de l’appel séquentiel {ForAll
[1 2 3 4] Browse} ? Quel est le comportement de ForAll dans un contexte
concurrent ?
Une fonction concurrente sur les listes
Voici une version concurrente de la fonction Map qui permet d’appliquer une fonction
F à chaque membre d’une liste Xs :
fun {Map Xs F}
case Xs of nil then nil
[] X|Xr then thread {F X} end|{Map Xr F} end
end
L’instruction thread est utilisée comme une expression. Explorons le comportement
de ce programme. Si nous exécutons l’instruction suivante :
declare F Xs Ys Zs
{Browse thread {Map Xs F} end}
un nouveau fil sera créé qui contient {Map Xs F}. Il suspend immédiatement dans
l’instruction case parce que Xs est non liée. Si nous exécutons les instructions
suivantes (sans declare !) :
Xs=1|2|Ys
fun {F X} X * X end
le fil principal traversera la liste, ce qui créera deux fils pour les deux premiers arguments de la liste, thread {F 1} end et thread {F 2} end, et ensuite il
suspendra de nouveau sur la queue Ys. Enfin, l’exécution de
Ys=3|Zs
Zs=nil
crée un troisième fil avec thread {F 3} end et termine le calcul du fil principal.
Les trois fils termineront, donnant la liste finale [1 4 9]. Remarquez que le résultat
est le même que celui de la fonction Map séquentielle, sauf qu’il pourra être obtenu de
façon incrémentale si l’entrée est incrémentale. La fonction Map séquentielle s’exécute
par lots : le calcul ne donne aucun résultat avant que l’entrée complète soit donnée,
c’est seulement ensuite qu’il donne le résultat complet.
