Korutiini

Vuonna 2003 monissa suosituimmissa ohjelmointikielissä, kuten C:ssä ja sen johdannaisissa, ei ole suoraa tukea korutiineille kielessä tai niiden standardikirjastoissa. Tämä johtuu suurelta osin pinopohjaisen aliohjelman toteutuksen rajoituksista. Poikkeuksena on Boost-kirjastoihin kuuluva C++-kirjasto Boost.Context, joka tukee kontekstinvaihtoa ARM:llä, MIPS:llä, PowerPC:llä, SPARC:llä ja x86:lla POSIX:llä, Mac OS X:llä ja Windowsilla. Boost.Contextin varaan voidaan rakentaa korutiineja.

Tilanteissa, joissa korutiini olisi luonteva toteutus mekanismille, mutta sitä ei ole saatavilla, tyypillinen vastaus on käyttää sulkeutumista – aliohjelmaa, jossa on tilamuuttujia (staattisia muuttujia, usein boolean-lipukkeita), jotka ylläpitävät sisäistä tilaa puheluiden välillä ja siirtävät hallinnan oikeaan kohtaan. Koodin sisällä olevat ehtolausekkeet johtavat eri koodipolkujen suorittamiseen peräkkäisissä kutsuissa tilamuuttujien arvojen perusteella. Toinen tyypillinen vastaus on toteuttaa eksplisiittinen tilakone suuren ja monimutkaisen switch-lauseen muodossa tai goto-lauseen, erityisesti laskennallisen goto-lauseen, avulla. Tällaisia toteutuksia pidetään vaikeasti ymmärrettävinä ja ylläpidettävinä, ja ne ovat motivaatio korutiinituen saamiseksi.

Säikeet ja vähäisemmässä määrin kuidut ovat nykyään vaihtoehto korutiineille valtavirtaisissa ohjelmointiympäristöissä. Säikeet tarjoavat välineitä samanaikaisesti suoritettavien koodinpätkien reaaliaikaisen yhteistoiminnan hallintaan. Säikeet ovat laajalti saatavilla ympäristöissä, jotka tukevat C:tä (ja niitä tuetaan natiivisti monissa muissa nykyaikaisissa kielissä), ne ovat tuttuja monille ohjelmoijille, ja ne ovat yleensä hyvin toteutettuja, hyvin dokumentoituja ja hyvin tuettuja. Koska ne kuitenkin ratkaisevat laajan ja vaikean ongelman, ne sisältävät monia tehokkaita ja monimutkaisia toimintoja, ja niiden oppiminen on vastaavasti vaikeaa. Kun tarvitaan vain korutiinia, säikeen käyttäminen voi olla ylivoimaista.

Yksi tärkeä ero säikeiden ja korutiinien välillä on se, että säikeet tyypillisesti ajoitetaan ennalta, kun taas korutiinit eivät. Koska säikeet voidaan ajoittaa uudelleen milloin tahansa ja ne voivat suorittaa samanaikaisesti, säikeitä käyttävien ohjelmien on oltava varovaisia lukituksen suhteen. Sitä vastoin, koska korutiineja voidaan ajoittaa uudelleen vain tietyissä kohdissa ohjelmaa eikä niitä suoriteta samanaikaisesti, korutiineja käyttävät ohjelmat voivat usein välttää lukituksen kokonaan. Tämä ominaisuus mainitaan myös tapahtumapohjaisen tai asynkronisen ohjelmoinnin etuna.

Koska kuituja ajoitetaan yhteistyössä, ne tarjoavat ihanteellisen pohjan edellä mainittujen korutiinien toteuttamiselle. Kuitujen järjestelmätuki on kuitenkin usein puutteellinen verrattuna säikeiden tukeen.

Toteutukset CEdit:lle

