Re[8]: C++20 coroutines (co_await)
От: rg45 СССР  
Дата: 07.01.21 20:05
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Там интересные примеры:

BFE>

BFE>В послевоенные годы множество калек нуждались в помощи пластических хирургов.


Так это только расширяет набор синонимов, а значит, укрепляет мою дискуссионную позицию
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[7]: C++20 coroutines (co_await)
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 07.01.21 20:07
Оценка:
Здравствуйте, rg45, Вы писали:

R>Выбирай: Синонимы к слову «калька»

R>От себя еще накину пару-тройку: сдувание, передирание, сдирание, передувание.

И какой из них, на Ваш взгляд, следовало использовать в качестве официального термина в науке лингвистике?
Re[8]: C++20 coroutines (co_await)
От: rg45 СССР  
Дата: 07.01.21 20:10
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>И какой из них, на Ваш взгляд, следовало использовать в качестве официального термина в науке лингвистике?


Я предоставляют тебе право выбора. В какой из перечисленных категорий, на твой взгляд, слово "калька" было первым и не имело аналогов?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: C++20 coroutines (co_await)
От: student__  
Дата: 07.01.21 21:38
Оценка:
Так это новый виток в эре копроэкономики наступил, когда вместо грамотной технической документации в сеть выплевывается либо автоматически сгенерированная справочная информация, жиденько откомментированная специалистом, либо поток сознания в виде тех же proposal, написанных, как средневековые философские трактаты, с закосом на наукообразность. А в опенсорс это вообще модус операнди, ведь продукт с его использованием делает только капиталист. А твоя де факто обязанность как инженера — социализация внутри релевантной тусовки инженеров, и попутное выяснение актуальных измениний в проекте. Вобщем-то, так всегда было, но чем больше капитал использует квалифицированную рабскую силу (опенсорс), тем больше подразумевается, что "все эти хомячки-хакеры... им же только хавку регулярно подбрасывай, а они там уже сами в своем кругу разберутся, какую документацию, и в каком виде писать, и типа организовывать их не нужно".
Отредактировано 07.01.2021 21:40 student__ . Предыдущая версия . Еще …
Отредактировано 07.01.2021 21:39 student__ . Предыдущая версия .
Отредактировано 07.01.2021 21:38 student__ . Предыдущая версия .
Re[10]: C++20 coroutines (co_await)
От: reversecode google
Дата: 07.01.21 21:49
Оценка:
причем здесь стекфул корутины в контексте обсуждаемой имплементации в С++ стеклесс ?

вообще все очень притянуто зауши учитывая что я за последние лет 10
и стекфул корутин не наблюдал в любом маломайски популярном или топ нейм продукте на С или С++
Re: C++20 coroutines (co_await)
От: _NN_ www.nemerleweb.com
Дата: 08.01.21 06:46
Оценка:
Здравствуйте, okman, Вы писали:

O>как выясняется, не "завезли" (ждите C++23). Я прав?


Всё верно.
Создали каркас, а там каждый пусть пишет реализацию .
Если бы ещё и занялись реализацией, мы бы не увидели ничего в C++20

Можете посмотреть разработку коллеги как раз решающую эту проблему.
cncurencpp
Автор: _NN_
Дата: 06.08.20
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: C++20 coroutines (co_await)
От: х Россия  
Дата: 09.01.21 05:22
Оценка: 53 (4)
Здравствуйте, okman, Вы писали:

O>Всем привет!


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


Всё просто, если немного упростить с деталями:
реализуешь шаблон coroutine_traits с внутренней структурой promise_type — это объект который будет использоваться в функции использующей корутины для управления работой.

По сути функция
T f(T1 a1, T2 a2 ...) {

   co_await ...
   co_return ...
}


преобразуется в:
T f(T1 a1, T2 a2 ...) {
struct Arguments {
  coroutine_traits<T, T1, T2...>::promise_type this_corutine;
  T1 a1;
  T2 a2;
};
  Arguments args { coroutine_traits::promise_type, std::move(a1), std::move(a2) ... };
  ...
  return args->this_corutine.get_return_object();
}


То есть при первом же вызове оператора корутин формируется структура для работы с ними.


Далее когда есть вызов:
auto res = co_await fnested(...);


и пусть при этом
TResult fnested(...)


тогда co_await преобразуется в (понятно, что move расставлены не корректно, но они для демонстрации передачи владением объекта в другой код)
  auto fnested_awaiter = operator co_await(fnested(...));

  auto rest_code = [std::move(fnested_awaiter), std::move(args)]() {
      auto res = fnested_awaiter.await_resume();
      ...//Rest code
  };

  if(!fnested_awaiter.await_ready()){
    //Suspend
    fnested_awaiter.await_suspend(std::move(rest_code));
  } else {
    rest_code();
  }


То есть вызывается вложенная функция и у результата этой функции спрашивается готов ли результат. Если он готов, то результат забирается через await_resume иначе просто остаток функции упаковывается в лямбду и через await_suspend говорится, что когда вложенная функция отработает надо вызвать нашу лямбду для продолжения выполнения нашей функции.

