LoriotPro Extended Edition Programmation en language LUA

Table des matières

HelpLUA

Cours d'instruction de Coroutines


Que sont les coroutines ?

Coroutines nous permettent d'exécuter plusieurs charge immédiatement. Ceci est fait d'une façon commandée en passant la main à chaque routine et l'attente jusqu'à ce que le courant indique de lui a fini. Nous pouvons réintroduire la routine pour continuer à un temps postérieur et en faisant ceci à plusieurs reprises nous réalisons multi-charger.

Multi-filetage

Chacun charge des courses dans un fil qui est séparé des autres fils. Ayant plusieurs charge le fonctionnement immédiatement s'appelle souvent multi-filetage. Puisqu'il y a plus d'un fil courant immédiatement notre application serait multi-fileté.

Il y a de différentes manières dont le multi-filetage peut être mis en application. Quelques systèmes assignent une quantité de temps fixe à chaque fil et enlèvent la commande quand le temps est en hausse, transmettant la commande au prochain fil etc... Ceci s'appelle multi-filetage de préemption. Dans ce cas-ci chacun des fils n'a pas besoin de s'inquiéter combien d'heure il occupe, il davantage est concerné par sa propre fonction.

Dans d'autres systèmes, un fil est concerné par combien de temps il prend. Le fil sait qu'il doit passer la main à d'autres fils de sorte qu'ils puissent fonctionner aussi bien. C'est s'appelle coopérative, ou multi-filetage de collaboration. Ici, tous les fils collaborent ensemble pour permettre à l'application de fonctionner correctement. C'est le type de multi-charger que les coroutines de Lua emploient.

Coroutines dans Lua ne sont pas des fils ou des processus de logiciel d'exploitation. Coroutines sont des blocs de code de Lua qui sont créés dans Lua, et ont leur propre écoulement de commande comme des fils. Seulement un coroutine fonctionne jamais à la fois, et il fonctionne jusqu'à ce qu'il active un autre coroutine, ou rapporte (des retours au coroutine qui l'a appelé). Coroutines sont une manière d'exprimer les fils de coopération multiples de la commande en manière commode et normale, mais ne s'exécutent pas en parallèle, et ne gagnent ainsi aucun avantage d'exécution de CPU's multiple. Cependant, depuis des coroutines commutez beaucoup plus rapidement que des fils de logiciel d'exploitation et n'exigez pas typiquement le complexe et les dispositifs de verrouillage parfois chers, employant des coroutines est en général plus rapide que le programme équivalent en utilisant de pleins fils d'OS.

Rendement

Afin coroutines multiples pour partager l'exécution qu'ils doivent cesser s'exécuter (après avoir effectué une quantité sensible de traitement) et passer la main à un autre fil. Cet acte de la soumission s'appelle rendement. Coroutines appellent explicitement une fonction de Lua coroutine.yield(), qui est semblable à employer return dans les fonctions. Ce qui différencie le rendement des retours de fonction est celui à un point postérieur que nous pouvons réintroduire le fil et continuer où nous avons cessé. Quand vous sortez une portée de fonction employant return la portée est détruit et nous ne pouvons pas la réintroduire, par exemple,

> foo(x) de fonction > > si x>3 alors 
l'extrémité vraie de retour -- nous pouvons sortir la fonction avant
que l'extrémité si besoin en est > > retour faux -- renvoyez une 
valeur à la fin de la fonction (facultative) > > extrémité > = 
foo(1) faux > = foo(100) -- point différent de sortie vrai

Utilisation simple

Pour créer un coroutine nous devons avoir la fonction qui le représente, par exemple,

> foo() de fonction > > print("foo", 1) > > 
coroutine.yield() > > print("foo", 2) > > extrémité >

Nous créons un coroutine en utilisant coroutine.create(fn) la fonction. Nous lui passons un point d'entrée pour le fil qui est une fonction de Lua. L'objet est retourné par Lua est un fil:

> les Co = coroutine.create(foo) -- créez un coroutine 
avec le foo comme entrée > = type(co) -- montrent le type fil de 
l'objet de "Co"

Nous pouvons découvrir quel état le fil est en employant coroutine.status() la fonction, par exemple,

> = coroutine.status(co) suspendu
L'état a suspendu des moyens que le fil est vivant, et car vous prévoiriez, ne faisant pas quelque chose. Notez que quand nous avons créé le fil il n'a pas commencé à s'exécuter. Pour commencer le fil nous employons coroutine.resume() la fonction. Lua entrera dans le fil et partira quand le fil rapporte.
> = coroutine.resume(co) foo 1 vrai
coroutine.resume() La fonction renvoie le statut d'erreur de l'appel de résumé. Le rendement reconnaît que nous avons écrit la fonction foo et avons puis sorti sans des erreurs. Est maintenant le peu intéressant. Avec une fonction nous ne pourrions pas continuer où nous avons cessé, mais avec des coroutines nous pouvons reprendre encore :
> = coroutine.resume(co) foo 2 vrai
Nous pouvons voir que nous avons exécuté la ligne après le rendement dedans foo et sommes encore retournés sans erreur. Cependant, si nous regardons le statut nous pouvons voir que nous avons sorti la fonction foo et le coroutine terminés.
> = coroutine.status(co) morts
Si nous essayons de reprendre encore une paire de valeurs est retournée : un drapeau d'erreur et un message d'erreur :
> = coroutine.resume(co) faux ne peut pas reprendre le 
coroutine mort
Une fois qu'un coroutine sort ou des retours comme une fonction il ne peut pas être repris.