Yleiskäyttöisten korutiinien toteuttamiseksi on hankittava toinen kutsupino, mikä on ominaisuus, jota C-kieli ei suoraan tue. Luotettava (vaikkakin alustakohtainen) tapa saavuttaa tämä on käyttää pientä määrää inline-kokoonpanoa pinon osoittimen eksplisiittiseen manipulointiin korutiinin alkuperäisen luomisen aikana. Tätä lähestymistapaa suosittelee Tom Duff keskustelussaan sen suhteellisista eduista Protothreadsin käyttämään menetelmään verrattuna. Alustoilla, jotka tarjoavat POSIX sigaltstack -järjestelmäkutsun, toisen kutsupinon voi saada kutsumalla ponnahduslauta-funktiota signaalinkäsittelijän sisältä, jolloin saavutetaan sama tavoite siirrettävällä C:llä, mutta tämä aiheuttaa jonkin verran ylimääräistä monimutkaisuutta. POSIXin tai Single Unix Specificationin (SUSv3) mukaiset C-kirjastot tarjosivat sellaisia rutiineja kuin getcontext, setcontext, makecontext ja swapcontext, mutta nämä funktiot julistettiin vanhentuneiksi POSIX 1.2008:ssa.

Kun toinen kutsupino on saatu aikaan jollakin edellä mainituista menetelmistä, C-standardikirjastoon kuuluvia setjmp- ja longjmp-funktioita voidaan sen jälkeen käyttää toteuttamaan korutiinien väliset vaihdot. Nämä funktiot tallentavat ja palauttavat vastaavasti pinon osoittimen, ohjelmalaskurin, kutsun tallentamat rekisterit ja minkä tahansa muun ABI:n vaatiman sisäisen tilan siten, että paluu korutiiniin sen jälkeen, kun se on luovuttanut, palauttaa kaiken sen tilan, joka palautuisi, kun palataan funktiokutsusta. Minimalistiset toteutukset, jotka eivät käytä setjmp- ja longjmp-funktioita, voivat saavuttaa saman tuloksen pienellä rivikokoonpanon lohkolla, joka vaihtaa vain pino-osoittimen ja ohjelmalaskurin ja tuhoaa kaikki muut rekisterit. Tämä voi olla huomattavasti nopeampaa, koska setjmp:n ja longjmp:n on varovaisesti tallennettava kaikki ABI:n mukaan mahdollisesti käytössä olevat rekisterit, kun taas clobber-menetelmän avulla kääntäjä voi tallentaa (pinoamalla pinoon) vain ne rekisterit, joiden se tietää olevan todella käytössä.

Suoran kielituen puuttuessa monet kirjoittajat ovat kirjoittaneet omia kirjastojaan korutiineja varten, jotka kätkevät sisäänsä edellä mainitut yksityiskohdat. Russ Coxin libtask-kirjasto on hyvä esimerkki tästä genrestä. Se käyttää kontekstifunktioita, jos ne ovat natiivin C-kirjaston tarjoamia; muuten se tarjoaa omat toteutuksensa ARM:lle, PowerPC:lle, Sparcille ja x86:lle. Muita merkittäviä toteutuksia ovat libpcl, coro, lthread, libCoroutine, libconcurrency, libcoro, ribs2, libdill., libaco ja libco.

Edellä mainitun yleisen lähestymistavan lisäksi on yritetty useasti lähentää korutiineja C:ssä aliohjelmien ja makrojen yhdistelmillä. Simon Tathamin osuus, joka perustuu Duffin laitteeseen, on merkittävä esimerkki genrestä, ja se on pohjana Protothreadsille ja vastaaville toteutuksille. Duffin vastalauseiden lisäksi Tathamin omat kommentit tarjoavat suoran arvion tämän lähestymistavan rajoituksista: ”Tietääkseni tämä on huonoin C-hakkerointi, jota on koskaan nähty vakavasti otettavassa tuotantokoodissa.” Tämän approksimaation tärkeimmät puutteet ovat, että koska jokaiselle koroutiinille ei ylläpidetä erillistä pinokehystä, paikalliset muuttujat eivät säily funktiosta poistuttaessa, funktiossa ei ole mahdollista olla useita sisäänkäyntejä ja hallinta voidaan luovuttaa vain ylimmän tason rutiinista.