co_return ещё проще — он просто вызывает метод return_value для вашего promise_type.

Таким образом
T f(T1 a1, T2 a2 ...) {

   auto res = co_await fnested(...);
   co_return ...;
}


преобразуется в что-то вида:
T f(T1 a1, T2 a2 ...) {
 struct Arguments {
  coroutine_traits<T, T1, T2...>::promise_type this_corutine;
  T1 a1;
  T2 a2;
 };
 Arguments args { coroutine_traits::promise_type, std::move(a1), std::move(a2) ... };
 
 auto fnested_awaiter = operator co_await(fnested(...));
 auto rest_code = [std::move(fnested_awaiter), std::move(args)]() {
      auto res = fnested_awaiter.await_resume();
      args->this_corutine.return_value(...);//co_return ...;
  };
 if(!fnested_awaiter.await_ready()){
  //Suspend
  fnested_awaiter.await_suspend(std::move(rest_code));
 } else {
  rest_code();
 }
 return args->this_corutine.get_return_object();
}


Собственно всё. Дальше Вы сами решаете как строить цепочки функций, как производить "просыпание" и т.п. В этом мощь. В отличии от C# вы тут можете выбирать ту модель которую считаете оптимальной.

Более детально можно посмотреть реализацию тут.
С уважением Вадим.
Отредактировано 09.01.2021 6:49 х . Предыдущая версия . Еще …
Отредактировано 09.01.2021 6:48 х . Предыдущая версия .
Отредактировано 09.01.2021 5:24 х . Предыдущая версия .
Re[6]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 09.01.21 14:44
Оценка: 5 (2)
Здравствуйте, landerhigh, Вы писали:

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

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

И stackless и stackful хороши по-своему.
Stackful легко реализуются в виде библиотеки — см Boost.Coroutine. А вот stackless в виде библиотеки не очень, и не полноценно — смотри реализацию в Boost.Asio. Поэтому вполне логично добавить stackless в стандарт в первую очередь.

Другое дело что походу то что завезли в стандарт, оно не самое лучше из того что можно было сделать, а конкртено в том месте где они впипдюрили аллоцирование фрейма, которого могло бы не быть, и что открыло бы ещё больше zero-overhead вариантов использования. В частности даже stackless макро-реализация из Boost.Asio обошлась без аллокаций, и такой и должна быть реализация stackless здорового человека, ибо размер фрейма известен во время компиляции.
Точно также как и размер замыкания известен во время компиляции, и мы мыжем просто сохранить всё замыкание через автоматический вывод типа. Представь что вместо конкретного типа замыкания мы бы всегда получали std::function
Отредактировано 09.01.2021 14:59 Evgeny.Panasyuk . Предыдущая версия .
Re[2]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 09.01.21 14:50
Оценка:
Здравствуйте, х, Вы писали:

х>преобразуется в что-то вида:


Подскажи пожалуйста, они дали возможность сохранить корутину через её конкретный тип, или там до сих пор есть стирание типа вытекающие в аллокацию (которое было в ранних вариантах)?
Re[3]: C++20 coroutines (co_await)
От: х Россия  
Дата: 09.01.21 15:08
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Подскажи пожалуйста, они дали возможность сохранить корутину через её конкретный тип, или там до сих пор есть стирание типа вытекающие в аллокацию (которое было в ранних вариантах)?


Всё типилизированно. Тут реальная обёртка текущая под clang.
С уважением Вадим.
Re[7]: C++20 coroutines (co_await)
От: reversecode google
Дата: 09.01.21 15:11
Оценка:
а как бы вы сделали симметричные стеклесс корутины без аллокации фрейма ?
Re[4]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 09.01.21 15:41
Оценка:
Здравствуйте, х, Вы писали:

EP>>Подскажи пожалуйста, они дали возможность сохранить корутину через её конкретный тип, или там до сих пор есть стирание типа вытекающие в аллокацию (которое было в ранних вариантах)?

х>Всё типилизированно. Тут реальная обёртка текущая под clang.

Вопрос не про типизацацию в плане безопасности, а про стирание типа, type erasure. Ибо я именно что стирание типа и наблюдаю — std::coroutine_handle, каковым оно и было в ранних версиях.
Если разные генераторы, с разным набором и колличеством локальных переменных можно сохранить в один и тот же тип — то это и есть стирание типов, которого по-хорошему быть не должно. То есть оно может быть опциональным, по-желанию, как и std::function для замыканий, но не долнжо быть единственным вариантом.
Re[8]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 09.01.21 16:10
Оценка:
Здравствуйте, reversecode, Вы писали:

R>а как бы вы сделали симметричные стеклесс корутины без аллокации фрейма ?


Сабжевые ассиметричные.

