Здравствуйте, Ikemefula, Вы писали:
_>>Evgeny.Panasyuk показывал в большинстве случаев вообще другие примеры, не имеющие прямого отношения к await/async, но при этом однозначно являющиеся примерами асинхронного программирования. Это случаи когда у нас есть некий callback, вызываемый откуда-то снаружи (например из ОС). Это на самом деле вполне часто встречающаяся задача и как раз асинхронная. Соответственно Evgeny.Panasyuk показал что можно красиво и удобно записывать такой код с помощью сопроцедур (из Boost'a), превращая их в линейный, без выделения спец. функции для callback'a. I>
I>function getSin(param, end)
I>{
I> end(Math.sin(param));
I>}
I>getSin(45, function(result){ ля ля ля})
I>
I>вот этот вызов выглядит как асинхронный, при этом в данном примере нет ничего асинхронного, обычный event driven подоход, а вы с EP почему то называете такой хлам асинхронщиной
ловко ты async_something превратил просто в something, ага
так ведь и async_download
I>function getSin(param, end)
I>{
I> end(Math.sin(param));
I>}
I>getSin(45, function(result){ ля ля ля})
I>вот этот вызов выглядит как асинхронный, при этом в данном примере нет ничего асинхронного, обычный event driven подоход, а вы с EP почему то называете такой хлам асинхронщиной
I>
Нет, тут показывались совсем другие примеры. Ничего похожего на это.
Предположим что у нас есть функция Read(buf, callback), которая читает некие данные в буфер и после этого вызывает callback. Из какого потока реально вызывается callback тут не принципиально. Это довольно распространённый случай и думаю не надо объяснять как обычно используют такие функции.
Так вот, Evgeny.Panasyuk показывал что можно пользоваться не только традиционным способом, но и так:
Read(buf, coro);//передаём вместо обычного callback'a наш специальный на базе сопроцедуры
yield();//вызодим из функции
ProcessBuf(buf);//выполняется как callback функции read, но в контексте текущей функции
Это вполне удобный механизм сам по себе. И кстати я не очень представляю как можно записать подобное на C#.
Ну а если дополнить это механизмами инициации этого самого callback'a (как было в моих примерах), то получим как раз реализацию await/async. )))
Здравствуйте, alex_public, Вы писали:
_>Так вот, Evgeny.Panasyuk показывал что можно пользоваться не только традиционным способом, но и так: _>
_>Read(buf, coro);//передаём вместо обычного callback'a наш специальный на базе сопроцедуры
_>yield();//вызодим из функции
_>ProcessBuf(buf);//выполняется как callback функции read, но в контексте текущей функции
_>
_>Это вполне удобный механизм сам по себе. И кстати я не очень представляю как можно записать подобное на C#.
await/async
_>Ну а если дополнить это механизмами инициации этого самого callback'a (как было в моих примерах), то получим как раз реализацию await/async. )))
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>>getline дёрнет TcpStream, который вызовет yield, после которого управление вернётся в message pump I>>Ну а до того цикл будет висеть, правильно ?
EP>До yield'а? Ну да, так же как и до await'а
Начинаем все сначала — кто вернет управление в message pump, пока getline не вернет значение ?
Ты хоть у alex_public подсмотри решение — RunAll в message pump или по таймеру (для которого тоже нужен message pump).
I>>Вопрос — как его запустить ДО того как getline вернет управление.
EP>Вернёт управление куда? в while цикл с getline'ом? Ну так message pump и так запустится до этого, сразу после yield'а внутри TcpStream
Представь себе такое — getline получит значения через полчаса. Каким образом будет работать UI ? С await все понятно — UI будет работать, потому что message pump никто не останавливал. А вот с getline все непросто — ты его просто вызвал в хандлере, который вызвался из message pump.
I>>От тебя требовался один пример явной работы с message pump
EP>Был не один пример с message pump'ом — и с asio'вским, и с win32, и даже с самодельным
Ты показал все, кроме того что надо — МОЙ message pump и твой getline.
I>>getline в твоем примере выполняется СИНХРОННО. Это значит, что следующая строчка после getline получит результат ПОСЛЕ того, как getline вернет управление.
EP>1. Asynchronous I/O: EP>
EP>Asynchronous I/O, in computer science, is a form of input/output processing that permits other processing to continue before the transmission has finished.
Эдак у тебя всё станет асинхронным. Главный поток спит, но выполняются другие потоки, значит по этому определению все асинхронно. Ерунда что главный поток блокирован и юзер ничего не видит, главное что все асинхронно.
EP>2. Если по-твоему строчка getline выполняется "СИНХРОННО", то и строчка await async_download: EP>
Разумеется. Толко эта хрень не блокирует message pump. Странно, да ?
>ведь "следующая строчка после getline await async_download получит результат ПОСЛЕ того, как getline await async_download вернет управление"
Правильно, ты наконец понял, что я тебе говорю уже две недели. Представь, наличие await не блокирует message pump, просто по той причине, что компилер сам генерит нужный код. То есть, возвращает управление в message pump. Это вобщем очевидно — код раскидывается на continuation и далее выход из метода в вызывающий. Самый верхний хандлер дергается именно из message pump, который никогда не делает ожидания, представь себе весь ужас
Открой любой туториал по await/async и там найдешь красные стрелочки которые ведут в этот message pump. В твоем getline ничего такого нет, соответсвенно UI будет блокирован.
Здравствуйте, Ikemefula, Вы писали:
EP>>ловко ты async_something превратил просто в something, ага I>Ты лучше свой пример про getline изучи внимательно.
И где связь между твоим getSin, который сразу вызывает продолжение с результатом, и getline который внутри yield'ится в main loop?
EP>>так ведь и async_download
который ты таки называл "асинхронщиной", в котором никакого await'а
I>вот этот вызов выглядит как асинхронный, при этом в данном примере нет ничего асинхронного, обычный event driven подоход, а вы с EP ты почему то называете называешь такой хлам асинхронщиной
I>у меня в примере async_download неблокирующий. await делает ожидание. сам метод где помещен код будет неблокирующим, что очевидно.
Вызываются "handler"'ы (в твоих терминах). В каждом "handler"'е код выполняется до каждого yield'а и сразу возвращается сюда — так же как и в C# с async/await код выполняется до первого await'а. Это в твоих понятиях являются асинхронными вызовами или нет?
Когда "event loop" ныряет в сопроцедуру — это аналог тому, когда await дожидается своего таска.
Все остальные yield'ы в "handler"'ах — аналогичны последующим await'ам и т.п.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>И где связь между твоим getSin, который сразу вызывает продолжение с результатом, и getline который внутри yield'ится в main loop?
твой getline в main loop ничего не yield'дит. Наверное ты забыл, но от тебя не было такого примера — мой message pump и твой getline.
EP>я говорил про код: EP>
вызванный из корутины, и имеющий внутри getline тоже неблокирующий
если getline неблокирующий, значит следующая за ним строчка выполнится ДО того как придут данные. Ты это хотел сказать ?
Если нет, то getline блокирующий, а стало быть, если его вызвать из message loop, он все повесит
EP>Я уже тебе это объяснял, но как-то туго идёт: EP>[q] EP>Вызываются "handler"'ы (в твоих терминах).
Здравствуйте, Ikemefula, Вы писали:
EP>>>>getline дёрнет TcpStream, который вызовет yield, после которого управление вернётся в message pump I>>>Ну а до того цикл будет висеть, правильно ? EP>>До yield'а? Ну да, так же как и до await'а I>Начинаем все сначала — кто вернет управление в message pump, пока getline не вернет значение ?
yield на 37 строчке, который находится внутри TcpStream, который дёргается getline'ом
I>>>Вопрос — как его запустить ДО того как getline вернет управление. EP>>Вернёт управление куда? в while цикл с getline'ом? Ну так message pump и так запустится до этого, сразу после yield'а внутри TcpStream I>Представь себе такое — getline получит значения через полчаса. Каким образом будет работать UI ? С await все понятно — UI будет работать, потому что message pump никто не останавливал. А вот с getline все непросто — ты его просто вызвал в хандлере, который вызвался из message pump.
И внутри он yield'нулся обратно в message pump
I>>>От тебя требовался один пример явной работы с message pump EP>>Был не один пример с message pump'ом — и с asio'вским, и с win32, и даже с самодельным I>Ты показал все, кроме того что надо — МОЙ message pump и твой getline.
Я уже показал пример асинхронной операции с win32 message pump. Делать ещё примеры нет никакого желания, по двум причинам: с твоей стороны не было запрошенных примеров (кроме неработающих огрызков), на каждый мой пример ты придумываешь нелепые отмазки
EP>>2. Если по-твоему строчка getline выполняется "СИНХРОННО", то и строчка await async_download: EP>>
EP>>также выполняется синхронно? I>Разумеется. Толко эта хрень не блокирует message pump. Странно, да ?
Я уже показывал примеры где message pump не блокируется. Тебе они не понятны? Нужен очередной ликбез?
>>ведь "следующая строчка после getline await async_download получит результат ПОСЛЕ того, как getline await async_download вернет управление"
I>Правильно, ты наконец понял, что я тебе говорю уже две недели. Представь, наличие await не блокирует message pump, просто по той причине, что компилер сам генерит нужный код. То есть, возвращает управление в message pump. Это вобщем очевидно — код раскидывается на continuation и далее выход из метода в вызывающий.
Ты до сих пор не понял, что yield у stackful coroutine превращает весь последующий код в "неявное" продолжение и возвращает управление в message pump?
I>Открой любой туториал по await/async и там найдешь красные стрелочки которые ведут в этот message pump. В твоем getline ничего такого нет, соответсвенно UI будет блокирован.
Я понял, что ты совершенно не понял как здесь используются stackful coroutine, да нужен очередной ликбез..
Здравствуйте, Ikemefula, Вы писали:
EP>>И где связь между твоим getSin, который сразу вызывает продолжение с результатом, и getline который внутри yield'ится в main loop? I>твой getline в main loop ничего не yield'дит.
вызванный из корутины, и имеющий внутри getline тоже неблокирующий I>если getline неблокирующий, значит следующая за ним строчка выполнится ДО того как придут данные. Ты это хотел сказать ? I>Если нет, то getline блокирующий, а стало быть, если его вызвать из message loop, он все повесит
Ещё раз, coroutine_start вызванный из корутины — неблокирующий. Как только код выполнения наткнётся на первый yield (неважно на какой глубине, это не one-level await) — управление вернётся в message loop
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>>И где связь между твоим getSin, который сразу вызывает продолжение с результатом, и getline который внутри yield'ится в main loop? I>>твой getline в main loop ничего не yield'дит.
EP>Если ты так думаешь, то объясни каким образом там получился результат
имелось ввиду message pump, которого у тебя просто нет, а надо что бы был
I>>если getline неблокирующий, значит следующая за ним строчка выполнится ДО того как придут данные. Ты это хотел сказать ? I>>Если нет, то getline блокирующий, а стало быть, если его вызвать из message loop, он все повесит
EP>Ещё раз, coroutine_start вызванный из корутины
Не отвлекайся, дай наконец внятный ответ: "getline блокирующий или нет ?".
Если нет, с message pump все в порядке, но не ясно, как результат связывается.
Если да, то надо явно дергать message pump.
Других вариантов просто нет и до тебя это пока не доходит.
Пока что у тебя позиция "войны не объявлять, мира не подписывать, армию распутить"
Здравствуйте, Ikemefula, Вы писали:
_>>Это вполне удобный механизм сам по себе. И кстати я не очень представляю как можно записать подобное на C#. I>await/async
await чего будем вызывать? )
I>только все руками.
Ну да, руками, но как бы один раз, а не для каждого вызова отдельно. Как и было показано в моих примерах. Т.е. мы можем закинуть эту реализацию в библиотеку и ситуация станет неотличимой от C#. Ну это кроме того, что тут у нас больше возможностей.
Здравствуйте, alex_public, Вы писали:
_>await чего будем вызывать? )
await method.
I>>только все руками.
_>Ну да, руками, но как бы один раз, а не для каждого вызова отдельно. Как и было показано в моих примерах. Т.е. мы можем закинуть эту реализацию в библиотеку и ситуация станет неотличимой от C#. Ну это кроме того, что тут у нас больше возможностей.
А еще больше возможностей будет если на ассемблере писать.
Здравствуйте, Ikemefula, Вы писали:
I>await method.
Ещё раз, у нас есть функция Read(buf, callback). Такое частенько встречается. Сама функция не блокирующая, но и не возвращает никаких значений (типа Task). И так, await чего мы тут будем вызывать, что бы код следующий за Read вызвался внутри callback и обработал buf?
Здравствуйте, alex_public, Вы писали:
I>>await method.
_>Ещё раз, у нас есть функция Read(buf, callback). Такое частенько встречается. Сама функция не блокирующая, но и не возвращает никаких значений (типа Task). И так, await чего мы тут будем вызывать, что бы код следующий за Read вызвался внутри callback и обработал buf?
Значит будет возвращать Task и делать ему await, не вижу принципиальной разницы. Если сравнивать построчно, то можно дойти до того что "В С++ нет using, finally а в С# нет деструкторов"
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>yield на 37 строчке, который находится внутри TcpStream, который дёргается getline'ом
Интересно, как ты вызываешь message pump который отсутствует ? Надо понимать это буст такой умный, проанализирует память и решит, что надо вызвать MessagePump, сходит на RSDN, сделает поиск по моим сообщениям, найдет цикл, скомпилирует его и выполнит.
I>>Представь себе такое — getline получит значения через полчаса. Каким образом будет работать UI ? С await все понятно — UI будет работать, потому что message pump никто не останавливал. А вот с getline все непросто — ты его просто вызвал в хандлере, который вызвался из message pump.
EP>И внутри он yield'нулся обратно в message pump
Там нет message pump, там просто какой то цикл.
EP>Я уже показал пример асинхронной операции с win32 message pump. Делать ещё примеры нет никакого желания, по двум причинам: с твоей стороны не было запрошенных примеров (кроме неработающих огрызков), на каждый мой пример ты придумываешь нелепые отмазки
Ты в начало треда посмотри и заметишь, что я повторяю один и тот же вопрос и так и не получил на него ответа.
EP>>>также выполняется синхронно? I>>Разумеется. Толко эта хрень не блокирует message pump. Странно, да ?
EP>Я уже показывал примеры где message pump не блокируется. Тебе они не понятны? Нужен очередной ликбез?
Нет, ты ничего подобного не показывал. мой message pump и твой getline — валяй.
EP>Ты до сих пор не понял, что yield у stackful coroutine превращает весь последующий код в "неявное" продолжение и возвращает управление в message pump?
Мы говорим не о том, что во что превращает, а как твой getline вернет управление в мой message pump.
EP>Я понял, что ты совершенно не понял как здесь используются stackful coroutine, да нужен очередной ликбез..
Я уже лет наверное 7-8 в курсе как и для чего они используются, еще с тех времен, как писал такую логику на файберах, а потом писал на питоне, а потом писал логику под Q3 движок, а потом писал yield-expression для C#, а потом приспосабливал yield return под обработку эвентов и тд и тд и тд.
Здравствуйте, Ikemefula, Вы писали:
I>Не отвлекайся, дай наконец внятный ответ: "getline блокирующий или нет ?".
Вызов getline, с точки зрения метода foo, очевидно блокирующий
coroutine_start вызванный из корутины, и имеющий внутри getline, — неблокирующий.
I>Если да, то надо явно дергать message pump.
Зачем дёргать? внутри TcpStream стоит yield, который вернёт управление (аналогично await'у, только "многоуровневый")
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Вызов getline, с точки зрения метода foo, очевидно блокирующий
Правильно, и с чем ты спорил ?
I>>Если да, то надо явно дергать message pump.
EP>Зачем дёргать? внутри TcpStream стоит yield, который вернёт управление (аналогично await'у, только "многоуровневый")
Представь — стрим заснул на пол-часа, нет данных. Что будет с UI ?
Покажи код — мой message pump и твой getline.
Здравствуйте, Ikemefula, Вы писали:
I>>>Представь себе такое — getline получит значения через полчаса. Каким образом будет работать UI ? С await все понятно — UI будет работать, потому что message pump никто не останавливал. А вот с getline все непросто — ты его просто вызвал в хандлере, который вызвался из message pump.
EP>>И внутри он yield'нулся обратно в message pump I>Там нет message pump, там просто какой то цикл.
конечно, просто какой-то цикл, просто по каким-то сообщениям стоящим в очереди, просто доставляемых конкретным корутинам
EP>>Я уже показал пример асинхронной операции с win32 message pump. Делать ещё примеры нет никакого желания, по двум причинам: с твоей стороны не было запрошенных примеров (кроме неработающих огрызков), на каждый мой пример ты придумываешь нелепые отмазки I>Ты в начало треда посмотри и заметишь, что я повторяю один и тот же вопрос и так и не получил на него ответа.
"Ты в начало треда посмотри и заметишь" что запрошенного примера на C# нет до сих пор
"Ты в начало треда посмотри и заметишь" что запрошенного примера на С++ без корутин
I>Вот и покажи эту асинхронщину на короутинах. Забудь про MesageBox, TcpStream и тд. Сделай что нибудь внятное, ну хоть Thread.Sleep() если ничего в голову не приходит. Покажи версию без корутин на C++ — я её переделаю на корутины. А то ты опять будешь кричать что это не "асинхронщина".
EP>>>>также выполняется синхронно? I>>>Разумеется. Толко эта хрень не блокирует message pump. Странно, да ? EP>>Я уже показывал примеры где message pump не блокируется. Тебе они не понятны? Нужен очередной ликбез? I>Нет, ты ничего подобного не показывал.
В моих примерах не было message pump? message pump блокировался?
I>Я уже лет наверное 7-8 в курсе как и для чего они используются, еще с тех времен, как писал такую логику на файберах, а потом писал на питоне, а потом писал логику под Q3 движок, а потом писал yield-expression для C#, а потом приспосабливал yield return под обработку эвентов и тд и тд и тд.
и если после этого тебе мерещатся заблокированные ui-loop-ы — то как-то совсем печально
Здравствуйте, Evgeny.Panasyuk, Вы писали:
I>>Там нет message pump, там просто какой то цикл.
EP>конечно, просто какой-то цикл, просто по каким-то сообщениям стоящим в очереди, просто доставляемых конкретным корутинам
Это никому не интересно. Внезапно, если в системе есть message pump, то ни про какие 200К короутин речи быть не может. А я пока что слабо представляю преложение без такого message pump. То есть, короутины заканчиваются, не успев начаться.
EP>"Ты в начало треда посмотри и заметишь" что запрошенного примера на C# нет до сих пор
Разумеется, пока ты не дашь ответа на мой вопрос, я его задал ажно две недели назад, я ничего не собираюсь показывать.
Ты напоказывал вагоны кода, которые тебя никто вообще не просил и так и не дал ответа на поставленый вопрос.
EP>Покажи версию без корутин на C++ — я её переделаю на корутины. А то ты опять будешь кричать что это не "асинхронщина". EP>[/q]
Вот еще пример — я показал код со Sleep и все на этом закончилось.
I>>Нет, ты ничего подобного не показывал.
EP>В моих примерах не было message pump? message pump блокировался?
Какие то циклы меня не интересуют. Меня интересует ровно один вариант — твой getline и мой message pump
EP>и если после этого тебе мерещатся заблокированные ui-loop-ы — то как-то совсем печально
Ты сам сказал, что getline блокирующий, раз так, надо показывать всё решение, в частности, как при этом будет работать message pump.
На stackless coroutine такая инкапсуляция не получится — асинхронные кишки будут торчать в клиентском коде, ибо такие сопроцедуры (без асинхронных кишок в клиентском коде) сразу возвращают управление в клиентский код — а это значит что либо данные ещё не получены, либо никакой асинхронности, так как только один поток.
I>>>Если да, то надо явно дергать message pump. EP>>Зачем дёргать? внутри TcpStream стоит yield, который вернёт управление (аналогично await'у, только "многоуровневый") I>Представь — стрим заснул на пол-часа, нет данных. Что будет с UI ?