Toteutukset C++Edit

  • C++:n koroutiinien TS (Technical Specification) -standardi, joka on kehitteillä standardina C++:n kielen laajennuksia varten pinoille, joissa ei ole pinokehystä koroutiinien kaltaiselle käytökselle. Visual C++ ja Clang tukevat jo suuria osia std::experimental-nimiavaruudessa. coroutines Technical Specification
  • Boost.Coroutine – Oliver Kowalken luoma, on boostin virallinen julkaistu siirrettävä coroutine-kirjasto versiosta 1.53 lähtien. Kirjasto perustuu Boost.Contextiin ja tukee ARM-, MIPS-, PowerPC-, SPARC- ja X86-käyttöjärjestelmiä POSIX-, Mac OS X- ja Windows-käyttöjärjestelmissä.
  • Boost.Coroutine2 – myös Oliver Kowalken luoma, on modernisoitu kannettava coroutine-kirjasto boostin versiosta 1.59 lähtien. Se hyödyntää C++11:n ominaisuuksia, mutta poistaa tuen symmetrisille korutiineille.
  • Mordor – Mozy avasi vuonna 2010 korutiineja toteuttavan C++-kirjaston, jonka pääpaino on niiden käyttämisessä asynkronisen I/O:n abstrahoimiseen tutummaksi sekventiaaliseksi malliksi.
  • CO2 – C++:n esiprosessorin kikkailuihin perustuva pinoton koroutiini, joka tarjoaa await/yield-emuloinnin.
  • ScummVM – ScummVM-projekti toteuttaa kevyen version pinottomista koroutiineista Simon Tathamin artikkelin pohjalta.
  • tonbit::coroutine – C++11 single .h epäsymmetrinen coroutine-toteutus ucontextin / kuidun kautta
  • Coroutines laskeutui Clangiin toukokuussa 2017, ja libc++-toteutus on käynnissä.
  • elle by Docker
  • oatpp-coroutines – stackless coroutines with scheduling designed for high-concurrency level I/O operations. Käytetty Oat++:n 5 miljoonan WebSocket-yhteyden kokeessa. Osa Oat++:n web-kehystä.

Toteutukset C#Editille

  • MindTouch Dream – MindTouch Dream REST-kehys tarjoaa C# 2.0:n iteraattorimalliin
  • perustuvan korutiineja sisältävän toteutuksen
  • Caliburn – Näyttökuviointimallien kehys WPF:lle käyttää C# 2.0:n iteraattoreiden käyttöä helpottaakseen käyttöliittymäohjelmointia erityisesti asynkronisissa skenaarioissa.
  • Power Threading Library – Jeffrey Richterin Power Threading Library toteuttaa AsyncEnumeratorin, joka tarjoaa yksinkertaistetun asynkronisen ohjelmointimallin iteraattoripohjaisten korutiinien avulla.
  • Unity-pelimoottori toteuttaa korutiinit.
  • Servelat Pieces – Jevhen Bobrovin Servelat Pieces -projekti tarjoaa läpinäkyvää asynkroniaa Silverlightin WCF-palveluille ja mahdollisuuden kutsua mitä tahansa synkronista metodia asynkronisesti. Toteutus perustuu Caliburnin Coroutines-iteraattoriin ja C#:n iteraattorilohkoihin.
  • – .NET 2.0+ -puitekehys tarjoaa nyt semi-coroutine (generaattori) -toiminnallisuuden iteraattorikuvion ja yield-avainsanan avulla.

C# 5.0 sisältää await-syntaksin tuen.

Toteutukset ClojureEdit

Cloroutine on kolmannen osapuolen kirjasto, joka tarjoaa tukea pinottomille korutiineille Clojuressa. Se on toteutettu makroina, jotka jakavat staattisesti mielivaltaisen koodilohkon mielivaltaisilla var-kutsuilla ja lähettävät coroutiinin tilallisena funktiona.

Toteutukset DEditille

D toteuttaa coroutiinit vakiokirjastoluokkanaan Fiber Generaattori tekee triviaaliksi paljastaa kuitufunktion syöttöalueena, jolloin mikä tahansa kuitu on yhteensopiva olemassa olevien aluealgoritmien kanssa.

Toteutukset JavaEditille

