Coprogramele (corutinele) sunt fire de execuție a codului care sunt organizate pe firele hardware (sistem).
Fluxul de execuție a codului este o secvență de operații care sunt executate unul după altul. În momentele potrivite, această secvență poate fi întreruptă și în loc de aceasta poate începe să fie executată o parte dintr-o altă secvență de operații.
Fluxurile de sistem constau în instrucțiuni ale procesorului, iar pe un nucleu al procesorului mai multe fluxuri de sistem pot funcționa.
Coprogramele funcționează la un nivel mai înalt - mai multe corutine pot, la rândul lor, executa codul lor pe un singur fir de sistem. (În funcție de implementare, corutina nu poate fi legată de un anumit fir de sistem, ci, de exemplu, execută codul său pe fondul de fire).
Spre deosebire de fluxurile de sistem, care sunt comutate de sistem la momente arbitrare ale timpului (înlocuirea multitaskingului), corutinele sunt comutate manual, în locurile indicate de programator (multitasking cooperativ).
Denumim operațiunile de pe corutină după cum urmează:
- mâner = spawn; - lansarea de corutine,
- randament; - suspendarea actualei corutine,
- relua (mâner); - reluarea corutinei.
Luați cele două corutine:
Apoi, dacă executați SP1 pe un fir de sistem și apoi pe SP2, firul de sistem efectuează operațiile în următoarea ordine deterministă:
Deoarece ambele corutine sunt executate pe același fir de sistem, cursele de date sunt imposibile în acestea, codul dintre randament este executat atomic (în cadrul acestui fir de sistem).
Dacă executați fiecare coroutine într-un flux de sistem separat, atunci nu diferă de la fluxul normal de sistem - va fi comutat în cazul în care sistemul va spune, trebuie să se sincronizeze, pentru a evita cursele de date.
Operații asincrone
Unul dintre scenariile principale pentru utilizarea corutinelor este operațiile asincrone, cum ar fi I / O și animațiile din interfața utilizator. După începutul operației asincrone, corutina poate face randament și poate continua după finalizarea acestei operații. În același timp, fluxul de sistem pe care a fost efectuat nu adoarme cu corutina, dar rămâne liber pentru alte corutine.
Codul asincron tradițional implică utilizarea apelurilor ca parametri funcționali și împreună cu viitorul / promisiunea:
În cazul în care apelul este o funcție care va fi apelată după terminarea scrierii asincrone. Ca collback, puteți utiliza o funcție lambda, de exemplu, în sintaxa C ++:
Introducem mânerul de funcționare = get_coroutine_handle ();. care va emite manualul (contextul) corutinei în codul corutinei în sine.
Apoi, în interiorul corutinei puteți scrie:
Pentru comoditate, multe limbi utilizează instrucțiunea await. care scurtează acest cod
Un exemplu mai detaliat:
generatoare
Un alt scenariu pentru utilizarea de corutine este "generatoare", corutine care generează secvențe de același tip, de exemplu, secvențe de numere:
Aici, pe lângă oprirea generatorului, randamentul are de asemenea valori care sunt generate de generator.
Realizarea stivuitoare a corutinelor
După cum sugerează și numele, corutinele stivuite sunt corutine care au propriile lor stiluri, la fel ca firele de sistem. Principala diferență între aceste corutine și firele obișnuite ale sistemului este aceea că acestea sunt comutate manual. În comparație cu viteza comutării fluxurilor de sistem, comutarea întreruperilor este aproape liberă (sute de cicluri ale procesorului). Cu toate acestea, datorită faptului că pentru fiecare corutină este necesar să alocăm o stivă separată și alte structuri de date ale serviciului - crearea și existența lor nu este mai ieftină decât crearea unui flux de sistem.
În Windows, corutinele stivuite sunt construite în sistem și se numesc fibre (fibre, fibre). Fibrele sunt legate de firul de sistem pe care sunt create, comutarea (randamentul / reluarea) este implementată prin funcția SwitchToFiber (fibră optică).
Rularea unei corutine stackless nu diferă de rulează un thread normal și ar putea să arate astfel:
A avea un stack personalizat vă permite să obțineți randamentele de la apelurile de funcții imbricate.
Cu toate acestea, din moment ce corutinele stivuite sunt destul de scumpe, ele nu pot fi folosite pentru a crea generatoare simple.
Realizarea fără sarcini a corutinelor
Stackless (bezstekovye) coroutine nu depinde de sistemul de operare, și puse în aplicare în mod exclusiv prin intermediul unui compilator: cod coroutine rescris în mașină-obiect de stat, variabilele locale sunt alocate nu pe stiva, și să devină membri ai acestui obiect.
Spre deosebire de corutinele stivuite, într-o corutină fără stivă, randamentul nu poate fi decât în corpul ei. Nu puteți obține un randament dintr-o funcție cauzată de o corutină.
Crearea unei coroutine non-corout creează un obiect care stochează starea lui (__fib) și, de obicei, arată ca un apel de funcție:
@ixSci, da, intr-un sens puteti spune ca "coroutine nu depinde de prezenta fluxurilor", dar, in general, suna ca "programul nu depinde de disponibilitatea procesorului". Am scris despre firele de sistem, deoarece acest lucru este important în contextul problemelor de sincronizare - dacă corutinele sunt executate pe fire de sistem diferite, atunci rasele de date sunt posibile, dacă sunt executate pe una - atunci nu vor mai exista curse. - Abyx pe 22 februarie la 13:36
korutiny, ASINKOM și alte lucruri, este o metodă de dezvoltare în care reușesc să scape de filamente și procese lasing (pentru a evita orice tip de comutare și de initializare), menținând o execuție cod pseudo. A activului suport siskol selectați / sondaj peste care navorocheno jungla de zahăr tonă, care executa același cod într-un singur flux de joc operații IO pentru a comuta între un așa-numita korutinami (funcția obișnuită tobish). Astfel de cazuri;)