Pull to refresh

Comments 34

Благодарю за статью. Как по мне — самая лучшая вводная по корутинам. Поправь только в тексте про await_ready(), указывается дважды false как возвращаемый результат.

Теперь вот вопрос по Task. А не надо ли его сохранять? Там хэндл корутины же лежит. А что будет, если он будет уничтожен, а мы вызовем resume? А то кажется, что doSomething работает только потому, что память незакораптилась.

UFO landed and left these words here

Хорошее решение этой задачи - shared_ptr. И вроде бы в cppcoro я его видел.

Ещё можно просто отменять корутину в деструкторе возвращаемого значения.

var client = await server.accept(); // принимаем входящее подключение
var request = await socket.read(...));

Похоже код никого не интересует. А код зачем-то приведен с подлянкой!

Куда делся client,и зачем он вообще нужен, если он дальше не используется и откуда взялся socket кто-нибудь может объяснить?

это конечно самая простая версия, но только это не может быть опечаткой. Поэтому возникает вопрос: может автора код не интересует? Тогда не имеет смысла дальше анализировать страшные классы приведенные в статье.

Да всё просто же, писался код одновременно со статьёй, копировался кусками, периодически редактировался и снова кусками переносился. Вот и исправление socket на client полностью не перенеслось.
Исправить это, конечно же, надо - но вот далеко идущие выводы про "автора код не интересует" я бы делать не стал.

Вот и исправление socket на client полностью не перенеслось.

это как это? Когда могло произойти такое исправление в трех строчках, в пяти?

не верю.

UFO landed and left these words here

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

Как мне показалось мы говорили о 5-ти строчках которые определяют-задают смысл всей статьи, и в этих строчках допущена ошибка, именно это меня и расстроило. Я не понимаю при чем здесь "множество однообразных изменений во многих местах", я про 5-ть строчек говорю, а вы про что?

Но честно говоря даже общий смысл статьи по моему ускальзает, потому что:

"WTF? Серьезно? Почему ТАК сложно? Зачем столько танцев с бубном чтобы запустить простейшие корутины?!"

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

Кроме модного слова "корутины" и некоторого непонятного шаманства вокруг него в статье нет ничего полезного для "чайника", которому она предназначена, судя по названию. ИМХО.

Мне просто интересно на чем основано восхищение тех кто вашу статью плюсует, поэтому я и указал на ошибку публично. Раз с поддержкой у вас проблем нет, я думаю критика вам не помешает, а то как бы корона не вросла и не повредила что-то в голове.

UFO landed and left these words here

Можно просто нажать Ctrl+Enter, чтобы сообщить автору об опечатке

Разве select и poll -- это асинхронный ввод-вывод, а не неблокирующий? Я не линухоид, поэтому и спрашиваю. Просто неблокирующий к асинхронщине отношения не имеет и толку с него в этом плане примерно нуль (смысл асинхронного ввода-вывода, как правильно указано в статье, -- сообщать о завершении операции ввода-вывода, ну а неблокирующий лишь говорит о том, что файл готов к дальнейшей работе -- а, скажем, настоящий честный дисковый файл всегда готов).

UFO landed and left these words here

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

UFO landed and left these words here

Спасибо за статью, она действительно закрыла некоторые пробелы в понимании но если честно с момента рассказа Гор Нишанова про корутины когда их ещё только пропихивали в стандарт, году в 18 на одном из открытых мероприятий яндекса, и посмотрев уже не один доклад по корутинам на cpp russia и cppcon, я пока ментально видимо не готов к корутинам и не могу принять то чем они проще. На "бумаге" все выглядит вроде не плохо, а потом начинается десяток всяких мета классов для того чтоб это работало с не очевидным и не до конца понятными переходами между состояниями и когда начинаю задумываться, а что если где то что то пойдёт не так и возникнет какая то гонка то я умру это дебажить. Для меня код из "старых" плюсов выглядит максимально просто и понятно, я понимаю примерные места где может быть гонка и мне понятно как это отлаживать в случае проблем, а вот корутины мне уже начинают boost asio напоминать и вспоминая дни отладки там бросает в дрож..

UFO landed and left these words here

