Koprogram: Porovnání verzí

Přidáno 13 bajtů ,  před 4 lety
m
Robot: přidáno {{Autoritní data}}; kosmetické úpravy
značky: editace z mobilu editace z mobilního webu
m (Robot: přidáno {{Autoritní data}}; kosmetické úpravy)
Podprogram má pouze jeden vstupní bod (svůj začátek) a můžeme se z něj vrátit jen jednou. Naproti tomu koprogramy se mohou vracet několikrát (příkazem ''yield''). Začátek koprogramu je první vstupní bod a následující vstupní body označuje příkaz ''yield''. V praxi příkaz ''yield'' vrací výsledek a předává řízení do volajícího koprogramu podobně, jako u klasických podprogramů. Avšak při dalším volání koprogramu nezačne provádění na jeho začátku, ale následujícím příkazem za posledním provedeným příkazem ''yield''.
 
V následujícím příkladu si ukážeme, jak mohou být koprogramy užitečné. Předpokládejme, že máme vazbu producent-konzument, kde jedna rutina vytváří položky a přidává je do fronty a druhá odebírá položky z fronty a zpracovává je. Z úsporných důvodů chceme přidávat a odebírat několik položek najednou. Zápis programu by mohl vypadat takto:
 
''var'' q := new queue
Přestože je tento příklad obvykle uváděn jako úvod do [[multithreading]]u, není nutné, abychom kvůli tomu vytvářeli dva thready. Příkaz ''yield'' může být implementován jako přímý odskok z jedné rutiny do druhé.
 
== Srovnání s generátory ==
Generátory jsou také zobecněním podprogramů, ale jsou více limitovány než koprogramy. Oba přístupy umožňují více návratů, což zastaví jejich vykonávání s tím, že je možné později pokračovat ve vykonávání z více vstupních bodů. Liší se však v tom, že koprogramy mohou kontrolovat místo, ve kterém bude vykonávání programu pokračovat po zavolání ''yield''. Toto generátory nemohou ovlivnit, neboť pouze vrací kontrolu zpět na místo kde byly zavolány.<ref>Příklad ''[http://docs.python.org/reference/index.html The Python Language Reference]''
"http://docs.python.org/reference/expressions.html#yieldexpr 5.2.10. Yield expressions]":<br />
"All of this makes generator functions quite similar to coroutines; they yield multiple times, they have more than one entry point and their execution can be suspended. The only difference is that a generator function cannot control where should the execution continue after it yields; the control is always transferred to the generator's caller."</ref>
 
Nicméně je stále možné implementovat koprogramy za pomocí více generátorů s vrchní rozhodující funkcí, která předává kontrolu explicitně svým generátorům identifikovatelným pomocí tokenů, které jsou z nich předány zpět:
 
''var'' q := new queue
Používání koprogramů pro stavové stroje nebo souběžnost je podobné jako používání [[Rekurze|vzájemné rekurze]] s návratem. V obou případech řízení mění různé druhy úloh. Nicméně koprogramy jsou více flexibilní a obvykle výhodnější. Koprogramy jsou uzpůsobené spíše k obnovení provádění než k restartování, a proto jsou schopné udržet stav, obě proměnné (jako uzávěry), bod vykonávání a výsledky nemusí nutně být na konci kódu. Vzájemné rekurzivní podprogramy musí používat [[Proměnná (programování)|sdílené proměnné]], a nebo odesílat stav jako parametr. Předávání řízení mezi koprogramy probíhá pomocí existujícího kontextu a může být jednoduše implementováno jako instrukce skoku. 
 
== Častá použití ==
Koprogramy jsou užitečné při implementaci:
* [[Konečný automat|Stavových automatů]] v jediném podprogramu, kde stav je určen aktuálním vstupním/výstupním bodem procedury; takto může vzniknout více čitelný kód v porovnání s použitím [[goto]] a může být také implementován pomocí [[rekurze|vzájemné rekurze]] s [[koncová rekurze|koncovým voláním]].
* [[aktor|Aktorový model]] souběhu, například v [[počítačová hra|počítačových hrách]]. Každý aktor má své vlastní procedury (logicky odděluje kód), ale dobrovolně předává kontrolu hlavnímu plánovači, který je vykonává sekvenčně (určitá forma [[multitasking|kooperativního multitaskingu]]).
* Generátory jsou užitečné pro [[Datový proud|proudy]] – zejména vstupní/výstupní – a pro obecné procházení datových struktur.
* Komunikace mezi sekvenčními [[Proces (program)|procesy]], kde každý podproces je koprogram. Vstupně-výstupní kanály a blokující operace volají ''yield'' v koprogramu a plánovač je následně odblokuje při dokončení.
 
 
== Alternativy ==
Použití koprogramů nemusí být vždy dostupné řešení pro přirozenou implementaci mechanismu. Typickou reakcí na tento problém je použití uzávěr - [[Podprogram|podprogramůpodprogram]]ů se stavovými proměnnými (statické proměnné, často booleovské příznaky). Tyto proměnné se používají k udržení vnitřních stavů mezi voláními a k řízení transferu do správného bodu. Podmínky uvnitř kódu určují, která část kódu se vykoná na základě hodnot stavových proměnných. Další typickou reakcí je implementace explicitního stavového stroje ve formě rozsáhlých a komplexních switch nebo „goto“ příkazů, zvláště vypočítaných „goto“ příkazů. Všechny tyto implementace jsou považovány za složité k pochopení a údržbě. Jsou tedy motivací pro podporu koprogramů.
 
[[Vlákno (program)|Vlákna]] jsou dnes v oboru [[programování]] také alternativou koprogramů. [[Vlákno (program)|Vlákna]] poskytují v reálném čase možnosti pro řízení spolupráce mezi souběžně vykonávanými kusy kódu. Vlákna jsou široce rozšířena v prostředích, která podporují jazyk [[C (programovací jazyk)|C]] (a jsou podporovány nativně ve spoustě ostatních moderních jazycích) a [[programátor|programátoři]] jsou s nimi obeznámeni. Jsou obvykle velmi dobře implementovány, dokumentovány a podporovány. Jakmile vlákna řeší rozsáhlý a obtížný problém obsahují mnoho mocných a komplexních možností a mají tomu odpovídající složitost na porozumění. V případě, že je snadnější použít koprogram, je vláknování velmi nadbytečné.
 
{{Pahýl}}
{{Autoritní data}}
 
[[Kategorie:Programování]]
1 430 051

editací