Plus de détails

Ce qui suit est un exemple plus compliqué démontrant quelques dispositifs importants des coroutines.

> odd(x) de fonction > > print('A : impair ', x) > >
coroutine.yield(x) > > print('B : impair ', x) > > extrémité >
> even(x) de fonction > > print('C : même ', x) > > si 
extrémité de retour de x==2 puis x > > print('D : même ', x) 
> > l'extrémité > > Co = coroutine.create(> > la fonction (x) > > 
pour i=1, le x  > > si puis coroutine.yield(-1) l'extrémité i==3 > >
si puis extrémité d'autre d'odd(i) de l'even(i) math.mod(i, 2)==0 > 
> extrémité > > extrémité) > > compte = 1 > tandis que 
coroutine.status(co) le ~ = 'complètement ' > > compte du 
print('----') ; compte = count+1 > > errorfree, valeur = 
coroutine.resume(co, 5) > > print('E : errorfree, valeur, 
statuts, errorfree, valeur, coroutine.status(co)) > > extrémité 1 A 
: 1 E impair : l'errorfree, valeur, statut rectifient 1 
suspendu 2 B : 1 C impair : égalisez 2 E : 
l'errorfree, valeur, statut rectifient -1 suspendu 3 A : 3
impairs E : l'errorfree, valeur, statut rectifient 3 suspendus 4
B : 3 impairs C : égalisez 4 D : égalisez 4 A : 
5 impairs E : l'errorfree, valeur, statut rectifient 5 
suspendus 5 B : 5 impairs E : errorfree, valeur, zéro 
vrai de statut mort >

Fondamentalement nous avons for une boucle qui appelle deux fonctions : odd() quand elle rencontre un nombre impair et even() sur des chiffres pairs. Il peut être peu un difficile digérer le rendement ainsi nous étudierons les boucles externes, comptées près count, une par une. Des commentaires ont été ajoutés.

1 A : 1 impair -- rendement de l'odd() E : 
l'errorfree, valeur, statut rectifient 1 suspendu
Dans la boucle une nous appelons notre employer de coroutine coroutine.resume(co, 5). La première fois qu'il s'appelle nous écrivons for la boucle dans la fonction de coroutine. Notez que la fonction odd(), qui s'appelle par nos rendements de fonction de coroutine. Vous ne devez pas rapporter dans la fonction de coroutine. C'est un dispositif important et utile. Nous renvoyons la valeur de 1 avec le rendement.

2 B : 1 impair -- résumé dans impair avec les 
valeurs que nous avons laissées sur le rendement C : même 2 --
appel égal et sortie pr3maturément E : l'errorfree, valeur, 
statut rectifient -1 suspendu -- rendement dedans pour la boucle
Dans la boucle 2, la boucle for principale rapporte et suspend le coroutine. Le point à la note ici est que nous pouvons rapporter n'importe où. Nous ne devons pas maintenir rapporter d'un point dans notre coroutine. Nous renvoyons -1 avec le rendement.

3 A : 3 impairs -- l'odd() rapporte encore après 
avoir repris dedans pour la boucle E : l'errorfree, valeur, 
statut rectifient 3 suspendus
Nous reprenons le coroutine dans for la boucle et quand odd() s'appelle elle rapporte encore.

4 B : 3 impairs -- le résumé dans l'odd(), des 
valeurs variables a maintenu C : égalisez 4 -- même le 
called() D : même 4 -- aucun retour dans l'even() cette fois A 
: 5 impairs -- odd() appelé et un rendement E : 
l'errorfree, valeur, statut rectifient 5 suspendus
Dans la boucle 4, nous reprenons dedans odd() où nous avons cessé. Notez que les valeurs variables sont préservées. La portée odd() de la fonction est préservée pendant un coroutine suspendent. Nous traversons à la fin de even(), cette fois sortant à la fin de la fonction. Dans l'un ou l'autre cas, quand nous sortons une fonction sans employer coroutine.yield(), la portée et toutes ses variables sont détruites. Seulement sur un rendement pouvons nous reprenons.

5 B : 5 impairs -- encore appelé E impair : 
errorfree, valeur, zéro vrai de statut mort -- pour la boucle 
se termine >

De nouveau nous reprenons dedans odd(). Cette fois la boucle for principale atteint la limite de 5 que nous avons passés dans le coroutine. La valeur de 5 et for l'état de boucle ont été préservés dans toute l'exécution du coroutine. Un coroutine préserve sa propres pile et état tandis que dans l'existance. Quand nous sortons notre fonction de coroutine qu'il meurt et nous pouvons plus ne l'employer.

 



LUTEUS www.loriotpro.com