C++20 coroutines (co_await)
От: okman Беларусь https://searchinform.ru/
Дата: 06.01.21 20:34
Оценка: 4 (2)
Всем привет!

Изучаю C++20. В целом все понятно, но одна вещь вызывает наибольшие затруднения — корутины.

Насколько я понял, в C++20 появился некий интерфейс, реализуя который, разработчик может обеспечить нужное ему
поведение, вплоть до низкоуровневых деталей, таких как выполнение задачи в отдельном потоке (например, в Windows
это можно сделать с помощью CreateThreadpoolWork/SubmitThreadpoolWork). Готовую библиотечную реализацию корутин,
как выясняется, не "завезли" (ждите C++23). Я прав?

Ну и тогда главный вопрос: где можно найти более-менее полноценное и толковое описание этого интерфейса?

Я пока плохо понимаю, как связаны task, promise и awaiter, чем отличаются "обычная" корутина и noop-coroutine,
куда конкретно нужно вставлять вызовы co_await/co_yield/co_return. А ведь там еще есть "загадочные" operator
co_await, await_transform, coroutine_handle, разделение на stackfull и stackless...

Выглядит это все ну очень странно и совершенно непонятно. Да что там говорить, почти весь код на эту тему, который
довелось посмотреть, просто выносит мозг!

  Скрытый текст
#include <coroutine>
#include <utility>
#include <iostream>
 
template<class T>
struct task {
    struct promise_type {
        auto get_return_object() {
            return task(std::coroutine_handle<promise_type>::from_promise(*this));
        }
        std::suspend_always initial_suspend() { return {}; }
        struct final_awaiter {
            bool await_ready() noexcept { return false; }
            void await_resume() noexcept {}
            std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> h) noexcept {
                // final_awaiter::await_suspend is called when the execution of the
                // current coroutine (referred to by 'h') is about to finish.
                // If the current coroutine was resumed by another coroutine via
                // co_await get_task(), a handle to that coroutine has been stored
                // as h.promise().previous. In that case, return the handle to resume
                // the previous coroutine.
                // Otherwise, return noop_coroutine(), whose resumption does nothing.
 
                auto previous = h.promise().previous;
                if (previous) {
                    return previous;
                } else {
                    return std::noop_coroutine();
                }
            }
        };
        final_awaiter final_suspend() noexcept { return {}; }
        void unhandled_exception() { throw; }
        void return_value(T value) { result = std::move(value); }
        T result;
        std::coroutine_handle<> previous;
    };
 
    task(std::coroutine_handle<promise_type> h) : coro(h) {}
    task(task&& t) = delete;
    ~task() { coro.destroy(); }
 
    struct awaiter {
        bool await_ready() { return false; }
        T await_resume() { return std::move(coro.promise().result); }
        auto await_suspend(std::coroutine_handle<> h) {
            coro.promise().previous = h;
            return coro;
        }
        std::coroutine_handle<promise_type> coro;
    };
    awaiter operator co_await() { return awaiter{coro}; }
    T operator()() {
        coro.resume();
        return std::move(coro.promise().result);
    }
private:
    std::coroutine_handle<promise_type> coro;
};
 
task<int> get_random() {
    std::cout << "in get_random()\n";
    co_return 4;
}
task<int> test() {
    task<int> v = get_random();
    task<int> u = get_random();
    std::cout << "in test()\n";
    int x = (co_await v + co_await u);
    co_return x;
}
 
int main() {
    task<int> t = test();
    int result = t();
    std::cout << result << '\n';
}



Пробовал вникать в примеры на en.cppreference.com, смотрел как устроены асинхронные вызовы в C++/WinRT, был на Хабре,
на MSDN, на MSVC Team Blog, смотрел исходники библиотеки cppcoro, но ясности не прибавилось.

> "Фреймворк для написания корутин состоит из более чем 20 функций которые частично нужно реализовать, а

> частично могут быть переписаны (Хабр, "Корутины в C++20. Часть 1").

Что это за функции? Где про это почитать подробнее? И т.д.


Ссылки ниже, вдруг кому-то пригодится:

Standard library header <coroutine>
https://en.cppreference.com/w/cpp/header/coroutine

C++ Coroutines in Visual Studio 2019 Version 16.8
https://devblogs.microsoft.com/cppblog/c-coroutines-in-visual-studio-2019-version-16-8/

lewissbaker/cppcoro
https://github.com/lewissbaker/cppcoro

C++20. Coroutines
https://habr.com/ru/post/519464/
Re: C++20 coroutines (co_await)
От: reversecode google
Дата: 06.01.21 20:54
Оценка: 14 (2)
если и это не поймете, значит оно не для вас

