Kako implementirati Coroutines u C ++

Sumnjam da se to može učiniti prijenosnim, ali postoji li kakvo rješenje? Mislim da se to može postići stvaranjem alternativnog stog i ponovnog pokretanja SP, BP i IP za ulazak u funkciju i dobivanje pristupa očuvanju IP-a i SP + BP oporavak. Destruktori i sigurnosne iznimke djeluju komplicirano, ali rješivo.

Je li gotovo? Je li to nemoguće?

56
23 сент. postavio / la Mike Elkins 23 ruj. 2008-09-23 18:31 '08 u 18:31 2008-09-23 18:31
@ 17 odgovora

Da, može se napraviti bez problema. Sve što trebate je mali kôd za izgradnju da premjestite stog poziva na novi namjenski stack na hrpi.

Ja bih pogledati potaknuti :: coroutine knjižnica .

Jedina stvar na koju treba obratiti pozornost je prelijevanje stogova. Na većini operacijskih sustava prelijevanje stog uzrokovat će segfault, budući da stranica virtualne memorije nije prikazana. Međutim, ako steku dodijelite hrpu, ne dobivate nikakva jamstva. Samo imajte to na umu.

85
23 сент. Odgovor je dat Ted 23 Sep. 2008-09-23 18:38 '08 u 18:38 2008-09-23 18:38

U POSIX-u možete koristiti podrutine makecontext () / swapcontext () za izvođenje konteksta izvođenja. U sustavu Windows možete koristiti API za vlakna. Inače, sve što trebate je mali kod za montažu ljepila koji prebacuje kontekst stroja. Provodio sam koroutine s ASM (za AMD64) i swapcontext (); niti vrlo teško.

border=0
17
23 сент. odgovor je dan zvrba 23 sep . 2008-09-23 19:05 '08 u 19:05 2008-09-23 19:05

Za potomstvo

Dmitry Vyukov sretan web stranica ima pametan trik koristeći ucontext i setjump za coroutine modeliranje u C + +.

Osim toga, knjižnica konteksta Olivera Kowalkea nedavno je usvojena u Boost, pa se nadam da ćemo vidjeti ažuriranu verziju boost.coroutine, koja radi na x86_64 u skoroj budućnosti.

12
25 февр. Odgovor je dan na : 25. veljače. 2012-02-25 01:22 '12 u 1:22 2012-02-25 01:22

Nema jednostavnog načina za primjenu koroutina. Budući da je sam coroutine izvan apstrakcije C / C ++ stog, baš kao i nit. Stoga se ne može održavati bez promjene razine jezika za podršku.

Trenutno (C ++ 11), svi postojeći C ++ koroutini implementatori temelje se na hakiranju razine sklopa koju je teško sigurno i pouzdano preći platforme. Da bi bili pouzdani, moraju biti standardni i rukovati ih prevodioci, a ne biti hakirani.

Za to postoji standardna ponuda - N3708 . Provjerite ako ste zainteresirani.

8
26 окт. odgovor je dao Eonil 26. listopada. 2013-10-26 09:13 '13 u 9:13 2013-10-26 09:13

Možda vam je bolje da budete s iteratorom nego s koroutinom, ako je moguće. Dakle, možete nastaviti next() poziv da biste dobili sljedeću vrijednost, ali možete spremiti svoje stanje kao članske varijable umjesto lokalnih varijabli.

To može učiniti stvari ugodnijima. Drugi C ++ programer možda neće odmah razumjeti coroutine, dok će možda biti bolje upoznati s iteratorom.

7
23 сент. Odgovor dao Steve g 23. rujna 2008-09-23 18:33 '08 u 18:33 2008-09-23 18:33

Ne mislim da C ++ ima puno cjelovitih, čistih implementacija. Jedan od pokušaja koji mi se sviđa je knjižnica protothread .

5
23 сент. odgovor je dan yrp 23 sep . 2008-09-23 18:37 '08 u 18:37 2008-09-23 18:37

Je li COROUTINE prijenosna knjižnica C ++ za coroutin niz koji vas usmjerava u pravom smjeru? Izgleda kao elegantno rješenje koje je trajalo test vremena ... ima 9 godina!

DOC mapa sadrži pdf dokument iz članka A Portable C ++ Library za Coroutine Sequencing Keld Helsgauna, koji opisuje biblioteku i daje kratke primjere njezine uporabe.

[update] Ja sam ga uspješno koristiti. Radoznalost me je poboljšala, pa sam pogledao ovo rješenje i našao da dobro radi za problem na kojem radim neko vrijeme!

5
23 сент. odgovor dan Dan 23. rujna 2008-09-23 18:33 '08 u 18:33 2008-09-23 18:33

Za one koji žele znati kako mogu koristiti Corouts u C ++ prijenosnom načinu rada, morat ćete čekati na C ++ 17. Odbor za standarde radi na ovoj značajki, vidi članak N3722 . Da biste saželi trenutni nacrt dokumenta, umjesto Async i Očekujte, ključne riječi će se nastaviti i čekati.

Pogledajte eksperimentalnu implementaciju u Visual Studio 2015 za igranje s eksperimentalnom implementacijom Microsofta. Čini se da nema implementacije zveke.

Dobar razgovor s Cppcon Coroutines negativnom apstraktom fakture opisuje prednosti korištenja Coroutines u C ++ i kako to utječe na jednostavnost i izvedbu koda.

Trenutačno moramo koristiti knjižnične implementacije, ali u bliskoj budućnosti imat ćemo coroutine kao glavnu funkciju C ++.

Update: Izgleda da se implementacija coroutina ne pretvara u C ++ 17, ali to će biti tehnička specifikacija ( p0057r2 ). S druge strane, čini se da je njihova podrška povezana s zastavom -fcoroutines_ts i ažuriranjem Visual Studio 2015 Update 2. Ključne riječi su također dodane. Tako co_await, co_yield, itd.

