Vlákno názorů ke článku Jak na korutiny v C++20 od peci1 - Jen se hloupe zeptam: kdyz zavolam co_await fetch(url),...

  • 18. 10. 2022 9:06

    peci1
    Stříbrný podporovatel

    Jen se hloupe zeptam: kdyz zavolam co_await fetch(url), tak kdo vykona tu funkci fetch? Musim mit nejake separatni vlastnorucne managovane vlakno, ktere kouka do nejakeho seznamu korutin a ty pousti? Nebo se nejake vlakno pro moji korutinu objevi nejak automagicky? A nebo tomu vubec nerozumim?

  • 18. 10. 2022 12:21

    Ondřej Novák

    funkce fetch() musí být napsaná tak, aby vrátila objekt awaitera. Tam začíná celá magie. Představ si, že to není fetch (moc složitý) ale třeba recv (ze socketu)

    co_await postupně zavolá tři funkce awaitera
    • await_ready -> awaiter může skusit číst ze socketu neblokovaně. Pokud obdrží EWOULDBLOCK, vrátí false, pokud obdrží data, vrátí true - pak se rovnou volá await_resume
    • await_suspend -> awaiter vezme handle korutiny a zaregistruje ho někam, do nějakého dispatcheru, který monitoruje sockety - předá socket a handle korutiny. Tenhle dispatcher si samozřejmě musíš někde mít implementovaný. Nejspíš bude mít nějaké vlákno, ve kterém to provádí, nejspíš čeká na epoll a když se dočká, provede nějaké třídění a buzení registrovaných korutin
    • teď korutina spí, dokud není vzbuzena. pak pokračuje na await_resume
    • await_resume -> tam si awaiter vyzvedne data vrátí je jako výsledek operace. V tomto příkladě, pokud awaiter již má data načteny, protože se mu to povedlo při await_ready, tak je jen vrátí, pokud nemá, tak teď udělá recv(), to nejspíš projde bez čekání a vysledek vrátí.

    Takže tvá odpověď na otázku. Záleží na implementaci. Pokud daná funkce něco řeší asynchroně, musí si k tomu zařídit nějaká vlákna a postavit vlastní asynchroní systém. Korutině je to jedno, ta komunikuje s tím mechanismem přes awaitera, což je takový zástupce toho mechanismu. Výhodou je, že dokud celá operace je stále v procesu, instance awaitera je po celou dobu k dispozici. Jakmile je operace kompletní, awaiter je zdestruován