корутины
Re[2]: C++20 coroutines (co_await)
От: bnk СССР http://unmanagedvisio.com/
Дата: 06.01.21 23:16
Оценка:
Здравствуйте, reversecode, Вы писали:

R>если и это не поймете, значит оно не для вас


R>корутины


Я правильно понимаю, что это просто async/await наконец сделали в С++? Или это что-то большее?
В смысле, async/await по типу как он есть в С#, javascript, и т.п.?
Отредактировано 06.01.2021 23:29 bnk . Предыдущая версия .
Re[3]: C++20 coroutines (co_await)
От: reversecode google
Дата: 06.01.21 23:29
Оценка: +1 :))) :))
можно и так сказать
только сделали сильно круче чем в расте или других языках
очень огромные возможности для кастомизации
  музыченко не читать
даже в ядре можно поюзать если хочеться
Re[4]: C++20 coroutines (co_await)
От: bnk СССР http://unmanagedvisio.com/
Дата: 06.01.21 23:34
Оценка:
Здравствуйте, reversecode, Вы писали:

R>можно и так сказать

R>только сделали сильно круче чем в расте или других языках
R>очень огромные возможности для кастомизации

Ну если это даже круче чем у других, то это конечно хорошо.
Посмотрел вики выглядит вроде практически так же как и в других языках.
https://en.wikipedia.org/wiki/Async/await

А в чем крутость по сравнению с остальными, если в дух словах?
Re[5]: C++20 coroutines (co_await)
От: landerhigh Пират  
Дата: 06.01.21 23:46
Оценка:
Здравствуйте, bnk, Вы писали:

bnk>А в чем крутость по сравнению с остальными, если в дух словах?


Не уверен насчет крутости. Пока сам не использовал всерьез, лишь игрался невсерьез.

-Они stackless. Значит, yield'ануть из глубин вложенных вызовов функций не выйдет.
+Они stackelss. Значит, оверхед по памяти ограничен и оверхед на переключение контекста должен быть минимальным

Этот плюс, имхо, должен перекрывать минус на порядок.
www.blinnov.com
Re[5]: C++20 coroutines (co_await)
От: reversecode google
Дата: 06.01.21 23:49
Оценка:
стейт машину в которые корутины разворачиваются можно кастомизировать в действиях на вход/выход/експрешин/возвращаемые значение
ключевые функции при кастомизации могут быть кастомизированы в разных возврат значениях
и это дает еще больше вариантов логики обработки

и хз есть ли в других языках
но в С++ можно еще делать симметричные корутины

из не достатков, пока что их не зацепили к сетевым функциям
в С++23 обещают и сеть и все остальное завести и прецепить

но asio уже можно с ними использовать
или свою логику над сокетами и таймерами если хоцца

корутины в С++ стейтлесс, как и у раста
в отличии от гоу и питона где они вроде бы стекфул
Re[5]: C++20 coroutines (co_await)
От: Тёмчик Австралия жж
Дата: 07.01.21 05:10
Оценка:
Здравствуйте, bnk, Вы писали:

bnk>А в чем крутость по сравнению с остальными, если в дух словах?


— Чем круче корутин в C++ чем в C# (Python, JS, десятки их)?
— Тем, что в C++.
Re: C++20 coroutines (co_await)
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 07.01.21 06:48
Оценка:
Здравствуйте, okman, Вы писали:

O>Изучаю C++20. В целом все понятно, но одна вещь вызывает наибольшие затруднения — корутины.

А неужели никто научной/полунаучной статьи на эту тематику не написал?
Sic luceat lux!
Re[2]: C++20 coroutines (co_await)
От: okman Беларусь https://searchinform.ru/
Дата: 07.01.21 08:07
Оценка: +2
Здравствуйте, reversecode, Вы писали:

R>если и это не поймете, значит оно не для вас


R>корутины


О, вот эта "новая реальность" меня немного расстраивает.
Теперь документация по языку и его фичам — это или набор слайдов от непонятного чувака, или отсылки ко всяким proposal?
Re[2]: C++20 coroutines (co_await)
От: okman Беларусь https://searchinform.ru/
Дата: 07.01.21 08:12
Оценка: +1
Здравствуйте, Kernan, Вы писали:

K>А неужели никто научной/полунаучной статьи на эту тематику не написал?