Javassa on useita toteutuksia coroutiineille. Javan abstraktioiden asettamista rajoituksista huolimatta JVM ei sulje pois mahdollisuutta. Yleisesti käytetään neljää menetelmää, mutta kaksi rikkoo tavukoodin siirrettävyyden standardien mukaisten JVM:ien välillä.

  • Modifioidut JVM:t. On mahdollista rakentaa korjattu JVM tukemaan koroutiineja natiivimmin. Da Vinci JVM:ään on luotu korjauksia.
  • Modifioitu tavukoodi. Coroutine-toiminnallisuus on mahdollista kirjoittamalla uudelleen tavallista Java-bytekoodia joko lennossa tai kääntäen. Työkalupaketteja ovat Javaflow, Java Coroutines ja Coroutines.
  • Alustakohtaiset JNI-mekanismit. Nämä käyttävät käyttöjärjestelmässä tai C-kirjastoissa toteutettuja JNI-menetelmiä tarjotakseen toiminnallisuuden JVM:lle.
  • Säikeiden abstraktiot. Säikeiden avulla toteutetut korutiinikirjastot voivat olla raskassoutuisia, joskin suorituskyky vaihtelee JVM:n säikeiden toteutuksen mukaan.

Toteutukset JavaScriptEdit

  • node-fibers
    • Fibjs – Fibjs on JavaScript-ajoympäristö, joka on rakennettu Chromen V8 JavaScript -moottorin päälle. fibjs käyttää fibers-kytkentää, sync-tyyliä ja lukkiutumatonta I/O-mallia skaalautuvien järjestelmien rakentamiseen.
  • Since ECMAScript 2015, stackless coroutine toiminnallisuutta ”generaattoreiden” ja yield-lausekkeiden kautta on tarjottu.

Toteutukset KotlinissaEdit

Kotlin toteuttaa coroutiinit osana ensimmaista kirjastoa.

Toteutukset Modula-2:lleEdit

Modula-2 Wirthin määrittelemässä muodossa toteuttaa korutiineja osana vakiomuotoista SYSTEM-kirjastoa.

Proseduuri NEWPROCESS() täyttää kontekstin, kun parametreina on koodilohko ja tilaa pinolle, ja proseduuri TRANSFER() siirtää kontrollin korutiineille, kun parametrina on korutiinin konteksti.

Toteutus MonoEdit

Mono Common Language Runtime -ohjelmassa on tuki jatkumoille, joista voidaan rakentaa korutiineja.

Toteutus .NET Frameworkissa fibersEdit

Microsoft laajensi .NET Framework 2.0:n kehittämisen aikana Common Language Runtime (CLR) -isännöintirajapintojen (APIs) suunnittelua siten, että ne käsittelevät kuitupohjaista aikatauluttamista silmälläpitäen sen käyttämistä kuitupohjaisessa toimintatavassa SQL-palvelimessa. Ennen julkaisua tuki tehtävänvaihtokoukulle ICLRTask::SwitchOut poistettiin aikarajoitusten vuoksi.Näin ollen kuitupohjaisen API:n käyttäminen tehtävien vaihtamiseen ei ole tällä hetkellä käyttökelpoinen vaihtoehto .NET Frameworkissa.

Toteutukset PerlEdit

  • Coro

Korutiineja on toteutettu natiivisti kaikissa Raku-backendeissä.

Toteutukset PHPEditille

  • Amphp
  • Coroutine toteutettu tavalla, joka muistuttaa Python-funktioita, ja jotkut Go, monet esimerkit, jotka osoittavat siellä koodia muunnettuna samalla rivimäärällä ja käyttäytymisellä.

Toteutukset PythonEditille

  • Python 2.5 toteuttaa paremman tuen coroutinen kaltaiselle toiminnallisuudelle, perustuu laajennettuihin generaattoreihin (PEP 342)
  • Python 3.3 parantaa tätä kykyä tukemalla delegointia aligeneraattoriin (PEP 380)
  • Python 3.4 ottaa käyttöön kattavan asynkronisen I/O-kehyksen, joka on standardoitu PEP 3156:ssa ja joka sisältää korutiineja, jotka hyödyntävät aligeneraattorin delegointia
  • Python 3.5 ottaa käyttöön eksplisiittisen tuen korutiineille, joissa on async/await-syntaksia (PEP 0492).
  • Python 3.7:stä lähtien async/await:stä on tullut varatut avainsanat .
  • Eventlet
  • Greenlet
  • gevent
  • stackless python
  • Abandoned
    • Shrapnel (viimeisin julkaisu 2015)
    • Kamaelia (viimeisin julkaisu 2015)
    • Kamaelia (viimeisin julkaisu 2015). 2010)
    • cogen (viimeinen julkaisu 2009)
    • multitask (viimeinen julkaisu 2007)
    • chiral

