Re[3]: Асинхронщина
От: landerhigh Пират  
Дата: 06.12.25 13:29
Оценка: +1
Здравствуйте, Videoman, Вы писали:

N>>Если посмотреть на userver, который делает всё то, что тебе надо, то видно, что он C++17 требует. То есть его достаточно.


V>Мне показалось, что там во всю стекфул корутины используются. Подход понятен, но мне хотелось бы получить что-то в стиле node.js. Один основной поток, в котором логика строго однопоточная, без необходимости синхронизации. Мне показалось, что со стекфул корутинами, если мы используем сразу кучу ядер,


Именно что показалось.
Корутина — это не поток. Это просто возможность прервать выполнение функции и потом продолжить с того же места. Когда прервать и когда продолжить, решать программисту, т.е. тебе.

V>Уточню. У меня задача не запускать паралльно несколько независимых веток исполнения, а делать все по очереди (псевдопараллельно(, как будто в одном потоке, без синхронизации. Если на низком уровне рассматривать, похоже на большой автомат, но который каждый цикл выполняет одну и ту же логику, но она огромная размазана между кучи ожиданий IO, иногда вложенных. Похоже на то, как работает node.js. Ощущение, что безстековые корутины тут лучше подходят или я не прав?


Тут подходят безстековые корутины. И стековые тоже подходят.
Разница между ними в том, что в случае безстековых корутин сохранение контекста либо делается вручную, либо должно поддерживаться языком/средой (в случае 20х корутин это делает компилятор, как правило выделяя память на куче). Для стековых корутин должен выделяться отдельный стек, и запуск/выход из них связан с необходимостью сохранения и восстановления всех регистров, что относительно дорого. Из плюсов стековых корутин можно назвать то, что переключение контекста возможно из любой функции в стеке вызовов, при этом функции выше по стеку вообще могут не знать, что они выполняются в контексте корутины.
Re: Асинхронщина
От: AleksandrN Россия  
Дата: 06.12.25 18:47
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Большая просьба по возможности воздержаться от тыканья в готовые библиотеки, в плане бери вот это, там всё уже есть и не думай. Хочется понять основные идеи и подходы, а не максимально быстро начать писать код в продакшене.


Для ожидания события в сокете можно использовать poll/epoll/select/kqueue (сокет должен быть не блокируемым). Но кросс-платформенный из этого только select.
В кроссплатформенных библиотеках boost::asio, libevent и ещё нескольких именно эти механизмы и используются.

Можно коллбек прикрутить, можно в отдельном потоке ответ ждать, причём можно ждать ответ более, чем на одном сокете.
Re: Асинхронщина
От: Pitirimov США  
Дата: 07.12.25 22:37
Оценка:
Здравствуйте, Videoman, Вы писали:
V> ... кто как подходит к IO-bound задачам, где CPU, будем считать для простоты, почти не используется и в основном приходится ждать завершение операций.

Я бы просто запускал новый поток и ожидал сообщения от него о завершении обмена данными. Ядер у современных процессоров гораздо больше одного и в наши дни неразумно обрабатывать все задачи сопрограммами на одном ядре процессора вместо многопоточной, многоядерной обработки.
Re[2]: Асинхронщина
От: kov_serg Россия  
Дата: 08.12.25 07:28
Оценка:
Здравствуйте, Pitirimov, Вы писали:

P>Здравствуйте, Videoman, Вы писали:

V>> ... кто как подходит к IO-bound задачам, где CPU, будем считать для простоты, почти не используется и в основном приходится ждать завершение операций.

P>Я бы просто запускал новый поток и ожидал сообщения от него о завершении обмена данными. Ядер у современных процессоров гораздо больше одного и в наши дни неразумно обрабатывать все задачи сопрограммами на одном ядре процессора вместо многопоточной, многоядерной обработки.


Дык если потоков много очень большие накладные расходы по памяти и на переключение, да и кэш бодро вымывается.
Поэтому вместо миллиона тактов на переключения потока использоую сотни тактов на планировщик и вместа 4мб стека на поток мелкие стуктуры и coroutine-ы.
В результате выигрыш по производительности может быть очень ощутимым. Если бы он был не значительным миллионы мух не заморачивались бы.
Отредактировано 08.12.2025 7:29 kov_serg . Предыдущая версия .
Re[2]: Асинхронщина
От: so5team https://stiffstream.com
Дата: 08.12.25 07:33
Оценка:
Здравствуйте, Pitirimov, Вы писали:

P>Здравствуйте, Videoman, Вы писали:

V>> ... кто как подходит к IO-bound задачам, где CPU, будем считать для простоты, почти не используется и в основном приходится ждать завершение операций.

P>Я бы просто запускал новый поток и ожидал сообщения от него о завершении обмена данными.


Довелось лет 5 назад понаблюдать за тем, как Linux вставал колом на такой модели thread per connection когда количество одновременно обслуживаемых соединений превышало 32K штук.

Не надо так делать.
Re[2]: Асинхронщина
От: Videoman Россия https://hts.tv/
Дата: 08.12.25 18:52
Оценка:
Здравствуйте, Pitirimov, Вы писали:

P>Я бы просто запускал новый поток и ожидал сообщения от него о завершении обмена данными. Ядер у современных процессоров гораздо больше одного и в наши дни неразумно обрабатывать все задачи сопрограммами на одном ядре процессора вместо многопоточной, многоядерной обработки.


В моих новых задачах мне такое не подходит. Говорю же CPU-bound. Основному потоку нечего желать, только логику распределять, всё на ожидании висит. Вот только автомат по логике получается безумный. Поэтому хочется всё это выпрямить. Зачем тут стрелять из пушки.
Re[4]: Асинхронщина
От: Videoman Россия https://hts.tv/
Дата: 08.12.25 19:13
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>Именно что показалось.

L>Корутина — это не поток. Это просто возможность прервать выполнение функции и потом продолжить с того же места. Когда прервать и когда продолжить, решать программисту, т.е. тебе.

А я где-то написал что корутина это — поток . Корутина это не поток, но выполняется она не в вакуме, а в контексте потока ОС.

L>Тут подходят безстековые корутины. И стековые тоже подходят.

L>Разница между ними в том, что в случае безстековых корутин сохранение контекста либо делается вручную, либо должно поддерживаться языком/средой (в случае 20х корутин это делает компилятор, как правило выделяя память на куче). Для стековых корутин должен выделяться отдельный стек, и запуск/выход из них связан с необходимостью сохранения и восстановления всех регистров, что относительно дорого. Из плюсов стековых корутин можно назвать то, что переключение контекста возможно из любой функции в стеке вызовов, при этом функции выше по стеку вообще могут не знать, что они выполняются в контексте корутины.

Я знаю чем стековые корутины отличаются от безстековых, только вот разница большая, на мой взгляд. Как я понимаю, в случае стековых корутин мне придется всё равно писать в многопоточном стиле, пофигу что физически поток один, нити то разные и стеки тоже. Потом придется как-то контекст руками размазывать по нитям, делать аналог join. Отличий от потоков почти никакой, с той лишь разницей, что мы оптимизируем переключение контекста оптимизирую по CPU, а мне это не нужно, хотелось бы логику выпрямить.
Меня интересуют безстековые корутины или их заменители, когда вся логика в основном потоке. Еще большой плюс, что можно использовать пул потоков, в которых выполнять асинхронные операции изолированно, а результат возвращать основному потоку. Видимо придется использовать 20-й стандарт.

А на 20-м стандарте есть какие-нибудь библиотеки, которые использую корутины оттуда? Была бы идеальна обертка libuv в С++20 корутины, кажется.
Re[5]: Асинхронщина
От: so5team https://stiffstream.com
Дата: 09.12.25 05:51
Оценка: 4 (1)
Здравствуйте, Videoman, Вы писали:

V>А на 20-м стандарте есть какие-нибудь библиотеки, которые использую корутины оттуда? Была бы идеальна обертка libuv в С++20 корутины, кажется.


На Reddit-е на днях кто-то запостил ссылку на свою такую обертку: https://old.reddit.com/r/cpp/comments/1pep8ie/introducing_asyncio_a_new_opensource_c23/
Но она требует C++23.
Re: Асинхронщина
От: B0FEE664  
Дата: 09.12.25 13:59
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Что в идеале хочется получить:

V>
V>data = await read(...);
V>await write(data);
V>

V>Понятно, что скорее всего должен быть некий механизм, который следит за завершенными операциями и продолжает выполнение с точки ожидания.
V>Как такое можно организовать проще всего? Обязательно нужно кроссплатформенное решение, без погружения в дебри с ассемблером, регистрами и т.л.

std::future, std::async
И каждый день — без права на ошибку...
Re[2]: Асинхронщина
От: sergii.p  
Дата: 09.12.25 15:24
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>std::future, std::async


это же создаст сонм потоков-бездельников
Re[5]: Асинхронщина
От: Великий Мессия google
Дата: 09.12.25 17:41
Оценка:
V>А на 20-м стандарте есть какие-нибудь библиотеки, которые использую корутины оттуда? Была бы идеальна обертка libuv в С++20 корутины, кажется.

на гитхабе с десяток тех оберток вокруг libuv которые дают возможностью юзать co_await итд соцпрограммы из С++17+

но все же asio VS libuv
лучше asio
хотя некоторые плюсики и у в libuv есть
Re[3]: Асинхронщина
От: B0FEE664  
Дата: 09.12.25 18:51
Оценка:
Здравствуйте, sergii.p, Вы писали:

BFE>>std::future, std::async

SP>это же создаст сонм потоков-бездельников

Или не создаст.
Зависит от имплементации.
Имплементация может использовать thread pool.
Так как у меня задачи совсем не укладываются в описанный топикастером подход, то на практике я эти функции не использовал, но, теоретически, как мне кажется, связка future + async укладывается в описанную задачу, как я её понял.
И каждый день — без права на ошибку...
Re[6]: Асинхронщина
От: Videoman Россия https://hts.tv/
Дата: 11.12.25 20:38
Оценка:
Здравствуйте, Великий Мессия, Вы писали:

ВМ>на гитхабе с десяток тех оберток вокруг libuv которые дают возможностью юзать co_await итд соцпрограммы из С++17+


А как они это делают в С++17, можете идею подкинуть?

ВМ>но все же asio VS libuv

ВМ>лучше asio

Чем лучше то, я во смотрю смотрю и не пойму? У меня не только стандартные протоколы и разные устройства. Я почти уверен что придется свои расширения и поддержку писать. Насколько сложно это будет с asio ?

ВМ>хотя некоторые плюсики и у в libuv есть

У меня есть специфические IO, такие как например STD handles или Unix Sockets, Serial Ports и т.д. Всё это поддерживается сейчас без библиотек своими силами под Windows и Linux. Преимущество, для меня, в том, что я могу добавить/расширить любой функционал. Снаружи это все обернуто в одни и те же интерфейсы (кстати похоже на asio получилось) и взаимозаменяемо. Вопрос в том, смогу ли я это всё контролировать в рамках asio ? Например таймауты connect и accept или скорость serial порта. Вообще, насколько asio расширяем?
Отредактировано 11.12.2025 20:40 Videoman . Предыдущая версия .
Re[2]: Асинхронщина
От: Videoman Россия https://hts.tv/
Дата: 11.12.25 20:46
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>std::future, std::async

BFE>

Это же руками закатывать солнце. Я хочу выпрямить логику. У меня реализована поддержка signal slots, куда можно любые объекты передавать и что угодно вызывать в каком угодно потоке. Ручной подход работает, но только если это подобие посылки сообщений. А вот если по сути логика линейная, но в ней есть много IO ожиданий, то это быстро превращается в программирование огромного автомата руками. Поэтому я и спрашиваю совета, хочу понять что-то поменялось/появилось в С++ для таких задач?
Отредактировано 11.12.2025 20:51 Videoman . Предыдущая версия .
Re[4]: Асинхронщина
От: Videoman Россия https://hts.tv/
Дата: 11.12.25 20:49
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Или не создаст.

BFE>Зависит от имплементации.
BFE>Имплементация может использовать thread pool.
BFE>Так как у меня задачи совсем не укладываются в описанный топикастером подход, то на практике я эти функции не использовал, но, теоретически, как мне кажется, связка future + async укладывается в описанную задачу, как я её понял.

У меня есть пулы потоков и сами потоки можно удобно использовать, и мне кажется std::async не гибким совсем. Он не позволяет убрать под капот логику ожидания длительных операций.
Re[7]: Асинхронщина
От: Великий Мессия google
Дата: 11.12.25 22:35
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Здравствуйте, Великий Мессия, Вы писали:


ВМ>>на гитхабе с десяток тех оберток вокруг libuv которые дают возможностью юзать co_await итд соцпрограммы из С++17+


V>А как они это делают в С++17, можете идею подкинуть?


С++17 co_await
https://godbolt.org/z/PvrKMsro5

так же как и в С++20
насколько я помню, и автор asio подтверждает
саму машинерию co_* добавили в компили с С++17, https://www.youtube.com/watch?v=proxLbvHGEQ
а некоторые await-ы в експерементал папочку
https://github.com/chriskohlhoff/asio/blob/55684d42ac00021b4c31ba8571aca414c863ead5/configure.ac#L166

AC_MSG_CHECKING([whether C++17 is enabled])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#if __cplusplus < 201703 L]]
[[#error C++17 not available]]
[#endif]])],
[AC_MSG_RESULT([yes])
HAVE_CXX17=yes;],
[AC_MSG_RESULT([no])
HAVE_CXX17=no;])


https://github.com/chriskohlhoff/asio/blob/55684d42ac00021b4c31ba8571aca414c863ead5/configure.ac#L194

AC_MSG_CHECKING([whether coroutines are enabled])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[#if defined(__clang__)]]
[[# if (__clang_major__ >= 14)]]
[[# if (__cplusplus >= 202002) && (__cpp_impl_coroutine >= 201902)]]
[[# if __has_include(<coroutine>)]]
[[# define ASIO_HAS_CO_AWAIT 1]]
[[# endif]]
[[# elif (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)]]
[[# if __has_include(<experimental/coroutine>)]]
[[# define ASIO_HAS_CO_AWAIT 1]]
[[# endif]]
[[# endif]]
[[# else]]
[[# if (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)]]
[[# if __has_include(<experimental/coroutine>)]]
[[# define ASIO_HAS_CO_AWAIT 1]]
[[# endif]]
[[# endif]]
[[# endif]]
[[#elif defined(__GNUC__)]]
[[# if (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902)]]
[[# if __has_include(<coroutine>)]]
[[# define ASIO_HAS_CO_AWAIT 1]]
[[# endif]]
[[# endif]]
[#endif]]
[[#ifndef ASIO_HAS_CO_AWAIT]]
[[# error coroutines not available]]
[#endif]])],
[AC_MSG_RESULT([yes])
HAVE_COROUTINES=yes;],
[AC_MSG_RESULT([no])
HAVE_COROUTINES=no;])


ВМ>>но все же asio VS libuv

ВМ>>лучше asio

V>Чем лучше то, я во смотрю смотрю и не пойму? У меня не только стандартные протоколы и разные устройства. Я почти уверен что придется свои расширения и поддержку писать. Насколько сложно это будет с asio ?


libuv СИ шная либа, по умолчанию будешь юзать колбеки, а для использования корутин аля co_*, нужно будет гитхабить обертки

asio С++ шная либа, там по умолчанию поддерживаются уже на выбор,или колбеки или лямюбды или co_*

что ты там собираешься писать я хз

ВМ>>хотя некоторые плюсики и у в libuv есть

V>У меня есть специфические IO, такие как например STD handles или Unix Sockets, Serial Ports и т.д. Всё это поддерживается сейчас без библиотек своими силами под Windows и Linux. Преимущество, для меня, в том, что я могу добавить/расширить любой функционал. Снаружи это все обернуто в одни и те же интерфейсы (кстати похоже на asio получилось) и взаимозаменяемо. Вопрос в том, смогу ли я это всё контролировать в рамках asio ? Например таймауты connect и accept или скорость serial порта. Вообще, насколько asio расширяем?

это все как я понимаю есть уже в asio

кстати минусы libuv, там подняли требования винды до win10+
там что win7,win8,vista не подержатся
можно ручками подправить либу
но некоторые функции отвалятся
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.