Stackless корутины есть в Boost.Asio — https://www.boost.org/doc/libs/1_75_0/doc/html/boost_asio/reference/coroutine.html
Локальное состояние и номер состояния преобразуется в поля класса, просыпание в нужное состояние происодит свитчем. Конкретный экземпляр корутины это объект этого класса у которго есть operator(). Всё состояине известно на этапе компиляции, также как и у лямбды-замыкания, поэтому аллокация не нужна.
Более того, такая конструкция не только позвоялет избавится от аллокации, но также и копировать корутины — что по сути является fork'ом. Ещё круче, что их можно сериализировать.

Автор Asio даже предлагал свой вариант в стандарт, без аллокаций — http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4244.pdf
Но Microsoft видимо продавили свою версию, так как у них уже была своя реализация Они её ещё иногда называют "negative overhead abstraction", с аллокациями ага, негатив блин
Отредактировано 09.01.2021 16:11 Evgeny.Panasyuk . Предыдущая версия .
Re[9]: C++20 coroutines (co_await)
От: reversecode google
Дата: 09.01.21 16:19
Оценка:
сабжевые какие, которые сейчас добавили в стандарт С++ ?
так там они и симметричные тоже

но на вопрос вы не ответили
Re[10]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 09.01.21 16:23
Оценка:
R>но на вопрос вы не ответили

Что именно не ясно? Вот ещё нашёл пример await'а на макросах и stackless корутинах из Asio.
Re[11]: C++20 coroutines (co_await)
От: reversecode google
Дата: 09.01.21 16:30
Оценка:
ассиметричные стеклесс корутины легко реализуются на макросах
симметричные стеклесс корутины на макросах нельзя сделать, поскольку есть контекст
а вот стекфулл симметричные легко
поэтому в сабже и сделали динамическое аллоцирование фрейма, через который можно переключаться
Re[12]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 09.01.21 16:42
Оценка:
Здравствуйте, reversecode, Вы писали:

R>ассиметричные стеклесс корутины легко реализуются на макросах

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

Имея конкретный тип ассиметричной корутины её можно аллоцировать на стэке, в поле другого объекта, либо напрямую в куче. Симметричные корутины можно реализовать поверх ассиметричных.
Для многих use-case'ов подходят ассиметричные корутины на стэке, либо вообще заинлайненые по самые помидоры. Например для генераторов типа Python'ского yield. Авторы же сабжа в таких случаях предлагают уповать на то что оптимизатор может выкинуть аллокацию — HALO (heap allocation elision optimization) — но это ганатированно не работает при сохранении корутины в поле другого объекта.
Re[7]: C++20 coroutines (co_await)
От: reversecode google
Дата: 09.01.21 17:00
Оценка:
стекфулл корутины очевидно не добавили в стандарт не потому что они легко реализуются самостоятельно
а потому что необходимо будет описать что такое стек(вспоминая Полухина и его бектрейс)
а за этим потянется и расщирения стека и перемещение объектов по стеку не нарушая их состояния, наверняка у комитета от этого взрывался мозг
я бы сказал по этому стекфулл корутины не очень юзабельны в С++

следить ручками и глазками за размером стека и пытаться сразу же угадать сколько нужно аллоцировать памяти на очередной фрейм это
Re[8]: C++20 coroutines (co_await)
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 09.01.21 17:09
Оценка:
Здравствуйте, reversecode, Вы писали:

R>я бы сказал по этому стекфулл корутины не очень юзабельны в С++

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

Вотчить хэндами и айсами за сайзом и аттемптить саппозинг эмаунта спейса...
Re[8]: C++20 coroutines (co_await)
От: Evgeny.Panasyuk Россия  
Дата: 09.01.21 17:23
Оценка:
Здравствуйте, reversecode, Вы писали:

R>стекфулл корутины очевидно не добавили в стандарт не потому что они легко реализуются самостоятельно

R>а потому что необходимо будет описать что такое стек(вспоминая Полухина и его бектрейс)
R>а за этим потянется и расщирения стека и перемещение объектов по стеку не нарушая их состояния, наверняка у комитета от этого взрывался мозг

Перемещение объектов по стэку у stackful корутин врядли кода либо будет, в общем случае это вообще не реализуемо, либо с очень жёсткими ограничениями на вызываемый код, что убьёт всё мощь stackful — ибо они могут работать и прыгать через сторонний код.

R>я бы сказал по этому стекфулл корутины не очень юзабельны в С++


Даже библиотечная реализация достаточно юзабельная.
А вот stackless не очень, поэтому если есть выбор лично я предпочту stackless реализацию в стандарте, так как stackful по сути уже доступна.

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


Ну здесь очевидно непонимание, ибо следить и угадывать размер ручками не нужно и никто не предлагает, даже в макро-реализации stackless из Asio.
Размер фрейма любой функции тривиально известен во время компиляции. Глубина прыжков stackless корутин огранична scope'ом одной фукции, что в C++20, что в C#, что в Python, на то они и stackless. Поэтому и размер корутины, как и её конкретный тип легко может быть известен во время компиляции
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.