Toteutukset RubyEdit

  • Ruby 1.9 tukee natiivisti koroutiineja, jotka on toteutettu kuitujen muodossa, jotka ovat puolikoroutiineja.
  • Toteutuksen on tehnyt Marc De Scheemaecker
  • Ruby 2.5 ja uudemmat tukevat natiivisti korutiineja, jotka on toteutettu kuituina
  • Toteutuksen on tehnyt Thomas W Branson

Toteutukset RustEditille

Rust tukee korutiineja versiosta 1 lähtien.39 .On olemassa myös vaihtoehtoinen asynkroninen runtime (vanhempi projekti kuin Rustin vakioruntime) : tokio

Implementations for ScalaEdit

Scala Coroutines on coroutine-toteutus Scalalle. Tämä toteutus on kirjastotason laajennus, joka luottaa Scalan makrojärjestelmään ohjelman osien muuttamiseksi staattisesti coroutine-objekteiksi. Sellaisenaan tämä toteutus ei vaadi muutoksia JVM:ssä, joten se on täysin siirrettävissä eri JVM:ien välillä ja toimii vaihtoehtoisten Scala-taustaohjelmien kanssa, kuten Scala.js, joka kääntää JavaScriptiksi.

Scala Coroutines luottaa coroutine-makroon, joka muuttaa tavallisen koodilohkon coroutine-määrittelyksi. Tällaista korutiinimääritelmää voidaan kutsua call-operaatiolla, joka instantioi korutiinikehyksen. Koroutiinikehystä voidaan jatkaa resume-menetelmällä, joka jatkaa koroutiinirungon suoritusta, kunnes saavutetaan yieldval-avainsana, joka keskeyttää koroutiinikehyksen. Scala-koroutiinit paljastavat myös snapshot-metodin, joka tehokkaasti kopioi koroutiinin. Yksityiskohtaiset kuvaukset Scala-korutiineista tilannekuvineen ilmestyivät ECOOP 2018 -tapahtumassa yhdessä niiden formaalin mallin kanssa.

Toteutukset SchemeEdit

Koska Scheme tarjoaa täyden tuen jatkumoille, korutiinien toteuttaminen on lähes triviaalia, sillä se vaatii vain jatkumoiden jonon ylläpitämistä.

Toteutukset SmalltalkEdit

Koska useimmissa Smalltalk-ympäristöissä suorituspino on ykkösluokan kansalainen, korutiineja voidaan toteuttaa ilman ylimääräistä kirjasto- tai VM-tukea.

Toteutukset SwiftEdit

  • SwiftCoroutine – Swift-korutiineja sisältävä kirjasto iOS:lle, macOS:lle ja Linuxille.

Toteutukset Tcl-komentokielelle (Tool Command Language)Edit

Versiosta 8 lähtien.6, Tool Command Language tukee korutiineja ydinkielessä.

Toteutukset ValaEdit

Vala toteuttaa natiivin tuen korutiineille. Ne on suunniteltu käytettäväksi Gtk Main Loopin kanssa, mutta niitä voi käyttää yksinäänkin, jos huolehditaan siitä, ettei lopetuskutsua tarvitse koskaan kutsua ennen kuin on tehty ainakin yksi yield.

Toteutukset assemblerointikielissäEdit

Koneesta riippuvaiset assemblerointikielet tarjoavat usein suoria metodeja korutiinien suorittamiseen. Esimerkiksi MACRO-11:ssä, PDP-11-minitietokoneperheen assemblerikielessä, ”klassinen” korutiinikytkentä tapahtuu käskyllä ”JSR PC,@(SP)+”, joka hyppää pinosta poimittuun osoitteeseen ja työntää nykyisen (ts. seuraavan) käskyn osoitteen pinoon. VAXenissa (Macro-32:ssa) vastaava käsky on ”JSB @(SP)+”. Jopa Motorola 6809:ssä on käsky ”JSR ”; huomaa ”++”, koska pinosta nostetaan kaksi tavua (osoitetta). Tätä käskyä käytetään paljon (standardissa) ’monitor’ Assist 09.

.

Jätä kommentti