EP>Вызываются "handler"'ы (в твоих терминах). EP>В каждом "handler"'е код выполняется до каждого yield'а и сразу возвращается сюда — так же как и в C# с async/await код выполняется до первого await'а. Это в твоих понятиях являются асинхронными вызовами или нет?
Нет, что очевидно — у тебя просто синхронный код.
EP>Когда "event loop" ныряет в сопроцедуру — это аналог тому, когда await дожидается своего таска. EP>Все остальные yield'ы в "handler"'ах — аналогичны последующим await'ам и т.п.
На вских yield можно построить асинхронный процессинг, но при этом не любой код на короутинах будет асинхронным.
I>>Ну и так же ты показал, что в предыдущем примере у тебя, мягко говоря, отсутствовало 99% решения
EP>Опустим этот "толстый, толстый слой шоколада" и вернёмся к исходному вопросу
. EP>Аналогичный код можно написать на await'ах — но там неизбежно "асинхронные кишки будут торчать в клиентском коде". Ты теперь понял почему?
ca(); — вот так что ли ? Там где ты явно, руками вызываешь короутину, будет стоять await. И эту самую асинхронщину как раз и надо контролировать руками.
Собтсвенно асинхронщина это не то, для чего нужны короутины.
Здравствуйте, Mazay, Вы писали:
I>>Собтсвенно асинхронщина это не то, для чего нужны короутины.
M>Согласен. Но с корутинами можно писать асинхронный код, который будет выглядеть как синхронный. И await это и есть корутина.
async это короутина, а await это подсказка компилеру где делать прерывание
Здравствуйте, IT, Вы писали:
IT>>>Это не тот ли самый случай из-за чего старый VB тормозил на операциях с памяться раз так в 200? V>>Нет, не тот. VB тормозил из-за передачи строк и Safe Array по значению при маршаллинге.
IT>Не скажу за строки, но он жутко тормозил на счётчиках ссылок.
Я не замерял совсем старые VB, но при разборе ассемлерных листингов программ на последних VB5/VB6 и сравнении их с аналогичным кодом на C++ со смарт-поинтерами, общее кол-во парных AddRef/Release на VB5/VB6 было намного меньше, т.е. компилятор был довольно-таки умен. Более того, приятно поразила неплохая оптимизация целочисленных вычислений.
Проблемы в VB не в компиляторе, а в программистах. Язык позволяет писать без аннотации типов. Хотя позволяет задавать опции модуля для требований обязательного описания переменных, но всегда можно описать бестиповую переменную. Вот и выходит, что даже простое копирование VARIANT будет выполняться уже с вызовом библиотечной VariantCopy, безо-всякой оптимизации, да еще из DLL, т.е. через переходник, а внутри затем будет распаковка и вызовы AddRef/Release, короч, много лишнего кода на простейший чих. В общем, типизация в VB6 давала нехилый буст.
Ну и ниша, опять же. VB использовался для шлепанья формочек, а числодробильную нагрузку во времена VB делали на С/С++. Нагруженные формочки на VB "летали" на тех машинках в сравнении с MFC, бо там многие контролы шли как windowless: http://support.microsoft.com/kb/184687
Здравствуйте, koodeer, Вы писали:
K>Начинающие программисты много внимания уделяют типу переменной; разбирая чужой код, они в первую очередь смотрят на тип, и таким образом пытаются понять, что можно сделать с этой переменной (этим объектом). И эти джуниоры мало уделяют внимания наименованию переменных.
K>Более опытные разработчики типу уделяют гораздо меньше внимания. Для них важнее сама семантика кода. Гораздо важнее название переменной, а не её тип. Дав описательное название переменной, можно по сути пренебречь её типом: и так всё ясно.
Бред сивой кобылы, сорри.
Точный тип относится к подробностям кода. Поэтому, надобность в точном типе при чтении кода зависит от степени вникания в эти подробности. Кароч, у тебя верные наблюдения, но ты сделал из них неверные выводы. Более опытные разработчики ворочают намного большими объемами кода, чем новички, отсюда разные навыки чтения кода при беглом его разборе. Но когда они вникают в подробности конкретного участка, поверь, их точно так же интересуют точные типы.
Здравствуйте, gandjustas, Вы писали:
G>Экономика корпоративных систем оставляет C++ за бортом.
Не изобретай, экономике корпоративных систем на язык реализации ваще наплевать.
G>На десктопе ситуация для C++ не лучше, так как ресурсов дофига, даже на планшетах, никто за лишние 30-50 мегабайт не будет беспокоиться и почти везде уже больше одного ядра.
Тебе-то что, если львиная доля любого софременного софта — это библиотечный код?
При наличии нормальных библиотек язык уже не столь принципиален. Джава стала популярна когда-то не из-за языка (он же чудовищен!), а из-за мега-инфраструктуры на тоннах библиотек. Дотнет лишь повторил эту модель на чуть более хорошем уровне.
G>Остаются встраиваемые системы с малыми ресурсами и всяческие HFT.
Хи. Помимо этого остаетcя ~99% софта на десктопе. Какие, право, мелочи.
=====
Как обычно, разработчикам заказухи из подвала виднее, угу...
Здравствуйте, Ikemefula, Вы писали:
EP>>Вызываются "handler"'ы (в твоих терминах). EP>>В каждом "handler"'е код выполняется до каждого yield'а и сразу возвращается сюда — так же как и в C# с async/await код выполняется до первого await'а. Это в твоих понятиях являются асинхронными вызовами или нет? I>Нет, что очевидно — у тебя просто синхронный код.
Основные претензии к "обычному асинхронному коду" в том, что он не похож на синхронный, то что нужно лепить callback'и, continuations, причём заворачивать в несколько уровней.
Основная фича await в том, что он позволяет распрямить асинхронный код, сделать его похожим на синхронный. Именно этим радикальные C#-исты пытались козырнуть в этом топике, типа "покажи аналог"
Так вот, если асинхронный код идентичен синхронному аналогу — то это же самый лучший вариант, вроде же очевидно
EP>>Когда "event loop" ныряет в сопроцедуру — это аналог тому, когда await дожидается своего таска. EP>>Все остальные yield'ы в "handler"'ах — аналогичны последующим await'ам и т.п. I>На вских yield можно построить асинхронный процессинг, но при этом не любой код на короутинах будет асинхронным.
А где я говорил что любой?
I>>>Ну и так же ты показал, что в предыдущем примере у тебя, мягко говоря, отсутствовало 99% решения EP>>Опустим этот "толстый, толстый слой шоколада" и вернёмся к исходному вопросу
. EP>>Аналогичный код можно написать на await'ах — но там неизбежно "асинхронные кишки будут торчать в клиентском коде". Ты теперь понял почему?
I>ca(); — вот так что ли ? Там где ты явно, руками вызываешь короутину, будет стоять await.
Фишка в том, что эти ca() можно инкапсуировать в библиотеки, асинхронные вызовы — а await'ы будут засорять все уровни кода.
Более того, синтаксис await'ов можно полностью реализовать на stackfull coroutines (async в объявлении будет не нужен, но будет нужен call_async в месте вызова + такие await могут стоят на "любой глубине").
I>И эту самую асинхронщину как раз и надо контролировать руками. I>Собтсвенно асинхронщина это не то, для чего нужны короутины.
Корутины позволяют делать асинхронный код похожим на синхронный, и ещё много чего.
C#-повский async/await, как я уже описывал выше
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Основные претензии к "обычному асинхронному коду" в том, что он не похож на синхронный, то что нужно лепить callback'и, continuations, причём заворачивать в несколько уровней. EP>Основная фича await в том, что он позволяет распрямить асинхронный код, сделать его похожим на синхронный. Именно этим радикальные C#-исты пытались козырнуть в этом топике, типа "покажи аналог" EP>Так вот, если асинхронный код идентичен синхронному аналогу — то это же самый лучший вариант, вроде же очевидно
Вот, отличная формулировка. А я всё не мог подобрать точных слов, когда говорил что лично мне совершенно не нравится этот await/async стиль. Вот как раз тем, что реально асинхронный код притворяется синхронным, оно мне и не нравится. Зачем лишние запутывания на пустом месте и без всякой выгоды?
Я ещё понимаю, когда речь идёт о разработке библиотеки, которая может работать и в синхронном и в асинхронном режиме. Тогда это действительно полезно и удобно — мы можем писать один код, а потом менять режим работы каким-то одним параметром в совершенно другом месте кода.
А в приведённом пример с фоновым скачиванием файла по запросу пользователя я не вижу разумных причин для применения подобной техники.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Так вот, если асинхронный код идентичен синхронному аналогу — то это же самый лучший вариант, вроде же очевидно
Ты пока что кроме синхронного ничего так и не показал.
I>>ca(); — вот так что ли ? Там где ты явно, руками вызываешь короутину, будет стоять await.
EP>Фишка в том, что эти ca() можно инкапсуировать в библиотеки, асинхронные вызовы — а await'ы будут засорять все уровни кода. EP>Более того, синтаксис await'ов можно полностью реализовать на stackfull coroutines (async в объявлении будет не нужен, но будет нужен call_async в месте вызова + такие await могут стоят на "любой глубине").
Это просто чушь и незнание истории операционных системы и их возможностей. В винде и лялихе файберы/короутины есть с незапамятных времен. И вот что странно — на фоне этих самых короутин, которые работают искаропки, внезапно распространяется APM — это всякие BeginAsync, EndAsync и IAsyncCallback и тд и тд и тд и тд и тд и тд.
Потом появляется async/await, хотя казалось бы, stackfull coroutines работают искаропки.
EP>Корутины позволяют делать асинхронный код похожим на синхронный, и ещё много чего.
Скажи пожалуйста, а кто будет контролировать все эти нелокальные переходы ? В async/await все понятно — компилятор. Максимум контроля над одной единсвенной небольшой задачей. А что stackfull даёт ? Переходы непойми где ? Вместо однозадачного кода получить кооперативную многозадачность со всеми её проблемами — starvation, гонки, инверсия приоретитов и тд.
Ну вот пример — исключения. Кто их будет обрабатывать ? Вызывающих сторон становится как бы больше одной. Предлагаешь исключения кидать всем подряд ? Или для одной из сторон исключения будут глотаться ?
Тебе понятно, что короутины нужно встроить вообще везде, что бы работал такой код ? В твоем случае он работать не будет, что очевидно, винда не знает про то, что ты используешь короутины.
То есть, для того что бы нормально использовать короутины, надо применить их тотально, то есть вообще везде где угодно.
Для примера выше — покажи приблизительный код, который нужно добавить, что бы работала и твоя модная асинхронщина и этот цикл выборки сообщений.
Здравствуйте, alex_public, Вы писали:
_>Вот, отличная формулировка. А я всё не мог подобрать точных слов, когда говорил что лично мне совершенно не нравится этот await/async стиль. Вот как раз тем, что реально асинхронный код притворяется синхронным, оно мне и не нравится. Зачем лишние запутывания на пустом месте и без всякой выгоды?
_>Я ещё понимаю, когда речь идёт о разработке библиотеки, которая может работать и в синхронном и в асинхронном режиме. Тогда это действительно полезно и удобно — мы можем писать один код, а потом менять режим работы каким-то одним параметром в совершенно другом месте кода.
_>А в приведённом пример с фоновым скачиванием файла по запросу пользователя я не вижу разумных причин для применения подобной техники.
На stackfull короутинах здесь не было ни одного примера асинхронщины. Ни одного, зато есть вопли, как всё просто и шоколадно. Есть мой пример с message pump — допили его и продемонстрируй асинхронщину
Пока что очевидно, что вызов любого метода из message pump приведет замораживанию приложения. Что бы это забороть, надо явно делать короутинами вообще всё, в т.ч. и message pump. То есть на ровном месте педалить и приседать с кооперативной многозадачностью.
Смешно — короутины есть в современных OS с незапамятных времен и как то это никак не сказалось на асинхронщине
Здравствуйте, gandjustas, Вы писали:
G>Но у тебя следующий пакет обработается когда полный цикл отправить-получить-сохранить-отправить.
Откуда ты это берешь? Читай код внимательней.
G>А кабель не при чем, больше всего времени уходит в ожидание ответа сервера.
Какая разница? В любом случае, конкретика будет зависеть от ТЗ, если требуется действия юзера обрабатывать последовательно с т.з. базы, то они ДОЛЖНЫ быть обработаны последовательно.
G>А Queue у тебя thread-safe?
Более того, по коду ProcessorQueue::ProcessTask() и сказанного до этого можно сделать вывод, что там допустима даже дисциплина "один писатель, много читателей", если, скажем, можно было бы запросы пользователя к базе обрабатывать параллельно согласно ТЗ.
G>>>3) запись в базу и в сеть идет последовательно, а не параллельно. MTD>>С чего вдруг? Очередь может иметь пул и по ним раскидывать данные. G>Код в студию. G>Вот уже сложность растет.
Это внешняя сложность диспетчера пула потоков и нужна только для случая, когда запросы пользователя к базе можно обрабатывать параллельно (применительно к вашему примеру). Но такой диспетчер, заметь, пишется однажды на целый дотнетный фремворк. Аналогично он пишется на С++ однажды для целой фирмы для всех проектов/задач или берется один из многих в сети готовых.
G>Ты пот покажи как сделать эту самую эффективную работу, чтобы не ожидать завершения IO в потоке и параллелить операции.
А где там видно, что NetworkRespondQueue.Push(data) что-то там ожидает? Я вижу простое заталкивание в очередь. Сами данные могут пересылаться из очереди асинхронно, через какой-нить boost::asio. Причем, в зависимости от выбранной асинхронной модели, допустима даже асинхронная отсылка без каких-либо неявно создаваемых дополнительных потоков.
Здравствуйте, Ikemefula, Вы писали:
EP>>Фишка в том, что эти ca() можно инкапсуировать в библиотеки, асинхронные вызовы — а await'ы будут засорять все уровни кода. EP>>Более того, синтаксис await'ов можно полностью реализовать на stackfull coroutines (async в объявлении будет не нужен, но будет нужен call_async в месте вызова + такие await могут стоят на "любой глубине"). I>Это просто чушь и незнание истории операционных системы и их возможностей. В винде и лялихе файберы/короутины есть с незапамятных времен.
Congratulation, you won Taradiddle Black Belt!
Где я говорил что в Windows/Linux нет fibers, etc?
I>Потом появляется async/await, хотя казалось бы, stackfull coroutines работают искаропки.
Stackless coroutine реализуются простейшим переписыванием одного кода в другой, т.е. банальный rewrite. Те stackless coroutine которые в Boost.Asio — тому подтверждение.
В то время как stackful coroutines требуют поддержки на уровне среды, вроде же очевидно?
EP>>Корутины позволяют делать асинхронный код похожим на синхронный, и ещё много чего. I>Скажи пожалуйста, а кто будет контролировать все эти нелокальные переходы ? В async/await все понятно — компилятор. Максимум контроля над одной единсвенной небольшой задачей. А что stackfull даёт ? Переходы непойми где ? Вместо однозадачного кода получить кооперативную многозадачность со всеми её проблемами — starvation, гонки, инверсия приоретитов и тд.
Да нет никаких starvation, то что в моём примере есть цикл распределения пакетов, не означает что он должен быть всегда при использовании сопроцедур.
Сопрецедуры не требуют изменения event loop, пример из Boost.Coroutine приведённый выше — тому подтверждение. Там не было никаких изменений в Boost.Asio
I>Ну и вопрос с message pump — http://rsdn.ru/forum/philosophy/5211489.1
I>Тебе понятно, что короутины нужно встроить вообще везде, что бы работал такой код ? В твоем случае он работать не будет, что очевидно, винда не знает про то, что ты используешь короутины.
Да и не должна она знать
I>То есть, для того что бы нормально использовать короутины, надо применить их тотально, то есть вообще везде где угодно.
нет, ты просто не понял как их можно использовать, и разводишь истерику
I>Для примера выше — покажи приблизительный код, который нужно добавить, что бы работала и твоя модная асинхронщина и этот цикл выборки сообщений.
Я уже много всякого кода здесь приводил. А ты даже не осилил
показать простой пример на C#.
Давай ты приведёшь полностью рабочий пример с асинхронностью в "традиционном стиле", на callback'ах — а я переделаю его на stackful coroutine, ок?
Здравствуйте, Ikemefula, Вы писали:
I>Что бы это забороть, надо явно делать короутинами вообще всё, в т.ч. и message pump. То есть на ровном месте педалить и приседать с кооперативной многозадачностью.
Вот смотри, есть у нас некий асинхронный метод, который принимает продолжение:
У сопроцедур есть двусторонний портал.
С одной стороны он красный:
— это вход в корутину.
С другой синий:
— это выход из корутины, в вызвавший её код.
Корутина может дать попользоваться красным порталом кому угодно, в том числе в callback асинхронного метода.
Код приведённый выше, механически переписывается в:
auto &&red_portal = make_shared<Coro>();
*red_portal = Coro([=](Coro::caller_type &blue_portal)
{
async_something( [=]{ (*red_portal)(); } );
blue_portal(); // goes to checkpoint
on_completion();
});
// checkpoint
// Это всё можно заправить синтаксическим сахаром, таким образом, чтобы код был похож на синхронный аналог.
Как видишь, никаких вмешательств в event-loop тут не было — трансформация полностью локализована
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>В то время как stackful coroutines требуют поддержки на уровне среды, вроде же очевидно?
Мне — да. Тебе — нет. Потому ты так и не привел простейшего асинхронного кода с моим message pump.
EP>Да нет никаких starvation, то что в моём примере есть цикл распределения пакетов, не означает что он должен быть всегда при использовании сопроцедур.
Опаньки ! А кто по твоему message pump будет дергать ?
EP>Сопрецедуры не требуют изменения event loop, пример из Boost.Coroutine приведённый выше — тому подтверждение. Там не было никаких изменений в Boost.Asio
Ну раз не требуют, стало быть ты легко накидаешь примерчик с моим message pump. Какие проблемы ?
I>>Ну и вопрос с message pump — http://rsdn.ru/forum/philosophy/5211489.1
I>>Тебе понятно, что короутины нужно встроить вообще везде, что бы работал такой код ? В твоем случае он работать не будет, что очевидно, винда не знает про то, что ты используешь короутины.
EP>Да и не должна она знать
Код покажи.
I>>То есть, для того что бы нормально использовать короутины, надо применить их тотально, то есть вообще везде где угодно.
EP>нет, ты просто не понял как их можно использовать, и разводишь истерику
Я всего то код прошу показать.
I>>Для примера выше — покажи приблизительный код, который нужно добавить, что бы работала и твоя модная асинхронщина и этот цикл выборки сообщений.
EP>Я уже много всякого кода здесь приводил. А ты даже не осилил
Это пример ___________синхронного___________ кода___________с___________кооперативной___________многозадачностью___________.
EP>Давай ты приведёшь полностью рабочий пример с асинхронностью в "традиционном стиле", на callback'ах — а я переделаю его на stackful coroutine, ок?
Возьми любой мой пример, я ажно пять вариантов привел. Только должно быть явно обозначено, как будет вызываться message pump. И message pump именно мой, а не просто какой то эвентлуп для короутин.
Здравствуйте, Ikemefula, Вы писали:
EP>>Сопрецедуры не требуют изменения event loop, пример из Boost.Coroutine приведённый выше — тому подтверждение. Там не было никаких изменений в Boost.Asio I>Ну раз не требуют, стало быть ты легко накидаешь примерчик с моим message pump. Какие проблемы ?
есть только трансформация локального кода, никакой другой код не менялся
EP>>Давай ты приведёшь полностью рабочий пример с асинхронностью в "традиционном стиле", на callback'ах — а я переделаю его на stackful coroutine, ок? I>Возьми любой мой пример, я ажно пять вариантов привел. Только должно быть явно обозначено, как будет вызываться message pump. И message pump именно мой, а не просто какой то эвентлуп для короутин.
Ты понимаешь что такое полностью рабочий пример? Это не те огрызки которые ты тут приводил.
Здравствуйте, alex_public, Вы писали:
_>Вот, отличная формулировка. А я всё не мог подобрать точных слов, когда говорил что лично мне совершенно не нравится этот await/async стиль. Вот как раз тем, что реально асинхронный код притворяется синхронным, оно мне и не нравится. Зачем лишние запутывания на пустом месте и без всякой выгоды? _>А в приведённом пример с фоновым скачиванием файла по запросу пользователя я не вижу разумных причин для применения подобной техники.
ИМХО, основная выгода в том, что synchronous-like код легче понять и меньше синтаксического шума.
Но "легче понять", в случае с await, имеет несколько граней: та синхроноподобность которая добавляется, безусловного помогает упростить видимость control flow'а, но в то же время программист должен знать как оно работает, когда передаётся управление в вызывающий код, в каком контексте что вызывается(UI, etc).
Например есть некая асинхронная функция которая возвращает результат, вызывающему код нужен этот результат. По большому счёту у него два варианта — вызывать .wait() на том future который вернулся, либо воткнуть await и самому стать async'ом. Такой выбор транзитивно распространяется наверх по call stack'у. Конкретно этого недостатка у кода на stackful coroutines нет.
Если всё что нужно это сделать фоновую скачку файла, то вполне могу себе представить ситуацию, где даже при наличии await'а — вместо него будет использоваться явный код с .then'ом, указанием ui контекста и т.п., ибо очевидно что у await'а есть свой порог вхождения, а код не только пишется, но ещё и обслуживается, причём зачастую разными людьми. Например тот же Ikemefula, который бьёт себя пяткой в грудь что заменит целый взвод азиатов, уже неделю не может понять как можно использовать stackful coroutine. Тогда чего уж там говорить о "типичных" программистах.
есть только трансформация локального кода, никакой другой код не менялся
Я уже помнится задавал вопрос — как получит управление message pump, не любой, а именно тот который я привел.
I>>Возьми любой мой пример, я ажно пять вариантов привел. Только должно быть явно обозначено, как будет вызываться message pump. И message pump именно мой, а не просто какой то эвентлуп для короутин.
EP>Ты понимаешь что такое полностью рабочий пример? Это не те огрызки которые ты тут приводил.
Внятно ответь на вопросы
1 — как получит управление МОЙ message pump.
2 — как message pump передаст управление короутине когда процессинг закончится.
Условно считаем так — есть message pump и есть ровно один хандлер который вызывается этим message pump. От тебя требуется показать что нибудь предельно простое, асинхронное, которое реализовано унутре этого хандлера.
Здравствуйте, Ikemefula, Вы писали:
I>>>Возьми любой мой пример, я ажно пять вариантов привел. Только должно быть явно обозначено, как будет вызываться message pump. И message pump именно мой, а не просто какой то эвентлуп для короутин. EP>>Ты понимаешь что такое полностью рабочий пример? Это не те огрызки которые ты тут приводил. I>Внятно ответь на вопросы I>1 — как получит управление МОЙ message pump. I>2 — как message pump передаст управление короутине когда процессинг закончится.
Зависит от того какую асинхронную операцию и как (по какому событию) ты собрался выполнять, поэтому и прошу привести полный пример.
I>Условно считаем так — есть message pump и есть ровно один хандлер который вызывается этим message pump. От тебя требуется показать что нибудь предельно простое, асинхронное, которое реализовано унутре этого хандлера.
Видимо конкретного кода я не дождусь. Давай тогда так:
Я только добавивлю include корутин, и сделаю трансформацию описанную выше внутри task.
Такой пример подойдёт?
I>Пока что ты продемонстрировал замерзание UI.