La raison principale est que le concept réel de coroutine n’existe pas tout à fait en Lua. En effet, les coroutines en Lua sont monothread, autrement dit asymétriques.
Contrairement aux threads traditionnels, qui permettent une exécution parallèle, les coroutines en Lua fonctionnent dans un seul thread et exigent une gestion explicite du passage de contrôle. Cela signifie qu’une coroutine ne reprend son exécution que lorsqu’elle est explicitement réactivée par l’appelant via coroutine.resume()
. Inversement, une coroutine suspend son exécution volontairement en appelant coroutine.yield()
.
L’utilisation des coroutines repose donc sur une stratégie bien définie pour organiser la coopération entre différentes parties du programme. Par exemple, elles sont souvent employées pour :
- Implémenter des itérateurs
- Mettre en place des systèmes de gestion d’événements
- Créer des mécanismes de planification de tâches non bloquantes style une requête web asynchrone
Une bonne stratégie d’utilisation des coroutines en Lua implique de structurer son code de manière à minimiser les points de blocage et à garantir une reprise fluide de l’exécution. Par exemple, dans un jeu vidéo, les coroutines peuvent être utilisées pour gérer :
- Des animations
- Des comportements d’intelligence artificielle
Cela permet d’éviter de bloquer le fil principal d’exécution.
Bien que Lua n’offre pas de multitraitement natif, il est possible de combiner les coroutines avec des bibliothèques externes ou des threads en C pour simuler une exécution concurrente. Cependant, cela demande une gestion soigneuse des ressources partagées et une coordination efficace entre les différents processus en cours d’exécution.
La bibliothèque coroutine
permet de créer, démarrer et suivre des routines dans le cadre de la gestion de l’exécution concurrente en Lua.
Cette fonction permet de créer une routine à partir d’une fonction.
Une routine représente une séquence d’exécution qui peut être mise en pause et reprise.
function
: Une fonction Lua qui contient le code à exécuter dans la routine.
- Retourne un objet
Routine
qui représente la routine créée.
local routine = coroutine.create(function()
print("Cette routine est exécutée !")
end)
Cette fonction permet d’executé une routine
routine
: la routine à exécuterargs
: un ensemble d’argument associer à la fonction dans laroutine
ou des données injecter dans lapause
précédent
- Succès d’éxécution de la
routine
- Message d’erreur de la
routine
(falcultatif) args
un ensemble d’argument associer aux des données injecter dans lapause
précédent (falcultatif)
local routine = coroutine.create(function(qui,message)
print(qui,message)
end)
Coroutine.resume(routine,"Yoda","Bonjour maître Yoda")
Yoda Bonjour maître Yoda
local routine = coroutine.create(function(qui,message)
print(qui,message)
end)
coroutine.resume(routine,"Yoda","Bonjour maître Yoda")
local estBienExecuter, messageErreur = coroutine.resume(routine)
print(estBienExecuter, messageErreur)
Yoda Bonjour maître Yoda
false cannot resume dead coroutine
Permet d’obtenir le status de la Routine
suspended
: la routine est disponible, mais non utilisérunning
: la routine est en cours d’exécutionnormal
: lorsque la routine est lancer par une autredead
: la routine est morte
Routine
: la routine à exécuter
- Status :
suspended
,running
oudead
local status = {
avant = nil,
pendant = nil,
apres = nil
}
local routine, bienvenue
bienvenue = function(nom)
print("Bonjour",nom)
status.pendant = coroutine.status(routine)
end
routine = coroutine.create(bienvenue)
status.avant = coroutine.status(routine)
coroutine.resume(routine,"Léo")
status.apres = coroutine.status(routine)
for etape,etat in pairs(status) do print(etape,etat) end
Bonjour Léo
avant suspended
pendant running
apres dead
Permet de mettre en pause une routine pour son prochain apelle.
Permet l'échapement
et l'injection
de données vers une Routine
args
: un ensemble d’argument associer à la fonction dans les pareméetre de yield
pour l'éhcapement
et comme assignation pour l'injection
(falcultatif)w
args
: un ensemble d’argument associer à la fonction dans les pareméetre de yield
pour l'éhcapement
(falcultatif)
pause
de la routine
pour savoir le nombre de coroutine.resume
à faire. compter le nombre de coroutine.yield + 1
dans votre fonction.
local routine = coroutine.create(function()
coroutine.yield("données échaper")
end)
local estExecuter, donneExtrapoler = coroutine.resume(routine)
print(donneExtrapoler)
données échaper
local routine = coroutine.create(function()
local x = coroutine.yield()
print(x)
end)
coroutine.resume(routine)
coroutine.resume(routine,"Données injecter")
Données injecter
Permet de créer une fonction avec un comportement de routine sans être une routine
Fonction
: la fonction avec lespause
args
un ensemble d’argument associer aux des données injecter dans lapause
précédent (falcultatif)
routine = coroutine.wrap(function()
print("Étape 1")
local reponse = coroutine.yield("Bonjour maître Yoda")
print("Étape 2 - "..reponse)
coroutine.yield()
print("Étape 3")
end)
local data = routine()
print(data)
routine("Bonjour Luc")
routine()
Étape 1
Bonjour maître Yoda
Étape 2 - Bonjour Luc
Étape 3
permet de tuer votre routine
Routine
: la routine à tuer
boolean
:true
si la routine existe
local routine = coroutine.create(function()
print("Dans la coroutine, c'est :",
coroutine.running()-- Affiche l'ID de la coroutine
)
end)
coroutine.close(routine)
print(coroutine.resume(routine))
false cannot resume dead coroutine
- Roberto Ierusalimschy, « 9.1 – Coroutine Basics », lua.org, https://www.lua.org/pil/9.1.html
- Inconnu, « Lua - Coroutines », www.tutorialspoint.com, https://www.tutorialspoint.com/lua/lua_coroutines.htm
- Sylvain Fabre et al., Le guide de lua et ses applications : Manuel d’apprentissage, D-Booker, 04/2016, pages 65-67.
Finnwinch my beloved ♥