Hlavní navigace

Vlákno 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...

  • 3. 11. 2022 16:45

    Ondřej Novák

    A nebude ten thread safety příznak něco podobného? Policy ve skutečnosti se odkazuje na třídu, která dodatečně implementuje ona pravidla, která policy představují.

    Rozšíření parametrů šablony není problém, nikdo vám nebrání udělat si


    template<typename T> using dtask = task<T, resumption_po­licy::dispatcher>

    a od toho okamžiku používat dtask<> místo task<>. Trochu záměrně nezmíněnou vlastností mé implementace je, že jakýkoliv task<T, policy> lze později převést na task<T, void>, ten se zkráceně dá zapsat jako task<T>, takže uživatel takové korutiny už nepotřebuje řešit policy,

    Jak jsem psal, ten návrh jsem udělal namísto původně rozpracovaného jiného návrhu, který je nyní pod policy resumption_po­licy::queue, kde právě ono obnovení korutiny je signalizováno - korutina je vložena do lokální fronty - a jakmile je vlákno volné, může se věnovat frontě a postupně jednu po druhé provede. Ale takový systém je víc vázán na konkrétní, mnou dodaný runtime. Místo toho jsem pak šel cestou obecnější, kdy právě v návrhu umožňuji aby korutina si sama mohla vybrat jak bude buzena. Dokážu si představit implementacu dispatch-like aplikace, kde budu mít jedno hlavní vlákno a v něm se bude spouštět většina korutin všechny vázané na dispatcher policy a to aniž bych musel upravit jedinou čárku kódu v mé knihovně.

    Právě snaha minimalizovat runtime, nechat implementační volnost je možná důvod, proč se toto v C++ neřeší.

    Ještě k move semantics. Používám na denní bázi a nemyslím si, že by to bylo málo muziky. Naopak vytrhalo dost trnů z pat.

  • 4. 11. 2022 0:37

    Králík

    Místo toho jsem pak šel cestou obecnější, kdy právě v návrhu umožňuji aby korutina si sama mohla vybrat jak bude buzena.
    No jo, ale pak nemůžu udělat to, co jsem popsal výše, tj. schedulovat v testech ty samé korutiny jinak než při ostrém běhu...