4
19 февр. Odgovor je dan Atifm 19. veljače 2016-02-19 18:13 '16 u 18:13 2016-02-19 18:13

Nova knjižnica, Boost.Context , objavljena je danas pomoću prijenosnih funkcija za izvođenje suroutina.

3
21 авг. odgovor dao Jeff Trull 21. kol. 2012-08-21 18:34 '12 u 18:34 2012-08-21 18:34

Ovo je stara nit, ali predlažem hakiranje Duff uređaja, koji ne ovisi o OS-u (koliko se sjećam):

C koroutine pomoću Duff uređaja

Kao primjer, ovdje je telnet biblioteka koju sam modificirala da koristim coroutines umjesto fork / threads: Telnet cli knjižnica pomoću coroutines

A budući da je standard C do C99 u suštini pravi podskup C + +, dobro radi s C ++.

3
04 дек. Odgovor koji je dao Erik Alapää 04 2015-12-04 18:48 '15 u 18:48 2015-12-04 18:48

Temelji se na makroima (cringe), ali sljedeća web-lokacija omogućuje implementaciju generatora jednostavnu za upotrebu: http://www.codeproject.com/KB/cpp/cpp_generators.aspx

2
04 нояб. odgovor je dan Mark 04 Nov. 2010-11-04 16:31 '10 u 16:31 2010-11-04 16:31

Došao sam do koda bez asm . Ideja je da se koristi funkcija kreiranja niti sustava kako bi se inicijalizirali stog i kontekst te pomoću setjmp / longjmp prebaciti kontekst. Ali to se ne prenosi ako ste zainteresirani, pogledajte tešku verziju pthread-a .

2
12 авг. odgovor dano rox 12 kol. 2014-08-12 20:34 '14 u 20:34 2014-08-12 20:34

https://github.com/tonbit/coroutine je sintaktička implementacija asimetrične prateće verzije C ++ 11, koja podržava primitive / resume / yield / wait i model kanala. Ona implementira preko ucontext / fiber, ne ovisi o poticaj, to radi na linux / windows / macOS. Ovo je dobra polazna točka za istraživanje implementacije u C ++.

1
16 нояб. odgovor dati atto_mu 16 Stu. 2016-11-16 04:58 '16 u 4:58 2016-11-16 04:58

WvCont je dio WvStreamsa , koji implementira tzv. Polu-hlače. Malo ih je lakše obraditi nego punopravni zadaci: zovete ga i vraća se onom koji ga je nazvao.

Provodi se pomoću fleksibilnijeg WvTask-a, koji podržava sveobuhvatne kopuutine; Možete ga pronaći u istoj knjižnici.

Radi na win32 i Linux, barem, a možda i na bilo kojem drugom Unix sustavu.

0
23 сент. Odgovori apenwarr 23. rujna 2008-09-23 22:28 '08 u 10:28 pm 2008-09-23 22:28

Pogledajte moju implementaciju, ona ilustrira asm hacking točku i jednostavna je:

https://github.com/user1095108/generic/blob/master/coroutine.hpp

0
05 янв. odgovor daje korisnik1095108 05 jan. 2017-01-05 11:29 '17 u 11:29 2017-01-05 11:29

Umjesto toga uvijek biste trebali koristiti tokove; osobito u modernoj opremi. Ako imate posao koji se može logički podijeliti na ko-rutine, korištenje niti znači da se rad može izvoditi istodobno koristeći zasebne izvršne jedinice (procesorske jezgre).

Ali možda želite koristiti coroutine, možda zato što imate dobro testiran algoritam koji je već tako napisan i testiran, ili zato što portirate kôd napisan na ovaj način.

Ako koristite Windows, trebali biste pogledati vlakna . Vlakna će vam pružiti popratnu strukturu s OS podrškom.

Nisam upoznat s drugim OS-ovima da bih tamo preporučio alternative.

0
23 сент. odgovor daje Euro Micelli na 23. rujna . 2008-09-23 18:58 '08 u 18:58 2008-09-23 18:58

Kroutine sam pokušao sam implementirati koristeći C ++ 11 i teme:

 #include <iostream> #include <thread> class InterruptedException : public std::exception { }; class AsyncThread { public: AsyncThread() { std::unique_lock<std::mutex> lock(mutex); thread.reset(new std::thread(std::bind( this))); conditionVar.wait(lock); // wait for the thread to start } ~AsyncThread() { { std::lock_guard<std::mutex> _(mutex); quit = true; } conditionVar.notify_all(); thread->join(); } void run() { try { yield(); for (int i = 0; i < 7; ++i) { std::cout << i << std::endl; yield(); } } catch (InterruptedException e) { return; } std::lock_guard<std::mutex> lock(mutex); quit = true; conditionVar.notify_all(); } void yield() { std::unique_lock<std::mutex> lock(mutex); conditionVar.notify_all(); conditionVar.wait(lock); if (quit) { throw InterruptedException(); } } void step() { std::unique_lock<std::mutex> lock(mutex); if (!quit) { conditionVar.notify_all(); conditionVar.wait(lock); } } private: std::unique_ptr<std::thread> thread; std::condition_variable conditionVar; std::mutex mutex; bool quit = false; }; int main() { AsyncThread asyncThread; for (int i = 0; i < 3; ++i) { std::cout << "main: " << i << std::endl; asyncThread.step(); } } 
-2
27 мая '12 в 21:10 2012-05-27 21:10 odgovor je dao jhasse 27. svibnja '12 u 21:10 2012-05-27 21:10

Ostala pitanja o oznake ili pitati pitanje