Názor ke článku C++20: Jak se budí korutiny od Králík - Z mého pohledu zásadní problém C++ coroutines je,...

  • 2. 11. 2022 23:25

    Králík

    Z mého pohledu zásadní problém C++ coroutines je, že typ, který korutina vrací, pochází z nějaké konkrétní korutinové knihovny, tzn. přímo deklarace každé korutiny je závislá na konkrétním runtime. Tohle bych čekal, že by se snad mělo dobudoucna vyřešit..??? Ale přitom už teď je ta koncepce poměrně složitá ... obecně z toho mam pocit, že to dopladlo klasicky á la C++ - za mnoho komplexity málo muziky. (Asi jako když byly přidány move semantics :-/ )

    Ze stejného důvodu mi nepřijde moudré dávat do signatury korutiny resumption policy - korutinám by to mělo být víceméně jedno. Respektive bych resumption policy nahradil thread-safety příznakem (non-thread-safe korutina nemůže být přesouvána mezi vlákny v thread-poolu) a zbytek nechal na rozhodnutí/nas­tavení runtimu.

    Vraťme se k našemu příkladu se socketem. V okamžiku, kdy se na socketu objeví data, první to zjistí epoll, který je provozován v nějakém vlákně. To nakonec pošle notifikaci objektu socket a ten probudí korutinu. To vše se děje ve stejném vlákně. Běda pokud ta korutina se rozhodne na základě vrácených dat spustit nějaký komplikovaný výpočet. Tím jsme si dokonale zablokovali náš monitorovací nástroj!

    U nás v Rustu to máme zařízeno tak, že korutina (respektive v Rustu tomu říkáme Future) se nesnaží sama vymyslet, kde/jak se má probudit po awaitu, ale pouze zasignalizuje runtimu skutečnost, že by měla v dohledné době běžet přes callback (tzv. Waker) dodaný dynamicky runtimem, a je na runtimu, aby pak danou Future nějakým způsobem znovuspustil.

    Nutno dodat, že ani async kód v Rustu často není reálně nezávislý na runtimu (většina lidí prostě použíje ten nejpopulárnější, nebudu jmenovat :D), což je nutné kvůli implementaci socketů, časovačů apod. Ale přecijen to oddělení je obecně lepší a např. v mnoha async aplikacích to mam tak, že při 'ostrém' běhu se použije plnohodnotný thread-pool, zatímco v testech ten stejný kód běží na jednovláknovém runtimu.

    Co se týče složitosti runtimů, to je IMO nevyhnutelné. Pokud má runtime poskytovat dostatek featur pro psaní asynchronních aplikací (sockety a jiné I/O, časovače, fronty, sychnronizační primitiva, ...) a slušný výkon, tak IMO prostě moc KISS nebude...