Что-то я не совсем понимаю или совсем не понимаю. doSomething() вызывает две функции с co_await .... Я так понимаю пока одна не закончится следующая не будет вызвана. А где же асинхронность? Можно какой-нибудь пример где два request выполняются наперегонки и печатают результат когда он будет доступен.

UFO landed and left these words here

Спасибо. Получается что вся кухня с callback и select никуда не делась, а работает себе в отдельном потоке, а в основном потоке что-то типа красивой обёртки - пользовательский интерфейс где можно выполнять высокоуровневые операции. Преимущество как мне кажется, что количество callback в коде будет значительно меньше. В данном случае будет только один :) Но если нужно добавить что-то другое помимо curl, то нужен либо отдельный поток, либо добавить это в WebClient::runLoop(). Я правильно понимаю? Например асинхронное чтения файла или server.accept(). Как бы вы поступили для такого расширения этого кода?

Получается что вся кухня с callback и select никуда не делась, а работает себе в отдельном потоке, а в основном потоке что-то типа красивой обёртки

Нет, не получается. Тот поток, который исполняет цикл событий - это и есть основной.

Но если нужно добавить что-то другое помимо curl, то нужен либо отдельный поток, либо добавить это в WebClient::runLoop()

В целом, да. Для каждого цикла обработки событий нужен свой поток (а лучше набор потоков по числу ядер).

Хотя конкретно в случае асинхронных сокетов и асинхронных http-запросов проще отказаться от curl и использовать только сокеты.

правильно написал @mayorovp

Хотя конкретно в случае асинхронных сокетов и асинхронных http-запросов проще отказаться от curl и использовать только сокеты.

в интерфейсах к сокетам есть все что нужно для ассинхронности, приплетать там какие-то "корутины" для которых даже нет однозначного определения (если вы попробуете посмотреть кто что понимает под этим названием) да еще и с непонятной внешней библиотекой в стабильности которой еще надо убедиться, совершенно не к чему.

У меня когда-то было решение как раз такой задачки с которой начал автор, она решается с использованием двух потоков достаточно просто, если вы умеете писать решения с асинхронностью на потоках, а если не умеете, то корутины вам точно не помогут.

Может быть я как-нибудь напишу статью про это решение, раз уж мне напомнили задачку и теперь она у меня снова перед глазами как 17 лет назад.

UFO landed and left these words here
UFO landed and left these words here

Вроде понятно. Я просто раньше думал что можно обойтись и без второго потока. Каким-то образом жонглировать в единственном потоке всеми состояниями и переключать контекст по мере того как становятся доступными данные. А внутри под капотом select/epoll + файловые дескрипторы ну или CURL. Такое возможно? Скажем вызываешь co_await а там начинает шуршать вся эта машина состояний и возможно выполнится какой-то другой co_await из другого контекста и там пойдёт выполнение дальше...

UFO landed and left these words here

"больные ублюдки" - вот что я понял про с++

На всех других языках это пишется в пару строк

UFO landed and left these words here

На C++ тоже можно взять folly и написать в пару строк. Корутины в C++ действительно переусложнённые, подход из Rust мне нравится больше, но абсолютно везде сделать поддержку ввода-вывода и минимально необходимых функций для корутин займёт немало кода.

Мы в мире C++ с юности привыкли к боли и унижениям

в каком-то грустном мире вы живете. Мы в нашем С++ мире привыкли к неограниченным возможностям, правда это было еще до 2011 года. Видимо это с 2011 года вас загоняют в мир боли и унижений. Это печально.

UFO landed and left these words here

вряд ли вам поможет C++11 или даже C++115, когда вы не понимаете, что так писать нельзя:

var socket = await server.accept(); // принимаем входящее подключение
var request = await socket.read(...));
var result = await db_сient.do_query(transform_request(request));
await socket.write(transform_result(result));
socket.close();

Компилятор сделает особую магию.

Вы заблокировали сервер, никакая магия вам не поможет! В течении времени работы с полученным сокетом, сервер не принимает другие входящие сокеты, не важно есть у вас там await-ы или нет.

UFO landed and left these words here
Sign up to leave a comment.

Articles