Так даже не статью ищу, а просто нормальную доку с описанием классов/методов и хотя бы поверхностным "how to".
А в таком виде как сейчас оно просто неюзабельно, по крайней мере для меня. Как можно использовать то, что недокументированно?
Даже на MSDN нет почти никакого описания, кроме ссылок на 2-3 статьи в блоге...
Re[6]: C++20 coroutines (co_await)
От: okman Беларусь https://searchinform.ru/
Дата: 07.01.21 08:14
Оценка: +2
Здравствуйте, reversecode, Вы писали:

R>стейт машину в которые корутины разворачиваются можно кастомизировать в действиях на вход/выход/експрешин/возвращаемые значение

R>ключевые функции при кастомизации могут быть кастомизированы в разных возврат значениях
R>...
R>но в С++ можно еще делать симметричные корутины
>...
R>корутины в С++ стейтлесс, как и у раста

reversecode, думаю, не я один был бы весьма благодарен за более подробное и развернутое описание.
Re[6]: C++20 coroutines (co_await)
От: kov_serg Россия  
Дата: 07.01.21 09:06
Оценка: 8 (1)
Здравствуйте, reversecode, Вы писали:

R>стейт машину в которые корутины разворачиваются можно кастомизировать в действиях на вход/выход/експрешин/возвращаемые значение

R>ключевые функции при кастомизации могут быть кастомизированы в разных возврат значениях
R>и это дает еще больше вариантов логики обработки
Вот заглянешь в чужой код и у всех будут свои реализации — шикарно.

R>и хз есть ли в других языках

R>но в С++ можно еще делать симметричные корутины
ждём inlineing для них, что бы в софтовый получить hyperthreading.

R>из не достатков, пока что их не зацепили к сетевым функциям

R>в С++23 обещают и сеть и все остальное завести и прецепить
где публикуют собрание обещаний?

R>корутины в С++ стейтлесс, как и у раста

R>в отличии от гоу и питона где они вроде бы стекфул
а dynamic memory less есть?

https://gist.github.com/MattPD/9b55db49537a90545a90447392ad3aeb
Re[3]: C++20 coroutines (co_await)
От: rg45 СССР  
Дата: 07.01.21 10:04
Оценка:
Здравствуйте, okman, Вы писали:

O>Так даже не статью ищу, а просто нормальную доку с описанием классов/методов и хотя бы поверхностным "how to".

O>А в таком виде как сейчас оно просто неюзабельно, по крайней мере для меня. Как можно использовать то, что недокументированно?
O>Даже на MSDN нет почти никакого описания, кроме ссылок на 2-3 статьи в блоге...

https://en.cppreference.com/w/cpp/language/coroutines

Вот это смотрел уже?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: C++20 coroutines (co_await)
От: reversecode google
Дата: 07.01.21 10:56
Оценка:
офф дока стандарта вам не зашла
ок
если и ссылка на разжевывание с картинками и стрелочками на русском вам не зашла
значит это или такой троллинг или корутины не для вас
Re: C++20 coroutines (co_await)
От: flаt  
Дата: 07.01.21 11:07
Оценка: 17 (2)
Здравствуйте, okman, Вы писали:



O>Пробовал вникать в примеры на en.cppreference.com, смотрел как устроены асинхронные вызовы в C++/WinRT, был на Хабре,

O>на MSDN, на MSVC Team Blog, смотрел исходники библиотеки cppcoro, но ясности не прибавилось.

Можно ещё посмотреть выступления их автора, Гора Нишанова: https://www.youtube.com/results?search_query=gor+nishanov+coroutines

Но вообще, тоже подпишусь в надежде на достойную доку.
Re[2]: C++20 coroutines (co_await)
От: reversecode google
Дата: 07.01.21 11:43
Оценка:
F>Но вообще, тоже подпишусь в надежде на достойную доку.

мифическая дока... ну что ж, будем ждать ее

у кого есть связь с комитетом ?
пусть напишут правильную доку по корутинам, а то ж никому ничего не понятно
Re[6]: C++20 coroutines (co_await)
От: reversecode google
Дата: 07.01.21 11:48
Оценка: :))) :))) :)
предлагаю всех кто чего то не осилил в С++ называть — тёмками

так сказать, увековечить первого не осилившего героя на века
Re[6]: C++20 coroutines (co_await)
От: vopl Россия  
Дата: 07.01.21 11:58
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>-Они stackless. Значит, yield'ануть из глубин вложенных вызовов функций не выйдет.


А можешь конкретный пример привести, пожалуйста?
Re[6]: C++20 coroutines (co_await)
От: reversecode google
Дата: 07.01.21 12:03
Оценка:
L>-Они stackless. Значит, yield'ануть из глубин вложенных вызовов функций не выйдет.

получиться, если есть хендл на корутину на которую нужно перейти(выпрыгнуть)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.