- Ama-Coroutine enza imisebenzi ehlukahlukene ibe yinkimbinkimbi ngokulondoloza isimo sendawo kanye nokuqalisa kabusha ukusebenza ezindaweni zokumiswa, okuvumela ukuvezwa kwemvelo kwemishini yesifundazwe, amajeneretha kanye nokusebenzisana ngokubambisana.
- Ukuqaliswa kwe-C kwavela kusukela ekuphathweni kwe-stack ngesandla kanye nama-API womongo we-POSIX kuya ekulinganisweni okusekelwe kuma-macro kanye nama-library e-coroutine aphathekayo akhelwe ekushintsheni komongo wezinga lomsebenzisi.
- I-C++20 ilinganisa imodeli ye-coroutine engenama-stackless ngezithembiso,
co_await,co_yieldkanye nozimele be-coroutine, okuvumela amalabhulali ukuthi achaze i-async ephezulu kanye ne-generator abstractions. - Imodeli ejwayelekile, ehlanganiswe nabalindile kanye nezinhlobo zezithembiso ezenziwe ngokwezifiso, ihlanganisa ukusetshenziswa kwe-coroutine kuwo wonke amalabhulali ngenkathi igcina ukusebenza nokulawula okubikezelwayo.
Ama-Coroutine ahlala endaweni ephakathi ethakazelisayo phakathi kwemisebenzi yakudala kanye nemicu egcwele, futhi indaba yabo kusukela kumaqhinga e-C asezingeni eliphansi kuya ekusekelweni kolimi lwe-C++20 okujwayelekile kungenye yezinguquko ezithakazelisa kakhulu ezinhlelweni zezinhlelo zesimanje. Uma wake wazama ukuhlanganisa ama-callback, imishini yesimo kanye nokuvumelanisa izintambo ukuze nje uphathe i-I/O engavimbeli, usuvele uhlangabezane nohlobo lobuhlungu ama-coroutine ayeklanyelwe ukuluqeda.
Kulesi sihloko sizohamba ngendlela ama-coroutine aguquke ngayo kusukela kuma-C hacks enziwe ngesandla kanye nama-POSIX context APIs kuya kumodeli yama-coroutines e-C++20 asezingeni eliphezulu, angenazitaki, ukuchaza ukuthi i-coroutine iyini ngempela, ukuthi ihluke kanjani kuma-generator, imicu kanye nemicu, ukuthi kusho ukuthini ukuthi “stackful” vs “stackless”, nokuthi imishini ye-C++20 (izinto ezithembisayo, izibambo ze-coroutine, co_await, co_yield, co_return) empeleni uziphatha ngaphansi kwesigqoko.
Kuyini ngempela i-coroutine?
Ayikho incazelo eyodwa esemthethweni eyamukelwa emhlabeni wonke ye-coroutine, kodwa izincwadi zihlangana ngezakhiwo ezimbili ezibalulekile ezihlukanisa ama-coroutines kuma-subroutines ajwayelekile:
- Uhulumeni wendawo uyasinda naphezu kokumiswa emsebenzini: idatha yendawo ku-coroutine iyaqhubeka phakathi kokusebenza, ngakho-ke isenzakalo ngasinye se-coroutine siziphatha njengento enememori.
- Ukwenza kungamiswa okwesikhashana bese kuqhubeka kabusha kusukela endaweni efanayo: uma ukulawula kushiya i-coroutine, kungafakwa kabusha endaweni efanele yokumiswa esikhundleni sokuqala kusukela phezulu njengomsebenzi ojwayelekile.
Esikhundleni sokuba nokungena okukodwa kanye nokuphuma njengezinhlelo ezincane, ama-coroutine asekela amaphuzu amaningi okungena nokuphuma esikhathini sokuphila kwawo, okubenza babe namandla okuveza abakhiqizi, abathengi, imishini kahulumeni, abahleli bezinhlelo abasebenzisanayo kanye nemisebenzi yokusebenza engahambisani ngendlela eqondile nefundekayo.
Ubukhulu obuyinhloko bomklamo we-coroutine
Izinhlelo ze-coroutine zomhlaba wangempela ziyahlukahluka ngezimbazo ezintathu ezibalulekile ezichaza indlela eziziphatha ngayo nokuthi ziveza kanjani: imodeli yokudlulisa ukulawula, ukuthi ama-coroutine angamanani ekilasi lokuqala, nokuthi ngabe agcwele noma awanama-stack.
Okokuqala, indlela yokudlulisa ukulawula ihlukanisa ama-coroutine angalingani nama-coroutine alinganayo. Ngomklamo ongafani, i-coroutine esebenzayo ingabuyela kuphela kumuntu obizayo ngqo (kusetshenziswa umsebenzi ofana nowokuthi yield), bese umuntu oshaya ucingo eqhubeka nakho kamuva (ngomsebenzi ofana no resume). Emiklamo elinganayo, i-coroutine ingadlulisela ngokusobala ukulawula kunoma iyiphi enye i-coroutine, kunokuba ihlale ibuyela kunoma ubani oyisebenzisile.
Okwesibili, ezinye izilimi ziphatha izimo ze-coroutine njengezinto zekilasi lokuqala ongazigcina, uzidlulise futhi uziphathe ngokukhululeka, kuyilapho abanye beveza ama-coroutine kuphela njengezakhiwo ze-syntactic ezinezindlela ezilinganiselwe zokuxhumana nawo. Ukusekelwa kwekilasi lokuqala kukhulisa kakhulu ukuguquguquka kanye nokuqina.
Okwesithathu, ama-coroutine angase abe nama-stackful noma angabi nama-stack. I-coroutine ehlanganisiwe ingamisa ngaphakathi kwe-call stack ehlanganisiwe; lapho iqala kabusha, wonke uhlaka olukuleso sitaki luyaqhubeka lapho lugcine khona. Ama-coroutine angenazitaki amisa kuphela ezingeni lomsebenzi we-coroutine uqobo: imisebenzi ejwayelekile yomsizi ayikwazi ukukhiqiza ngaphandle kokuthi yona ngokwayo iyi-coroutine noma ichazwe ngokukhethekile.
Igama elithi “i-coroutine ephelele” liphakanyiswe ngenxa yenhlanganisela eveza kakhulu: i-coroutine ehlanganisiwe, yekilasi lokuqala, kungaba elinganayo noma engalingani, okunamandla anele ukuveza ukuqhubeka kweshothi elilodwa noma ukuqhubeka okunqunyelwe. Ngisho noma izitayela ezilinganayo nezingenawo umkhawulo zinamandla afanayo okuveza, imodeli engalingani ivame ukuzwakala 'ifana nejwayelekile' futhi ijwayelekile kubahleli abaningi bezinhlelo.
Ama-Subroutines, ama-coroutines, ama-generator kanye nemicu
Izinqubo ezingaphansi zingabonakala njengecala elikhethekile lama-coroutine anokugeleza kokulawula okulinganiselwe kakhulu kanye nokuziphatha kwesimo. Umsebenzi ojwayelekile uqala njalo emyalweni wawo wokuqala, uphuma kanye, bese ulahla isimo sawo sendawo ngemuva kwalokho. I-coroutine, ngokuphambene, ingadlulisela ukulawula kwamanye ama-coroutine, iphinde iqalwe kabusha kamuva endaweni yokukhiqiza, futhi igcine isimo sayo phakathi kwalokhu kudluliselwa. Izimo eziningi ze-coroutine zomsebenzi ofanayo zingase zihlale ndawonye, ngasinye sinedatha yaso yendawo egciniwe.
Amajeneretha akha i-subset ephawulekayo yama-coroutine, ngezinye izikhathi abizwa ngokuthi “ama-semicoroutine”. Njengama-coroutine, ama-generator angamisa ukwenziwa izikhathi eziningi bese kamuva aqhubeke, kodwa ahlala evuma ukushaya ucingo lwawo ngqo futhi awanayo indlela yokuqondisa kabusha ukwenziwa ku-coroutine yesithathu engahleliwe. Lowo mkhawulo ungowenhloso: ama-generator alungiselelwe ukusebenzisa ama-iterators kanye nokulandelana okuvilaphayo lapho ngamunye yield kusho ukuthi “khiqiza inani lanoma ubani ongiphindayo”.
Eqinisweni, ungalingisa ama-coroutine ajwayelekile ngokubeka i-dispatcher phezu kohlelo lwe-generator, isibonelo ngokuba ne-trampoline esezingeni eliphezulu ethola amathokheni avela kuma-generator bese inquma ukuthi iyiphi i-generator okufanele isetshenziswe ngokulandelayo. Le ndlela yayisetshenziswa ngokomlando ezilimini ezifana nezinguqulo zakuqala ze-Python, ezazinama-generator kuphela kodwa zingenazo izakhi zokuqala ze-coroutine ezakhelwe ngaphakathi.
Ama-Coroutine avame ukuqhathaniswa nezintambo, kodwa ngokuyinhloko amayelana nokuhlela ngokubambisana kunokuba kube ukuhambisana kwangaphambili. Ama-Coroutine ahlinzeka nge-concurrency ngomqondo wokuhlanganisa imisebenzi ngaphandle kokushintsha ama-semantics ajwayelekile, kodwa awasebenzi ngesikhathi esisodwa kuma-core amaningi ngokwawo. I-coroutine iveza kuphela ukulawula ezindaweni zokumiswa ezicacile, ngakho-ke ikhodi phakathi kwalawo maphuzu isebenza ngaphandle kokuphazamiseka kwamanye ama-coroutine.
Le modeli yokubambisana iqeda izinhlungu eziningi zokuvumelanisa ezivame ukuba khona ngemicu: ngoba i-coroutine eyodwa kuphela esebenza ngesikhathi kushejuli ethile, awudingi ama-mutexes noma imisebenzi ye-athomu yesimo esabiwe esijwayelekile. Ngakolunye uhlangothi, ama-coroutine ngokwawo ngeke asebenzise ama-cores amaningi e-CPU ngaphandle kokuthi uwahlanganise nezintambo noma i-executor enezintambo eziningi.
Isibonelo se-coroutine yakudala: umkhiqizi-umthengi
Ukubonakaliswa kwencwadi yesifundo kwama-coroutine alinganayo yiphethini yomkhiqizi nomthengi enomugqa owabiwe. I-coroutine eyodwa ikhiqiza izinto bese izisunduzela emgqeni kuze kube yilapho zigcwele, bese inikela kumthengi; umthengi uphonsa izinto kuze kube yilapho umugqa ungenalutho, bese inikela kumkhiqizi. Ukusebenza kuyashesha futhi kuya phambili njengoba uhlangothi ngalunye lunikeza ukulawula ngokubambisana.
Ekusetshenzisweni okunjalo, umkhiqizi nomthengi babonakala besebenza “ngokufanayo” ngokombono womhleli wezinhlelo, yize empeleni zigxumagxuma nje ngaphakathi kwentambo eyodwa yokusebenza. Asikho isidingo sezintambo zezinga le-OS noma ukushintsha komongo: ukusebenza kwe-yield kungaba ukugxuma okuphansi okuvuselela uhlaka lwesitaki esisebenzayo.
Lesi sibonelo sivame ukusetshenziswa ukwethula i-multithreading, kodwa kubalulekile ukuqaphela ukuthi ama-coroutines wodwa anele ukuveza umqondo, nokuthi ukufaka esikhundleni sazo ngezintambo kungase kungadingeki noma kube yingozi ngisho nasezindaweni ezikhathalela iziqinisekiso zesikhathi sangempela noma izindleko ezincane zesikhathi sokusebenza.
Kungani ama-coroutines ebalulekile: imishini kahulumeni, abadlali kanye nokuhamba komsebenzi kwe-async
Ngenxa yokuthi ama-coroutine agcina iphuzu lawo lokusebenza kanye neziguquguquko zawo zasendaweni kuzo zonke izinzuzo, zinikeza indlela yemvelo kakhulu yokusebenzisa imishini yesimo esiyinkimbinkimbi ngaphandle kwezitatimende zokushintsha ezibanzi, amafulegi noma izibali zohlelo ezicacile. Iphuzu lokumiswa lamanje limelela ngokoqobo isimo samanje.
Ama-Coroutine nawo afaneleka kahle kumamodeli e-concurrency yesitayela somlingisi, njengalezo ezisetshenziswa ezinjinini eziningi zemidlalo. Umdlali ngamunye angasetshenziswa njenge-coroutine ebuyisela ukulawula emuva kumhleli ophakathi, oqhuba umdlali oyedwa ngemva komunye ngentambo eyodwa. Lokhu kusebenza okuningi ngokubambisana kuqeda isidingo sokukhiya okuningi ngenkathi kusanikeza ukuziphatha okuphendulayo.
Amajeneretha akhelwe phezu kwama-coroutine alungele ukusebenza ngemifudlana kanye nokudlula kwesakhiwo sedatha, ikakhulukazi uma ufuna ukukhiqizwa kwamanani okuvilaphayo, okufunwayo. Esikhundleni sokusunduza amanani kumthengi, ijeneretha ivumela umthengi ukuthi adonse amanani ngalinye ngalinye esebenzisa iluphu elula.
Ama-Coroutine aphinde akhanye emaphethini okuxhumana njengemipayipi kanye nezinqubo zokulandelana kokuxhumana (i-CSP), lapho isigaba ngasinye siyi-coroutine eveza khona uma ilinde okokufaka noma okukhiphayo. Umhleli weshejuli ube eseqala kabusha ama-coroutine lapho iziteshi zawo zokuxhumana sezilungile, enikeza enye indlela enhle esikhundleni sezihibe zemicimbi esindayo.
Okokugcina, imitapo eminingi yezinombolo isebenzisa isitayela esibizwa ngokuthi “ukuxhumana okuphambene”, lapho isixazululo sizimisa khona noma nini lapho sidinga umsebenzisi ukuthi anikeze ukuhlolwa komsebenzi, bese siqala kabusha uma umsebenzisi ephendula. Ama-Coroutine anikeza indlela eqondile nefundekayo yokuveza ukugeleza kokulawula okuya phambili nangemuva.
Kusukela ekusetshenzisweni kwe-C okuphansi kuya emitatsheni yezincwadi ephathekayo
Isigaba esisodwa sokusetshenziswa sithola isitaki sesibili sokushaya ngesandla bese sisebenzisa setjmp/longjmp ukushintsha phakathi kwama-coroutine. Ukuhlanganiswa okuqondile kwepulatifomu kungamisa isitaki esisha se-coroutine ngayinye; ezinhlelweni ze-POSIX, amasignali ahlanganiswe sigaltstack ingasetshenziswa ukuqalisa ukusebenza kwe-stack kwenye i-stack ku-C emsulwa. Uma i-coroutine ngayinye ine-stack yayo, setjmp igcina isimo se-CPU kanye ne-stack pointer, futhi longjmp iyazibuyisela ukuze ziqalise kabusha i-coroutine.
Amanye amalabhulali e-C ahambisana ne-POSIX kanye ne-UNIX aveze imisebenzi yomsizi njengomlando getcontext, setcontext, makecontext futhi swapcontext, okuhlanganisa ngqo umqondo wokushintsha phakathi kwezimo zezinga lomsebenzisi. Nakuba lokhu sekumakwe njengokungasasebenzi ku-POSIX.1-2008, kwakha umgogodla wemitapo yolwazi eminingi ye-coroutine futhi kwaphefumulela imiklamo yakamuva.
Ukudlula kokusetshenziswa okuncane kwe-coroutine setjmp/longjmp kanye nama-API omongo ngokuphelele, esikhundleni salokho ukhetha ukuhlanganiswa okubhalwe ngesandla okushintshanisa kuphela ikhawunta yohlelo kanye nesikhombisi se-stack, okuphazamisa amanye amarejista. Lokhu kungaba ngokushesha okukhulu kwamanye ama-ABI ngoba kusindisa ngqo lokho okudingekayo hhayi okunye, kanti setjmp kufanele igcine isethi enkulu yamarejista ngokuqapha.
Ukuze kufihlwe konke lokhu bunzima ekhodini yesicelo, kwavela imitapo yolwazi eminingi ye-C eminyakeni edlule ehlanganisa i-coroutine eshintshela kuma-API ahlanzekile, njengekaRuss Cox's libtask kanye nabanye abahlukahlukene (libpcl, coro, lthread, libcoro, libaco, libco nokuningi). Lawa malabhulali ngokuvamile ahlinzeka ngezinto ezingasetshenziswa njengemisebenzi elula noma imicu engaqalwa kabusha futhi ikhishwe ngaphandle kokuthi umuntu oshayelayo adinge ukukhathazeka ngamaqhinga okuhlanganisa ayisisekelo.
Ama-coroutine alinganiselwa ku-C kusetshenziswa ama-macro
Lapho ama-stack ahlukene noma ama-API okushintsha umongo engatholakali noma engafiseleki, onjiniyela nabo balinganise ama-coroutine ku-C emsulwa ngama-macro kanye nezitatimende zokushintsha, inqubo ebhalwe ngokudumile nguSimon Tatham futhi ehlobene necebo elidala elithi “idivayisi kaDuff”.
Umqondo oyinhloko ukufaka ikhodi yesimo se-coroutine njenge-counter yohlelo esetshenziswe nge- switch futhi case amalebula, lapho ngamunye yieldI-macro efana ne--like iyanda ibe ikhodi eqopha ilebula yamanje ku-static variable bese ibuyela kumuntu oshaya ucingo. Ekushayweni okulandelayo, umsebenzi ubuyela kulelo lebula esikhundleni sokuqala ekuqaleni.
Amalabhulali afana ne-Protothreads akhela phezu kwaleli phethini ukuze anikeze ama-coroutine alula kakhulu, angenazitaki afaneleka ezindaweni ezihlanganisiwe ezivinjelwe, kodwa le ndlela iza nemikhawulo emikhulu: iziguquguquko zasendaweni azihlali ngokwemvelo kuzo zonke izivuno ngaphandle kokuthi zigcinwe ezakhiweni ezimile noma zangaphandle, awukwazi ukuma kalula kumakholi womsebenzi ahlanganisiwe, futhi ngokuvamile unendawo eyodwa yokungena.
Ngisho nabasekeli bayo bachaza lobu buqili obusekelwe ku-macro njengenye yekhodi ye-C embi kunazo zonke eyake yasetshenziswa ekukhiqizeni, futhi abagxeki bakhomba ukuthi ukugeleza kokulawula okubangelwayo kungaba nzima ukucabanga ngakho nokulondoloza ngokuhamba kwesikhathi. Noma kunjalo, kusalokhu kuyisivumelwano esiwusizo ezinhlelweni lapho ama-stack engeziwe noma amaqhinga okuxhumanisa engekho etafuleni.
Itshe lokunyathela: imicu, imicu kanye nezinto ezihlobene nayo
Ezindaweni ezivamile ezingenazo izinhlayiya zomdabu, imicu (futhi, ngezinga elincane, imicu) isibe yisakhiwo esizenzakalelayo se-concurrency, noma ngabe ukuziphatha ngokubambisana kwanele. Izingxoxo zivame ukusekelwa kahle futhi zibhalwe kahle, kodwa zixazulula inkinga ebanzi neyinkimbinkimbi kakhulu kunalokho okudingwa yizimo eziningi zokusetshenziswa kwe-coroutine.
Ama-Fiber, lapho etholakala khona, ahambisana kakhulu nama-coroutines asezingeni lomsebenzisi ngoba ahlelwe ngokubambisana futhi angashintshwa ngaphandle kokubandakanyeka kwe-OS, okwenza kube yi-substrate yemvelo lapho kuzosetshenziswa khona ama-API esitayela se-coroutine. Kodwa-ke, ukusekelwa kwesistimu yama-fiber kuyinkimbinkimbi uma kuqhathaniswa nemicu, futhi ukuphatheka kuyawohloka.
Umehluko owodwa ophawulekayo phakathi kwezintambo nama-coroutines ukuziphatha kokuhlela. Imicu ivame ukungavinjelwa ezindaweni ezingahleliwe, okuphoqa abahleli bezinhlelo ukuthi bacabange ngezimo zomjaho kanye nokuvumelanisa yonke indawo. Ama-Coroutine, ngokuphambene, ashintsha kuphela ukulawula ezindaweni zokumiswa ezicacile, okuvame ukukuvumela ukuthi ubhale ikhodi elula ngaphandle kokukhiya noma imisebenzi ye-athomu.
Izilimi kanye nezikhathi zokusebenza zihlole izindlela eziningi zokulingisa ama-coroutines ngaphezu kwengqalasizinda ekhona, kusukela ekubhaleni kabusha i-bytecode (njengakwezinye izinhlaka ze-Java coroutine) kuya ekumepheni izakhiwo ezifana ne-coroutine kuya kuma-iterators (njengoba i-C# yenze nge yield ngaphambi async/await) noma ukuzakha phezu kwemicu eluhlaza, imicu eqhubekayo noma imicu.
Ama-Coroutine kuzo zonke izilimi zokuhlela
Emashumini eminyaka edlule, izilimi eziningi ziye zazama ukwakha okufana ne-coroutine, ngayinye inokunambitheka kwayo kanye nokushintshana kwayo, futhi ukuqonda le ecosystem kusiza ekubekeni ukuvela kwe-C++ kumongo.
Ezinye izilimi zinikeza ama-coroutine ekilasi lokuqala, agcwele ama-stackful ngqo ku-runtime kanye nomtapo wolwazi ojwayelekile. I-Lua, isibonelo, isekele ama-coroutine angenawo u-asymmetric, agcwele kusukela kunguqulo 5.0 nge-standard yayo coroutine I-API, enezimpawu zokuqala zokudala, ukuqalisa kabusha kanye nokukhiqiza. I-Modula-2 yayihlanganisa ngokomlando ukwesekwa kwe-coroutine ngezinqubo ezifana ne- NEWPROCESS futhi TRANSFER ezimisa izitaki ezihlukene futhi zishintshashintsha phakathi kwezimo.
Ezinye izikhungo zemvelo zakha ama-coroutine phezu kwezinto zokuqala ezikhona njengezinqubekela phambili noma imicu eluhlaza. I-Racket (kanye nezilimi ze-Scheme ngokuvamile) zingasebenzisa ama-coroutine cishe kancane ngoba zidalula ukuqhubeka njengezindinganiso zekilasi lokuqala. Izinhlelo ze-Smalltalk, lapho ama-execution stacks ezinto ezisebenzisekayo, zingabamba ngokufanayo ama-coroutine abstractions ngaphandle kokusekelwa okwengeziwe kwe-VM. Ku-OCaml, i-cooperative concurrency inikezwe ngamamojula ahlela izintambo ngaphambi kokusebenzisa intambo eyodwa ye-OS, kuyilapho izinguqulo ezintsha zengeza ukwesekwa kwesitayela sentambo eluhlaza.
Izilimi ezigxile ekuhleleni izinhlelo okungenazo izinhlelo ngokuvamile zaziqala ngamajeneretha ngaphambi kokwethula ama-coroutine aphelele. I-C# ekuqaleni yengeze ama-generator ngokusebenzisa yield kanye nephethini ye-iterator, yabe isiguqukela ku- async/await ukulingisa imisebenzi engahambisani ne-coroutines. I-JavaScript ilandele indlela efanayo: I-ES2015 yethule ama-generator njengecala elikhethekile lama-coroutines, futhi izinguqulo zakamuva zengeziwe async/await yakhelwe phezu kwezithembiso kanye namajeneretha.
Ezweni le-JVM, i-Java ngokwayo ayinikezi ama-coroutines omdabu, kodwa amathuluzi nezilimi ezizungezile zigcwalisa igebe. Amanye amalabhulali ashintsha i-bytecode ukuze alingise ukuziphatha kwe-coroutine, amanye asebenzisa i-JNI ukuze afinyelele izindlela ezithile zepulatifomu, kanti amanye athembele emicu ukuze alingise i-semantics ye-coroutine ngezindleko eziphakeme. I-Kotlin, ngakolunye uhlangothi, inikeza ama-coroutine njengesici selabhulali yeqembu lokuqala futhi ingasebenzisana nekhodi ye-Java (yize i-Java ingenakukwazi "ukumisa" ngokwemvelo futhi kufanele ivimbele noma isebenzise ama-futures).
Ukubhala imibhalo kanye nezilimi ezishintshashintshayo kuthathe izindlela ezahlukene. I-Python yaqala ngama-generator athuthukisiwe (i-PEP 342), yawandisa nge-subgenerator delegation (i-PEP 380), futhi ekugcineni yasungula ama-coroutines acacile endawo nge async/await (PEP 492), kamuva igcina lawo magama angukhiye ku-Python 3.7. I-Ruby isebenzisa ukuziphatha okufana ne-coroutine nge-fibers; I-Raku ne-Tcl zinikeza ukwakheka kwe-coroutine yomdabu; I-PHP 8.1 yengeze i-fibers ukusekela imitapo yolwazi esekelwe ku-coroutine ye-I/O engavumelani.
Izilimi ezigxile ohlelweni ziphinde zihlole amamodeli afana ne-coroutine ane-twist yawo. I-Go isebenzisa ama-goroutine — izinqubo ezilula, ezihlanganisiwe ezinama-stack anobukhulu obuguquguqukayo. Nakuba ama-goroutine engewona ama-coroutine ngomqondo oqinile (asondelene nezintambo eziluhlaza, futhi idatha yendawo ayihlali 'nezingcingo' eziningi ngomqondo we-coroutine), athatha isikhala sengqondo esifanayo nemisebenzi yezinga lomsebenzisi ephethwe yisheduli yesikhathi sokusebenza. I-D iveza ama-coroutine nge Fiber kulabhulali yayo ejwayelekile, futhi ezinye izinhlaka zizifaka ezinkundleni zokuxhumana ezilula zesitayela sejeneretha.
Faka i-C++: amalabhulali ngaphambi kwe-standard
Ngaphambi kwama-coroutine ajwayelekile e-C++, i-ecosystem yayithembele emitatsheni yezinkampani zangaphandle ukuletha i-semantics ye-coroutine olimini, kusetshenziswa ingxube yokushintsha komongo we-assembler, ama-platform API kanye ne-smart template metaprogramming.
I-Boost.Context ivele njengesisekelo esiphansi sokushintsha izimo zokusebenza kuzo zonke izakhiwo eziningi kanye nezinhlelo zokusebenza, inikeza indlela ephathekayo yokuphatha izitaki zesikhala somsebenzisi. Ngaphezu kwalokho, i-Boost.Coroutine kanye ne-Boost.Coroutine2 kamuva zinikeze izifinyezo ze-coroutine ezisezingeni eliphakeme, zisuka ekusekelweni kwamafomu alinganayo kanye nalawo angalingani ziye esibonakalayo sesimanje esingalingani esivumelana kangcono nama-idiom e-C++ anamuhla.
Amanye amaphrojekthi ahlole ama-engeli ahlukene, njenge-preprocessor-based stackless coroutines ezilingisa await/yield izincazelo, imitapo yolwazi enesihloko esisodwa egoqa imicu yesikhulumi, noma izinhlaka (ezifana ne-Mordor noma i-Oat++ coroutines) ezigxile ngqo ekufihleni ama-callback e-I/O angenasilinganiselo ngemuva kwekhodi elandelanayo efana ne-coroutine.
Lezi zinhlelo zemvelo zibonise ukuthi abathuthukisi be-C++ babelambele ukuvezwa okufana ne-coroutine, kodwa futhi baveze amaphuzu abuhlungu ezixazululo ze-ad-hoc: i-syntax engaguquki, ukukhathazeka okuphathekayo okuyinkimbinkimbi, ukulungisa amaphutha kanye namathuluzi angaqondakali, kanye nokuhlanganiswa okungeyona into encane nalo lonke umtapo wolwazi ojwayelekile.
Ama-coroutine e-C++20: imodeli ejwayelekile, engenazitaki
I-C++20 ekugcineni ilethe ama-coroutine olimini njengesici sekilasi lokuqala, kodwa ngomklamo omncane ngamabomu futhi osezingeni eliphansi. Esikhundleni sokuthumela isifinyezo esithile sezinga eliphezulu (njengokuthi “umsebenzi”, “ijeneretha” noma “ikusasa”) kulabhulali ejwayelekile, i-C++20 imise amabhlogo okwakha avumela amalabhulali ukuthi achaze izinhlobo zawo ezinobungani ne-coroutine.
Umsebenzi uba yi-coroutine uma umzimba wawo uqukethe noma yiziphi izakhi ezithile ze-coroutine: the co_await umqhubi ukuthi amise okwesikhashana kuze kube yilapho umcimbi noma inani elithile selilungile, co_yield ukuvezwa kokukhiqiza inani kanye nokumiswa (njengakumajeneretha), noma co_return isitatimende sokuqedela i-coroutine, ngokuzithandela kube nomphumela.
Uma i-compiler ithola noma yikuphi kwalokhu kwakhiwa, iguqula umsebenzi ube umshini wesimo onesimo esiqhubekayo esigcinwe "kuhlaka lwe-coroutine" olunikezwe inqwaba, ngaphandle kokuthi ukwenza ngcono kufakazela ukuthi isikhathi sohlaka sifakwe ngaphakathi komuntu oshaya ucingo futhi singafakwa kuhlaka lwesitaki somuntu oshaya ucingo. Lolu hlaka luphethe into yesithembiso, amakhophi ezimpikiswano, iziguquguquko zendawo ezihlala ezindaweni zokumiswa kanye nemethadatha yokugcina amabhuku yokuqalisa kabusha ukusebenza.
Okubaluleke kakhulu, ama-coroutine e-C++20 awanama-stackless: i-coroutine ingamisa kuphela ezindaweni zokumiswa ezicacile (co_await or co_yield) futhi ayikwazi ukuveza ngokusobala ngaphakathi kwezingcingo ezihlanganisiwe ngaphandle kokuthi leyo misebenzi nayo iyi-coroutines noma ihlanganyele ngenye indlela emishinini ye-coroutine. Lokhu kwenza ukusetshenziswa kube lula futhi kubikezelwe, ngezindleko zamandla athile okuveza uma kuqhathaniswa nemiklamo egcwele ngokugcwele.
Imikhawulo kanye nomjikelezo wokuphila kwe-coroutine ye-C++20
Akuwona wonke umsebenzi ku-C++20 ovunyelwe ukuba yi-coroutine; indinganiso ibeka imingcele eminingana ukuze imodeli ihlale iphilile. Ama-Coroutine awakwazi ukuba constexpr or consteval imisebenzi, azikwazi ukuba abakhi, ababhubhisi, noma main umsebenzi, futhi kungenzeka bangasebenzisi izimpikiswano eziguquguqukayo zesitayela se-C noma izinhlobo zokubuyisa izibambi-ndawo ezifana ne-plain auto ngaphandle kwemininingwane eyengeziwe.
Uma i-coroutine ibizwa okokuqala, ayiziphathi ngokushesha njengomzimba ojwayelekile osebenzayo. Esikhundleni salokho, isandulela esikhiqizwe yi-compiler sinikeza uhlaka lwe-coroutine (ngokuvamile nge- operator new), ikopisha amapharamitha omsebenzi kulolo hlaka (ngenani noma ngereferensi njengoba kumenyezelwe), yakha into yesithembiso bese ibiza promise.get_return_object(), okuvame ukuveza into ethile yesibambo noma yokusonga ebuyiselwa kumuntu oshaya ucingo.
Into yesithembiso uhlobo oluchazwe ngumsebenzisi, olutholwe ngokusebenzisa std::coroutine_traits ngokusekelwe kuhlobo lokubuyisa lwe-coroutine kanye nohlu lwamapharamitha, futhi inquma ukuthi imiphumela, okuhlukile kanye nezinqubomgomo zokumiswa zisebenza kanjani. Umhlanganisi uthola i- Promise thayipha bese ubiza izindlela ezifana initial_suspend(), final_suspend(), return_value() or return_void(), Futhi unhandled_exception() ngezigaba ezifanele emjikelezweni wokuphila kwe-coroutine.
Ekuqaleni kokubulawa, i-coroutine iyabiza promise.initial_suspend() futhi co_awaitnoma yini ebuyayo, okuvumela ababhali bezincwadi ukuthi banqume ukuthi uhlobo lwabo lwe-coroutine “luyalangazelela” (luqala ukusebenza ngokushesha) noma “luyavilapha” (lubuyela kumuntu oshaya ucingo kuze kube yilapho luqala kabusha ngokusobala). Lapho i-coroutine igcina iphelile nge co_return noma okuhlukile okungaphathwanga, kuyabiza promise.final_suspend(), okunikeza umtapo wolwazi ithuba lokugcina lokuhlela ukuqhubeka noma ukuhlanza.
Uma uhlaka lwe-coroutine lubhujiswa — kungaba ngemva kokuqedwa noma ngokusebenza okucacile kokubhubhisa esibambweni salo — Isikhathi sokusebenza sibhubhisa into yesithembiso, amakhophi amapharamitha nanoma yiziphi izakhamuzi ezibukhoma ezisele, bese sikhulula inkumbulo nge operator delete (noma ngomhlinzeki wesithembiso esithile uma enikeziwe). Uma ukwabiwa kwehluleka futhi isithembiso sichaza get_return_object_on_allocation_failure(), i-coroutine ingabonisa ngomusa ukwehluleka ngaphandle kokuphonsa std::bad_alloc.
co_await, abalindelwe kanye nabalindile
The co_await I-opharetha iyi-suspension yokuqala eyinhloko ohlelweni lwe-coroutine lwe-C++20, futhi ukuqonda indlela esebenza ngayo kubalulekile ekwakheni izifinyezo eziqinile ezingahambisani nesikhathi.
Uma ubhala co_await expr; ngaphakathi kwe-coroutine, umhlanganisi uqala ngokuguqula expr into "elindelekile", noma ngokudlula kukho promise.await_transform(expr) uma ilungu elinjalo likhona, noma ngokulisebenzisa njengoba linjalo. Bese linquma into "yomlindi" ngokubiza ilungu operator co_await kumuntu olindelekile, ongeyena ilungu operator co_await, noma nje ukuphatha lowo olindelwe njengomuntu olindayo uma engekho opharetha onjalo.
Umlindi kumele ahlinzeke ngemisebenzi emithathu ebalulekile: await_ready(), await_suspend(handle) futhi await_resume(). If await_ready() ibuya iyiqiniso, i-coroutine ayimisi futhi ibiza ngokuqondile await_resume(), okuvumela izindlela ezisheshayo zemisebenzi eseqediwe kakade. Uma ibuya ingamanga, i-coroutine iyama, isimo sayo sigcinwa kufreyimu, futhi await_suspend() ibizwa ngesibambo se-coroutine yamanje.
Inside await_suspend(), umlindi anganquma ukuthi enzeni ngesibambo se-coroutine: yihlele ukuze iqale kabusha kamuva kumphathi othile, qalisa kabusha enye i-coroutine, noma qalisa kabusha i-coroutine efanayo ngokushesha (kuye ngohlobo lokubuyisela kanye nenani le- await_suspend()). Lapho umsebenzi olindelwe usuphelile, othile ekugcineni uyafona handle.resume(), lapho ukulawula kubuyela khona ngaphambi nje await_resume(), bese await_resume() kuveza umphumela we co_await isisho.
Umtapo wolwazi ojwayelekile uthumela izinto ezimbili ezingabalulekile ezilindelekile: std::suspend_always futhi std::suspend_never, ezivame ukusetshenziswa ku initial_suspend() futhi final_suspend() ukusetshenziswa okubonisa ukuqala okuvilaphayo noma okulangazelelayo kanye nendlela yokuziphatha ekugcineni. Abalindi abanolwazi oluningi bangabamba isimo sokusebenza, isibonelo ukubopha ama-coroutine kuma-API e-I/O angavumelani, futhi leso simo sihlala ngaphakathi kohlaka lwe-coroutine ngaphesheya kwephuzu lokumiswa.
co_yield kanye nama-coroutines esitayela sejeneretha
The co_yield ukubonakaliswa kwakha phezu co_await ukusekela ukuziphatha okufana nokwe-generator, lapho i-coroutine ikhiqiza ngokuphindaphindiwe amanani omuntu oshaya ucingo aphindaphinda phezu kwawo.
Ngokomqondo, co_yield value; ikhula ibe ucingo oluya ku- promise.yield_value(value) bese kuba ukumiswa, ngokuvamile nge- co_await std::suspend_always noma okufanayo okulindelwe. Ukuqaliswa kwesithembiso kunesibopho sokugcina inani elitholiwe endaweni ethile efinyelelekayo (ngokulikopisha, ukulihambisa noma ukulibhekisa) ukuze umthengi akwazi ukulithola ngaphambi kokuba i-coroutine iqale kabusha.
Ikhodi yomtapo wolwazi esebenzisa ama-generator ivame ukuchaza uhlobo lwesithembiso oluveza izindlela zokufinyelela inani elikhiqizwe njengamanje kanye nokuhlanganiswa nezinqubo ezijwayelekile zokuphindaphinda, njengokuhlinzeka begin()/end() esimbozweni sesibambo bese uqhubekisela phambili i-coroutine engaphansi ekunyuseni ngakunye.
Ukuphathwa kwephutha, ukulenga izinkomba kanye nemininingwane ecashile
Ama-coroutine e-C++20 ahlangana nokuphathwa kwe-C++ okuhlukile ngesithembiso unhandled_exception() indlela, okubizwa ngumhlanganisi uma i-exception iphunyuka emzimbeni we-coroutine. I-coroutine iqhubekela ekumisweni kwayo kokugcina, futhi isithembiso kulindeleke ukuthi sihlele ukuthi iphutha lidluliselwe kunoma ngubani ongumnikazi wohlobo lomphumela we-coroutine.
Ngoba amapharamitha akopishwa noma abhekiselwa kufreyimu ye-coroutine ngesikhathi sokudala, Kumele kuqashelwe ngamapharamitha okubhekisela: uma ebhekisela ezintweni eziphela ngaphambi kokuba i-coroutine iqalwe kabusha, i-coroutine ingase isuse ukubhekisela kokubhekisela. Lena akuyona inkinga ethize ye-coroutine, kodwa isimo esiqhubekayo sohlaka senza kube lula ukuphila ngengozi kunezinto ezibhekiselwe kuzo.
Indinganiso iphinde yathuthuka ukuze icacise amacala angaphandle ngemibiko yamaphutha, njengokwenza okuthile kungasebenzi return_void ukusetha akwakhiwe kahle esikhundleni sokukhiqiza ukuziphatha okungachazwanga lapho kuwa ekugcineni kwe-coroutine, nokuvumela co_await ezimweni eziningi njengemizimba ye-lambda.
Ndawonye, le mithetho kanye nokulungiswa kwakha imodeli esezingeni eliphansi kodwa ebikezelwayo lapho imitapo yolwazi yezinga eliphezulu ingakha khona ngokuphephile, kusukela kuma-generator alula kuya ezinhlelweni zomsebenzi ezigcwele ze-async/await ezihlanganiswe nabaphathi kanye nabahleli bezinhlelo.
Kubonwe kusukela ngenhla, uhambo oluvela kumaqhinga omhlangano we-ad-hoc ku-C luya kuma-coroutine ahlelekile, angenazitaki, aqhutshwa yisithembiso se-C++20 kubonisa ukusunduza okuqhubekayo okuya ezifinyezweni eziphephile nezihlelekile zokuveza ukugeleza kokulawula okuyinkimbinkimbi, imisebenzi engahambisani kanye nokubala okunesimo, ngaphandle kokuyeka ukusebenza nokulawula abahleli bezinhlelo abathembele kukho.