Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>У тебя какое-то плоское представление о мире.
I>>Предположим, это единственный код в приложении, а чтение из стрима занимает 5 минут. Итого — асинхронщина, в твоем понимании, это зависание UI на 5 минут.
EP>Не будет зависания — до прихода данных из стрима управление передаться в другое место. Если там UI — то в UI loop
Судя по описанию boost.coroutine это аналог yield в сишарп или питоне, потому никакой асинхронщины тут нет, когда работает один — другой спит и наоборот.
Здравствуйте, Ikemefula, Вы писали:
I>Ты хочешь показать асинхронщину "где то то там", а я прошу "где то здесь"
Я показываю, то как можно полностью инкапсулировть "асинхронщину", вообще без вмешательств в клиентский код.
I>>>Предположим, это единственный код в приложении, а чтение из стрима занимает 5 минут. Итого — асинхронщина, в твоем понимании, это зависание UI на 5 минут. EP>>Не будет зависания — до прихода данных из стрима управление передаться в другое место. Если там UI — то в UI loop
I>В какое другое?
В любое. Если надо — в event loop, если надо в asio, или ещё куда-нибудь.
I>Или короутина такая умная, что пороется в адресном пространстве процесса и скажет "О, пока я буду спать, пусть повыполняется вот этот кусочек кода" и некоторым чудом окажетс так, что этот некоторый кусочек кода и будет тем который мне нужен ?
Нигде она не будет рыться, она просто сделает yield.
I>Покажи весь код, для полноты картины.
, и мне не придётся показывать ещё один пример.
I>Если UI loop и короутина работают асинхронно, покажи именно эту асинхронщину. Ну и до кучи покажи как руками написать метод навроде getline.
getline тут самый стандартный, который std::getline.
I>Покажи весь код, для полноты картины. Если UI loop и короутина работают асинхронно, покажи именно эту асинхронщину. Ну и до кучи покажи как руками написать метод навроде getline.
Здравствуйте, Ikemefula, Вы писали:
I>Судя по описанию boost.coroutine это аналог yield в сишарп или питоне
Hint: ты в Python или C# через сколько уровней можешь yield'ануть?
Если брать Python то ближайший аналог это gevent, который ни разу ни yield. Более того, у gevent есть фишка — он может на ходу сделать monkey patch стандартных сокетов, и фактически весь синхронный код становится асинхронным
I>потому никакой асинхронщины тут нет, когда работает один — другой спит и наоборот.
В моём примере, при вызове getline, если данные сразу не готовы, то текущий засыпает и управление передаётся другому.
Здравствуйте, Ikemefula, Вы писали:
I>>>когда получит управление код после getline ? Ну, например, если сделать вот так I>>>
I>>>getline(client_stream, msg);
I>>>SendMessage(hwnd,WM_SET_TEXT,msg, NULL); // когда сюда придет управление
I>>>
EP>>Управление придёт после того как msg прочитается из stream'а.
I>А где же асинхронщина ? Предположим, это единственный код в приложении, а чтение из стрима занимает 5 минут. Итого — асинхронщина, в твоем понимании, это зависание UI на 5 минут.
Так а после await когда придёт управление? Это же полный аналог твоего кода:
private async void handler(object sender, TaskArgs args)
{
string result = await new Task(() => Download(args.Url), args.Cancellation);
textBox.Text += result; // когда сюда придет управление
}
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>getline тут самый стандартный, который std::getline.
Ну ты не перебарщивай. К этому getline нужна таки обёртка, которая будет откидывать управление из корутины и получать его назад, по типу той что я писал выше.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
I>>Ты хочешь показать асинхронщину "где то то там", а я прошу "где то здесь"
EP>Я показываю, то как можно полностью инкапсулировть "асинхронщину", вообще без вмешательств в клиентский код.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR lpCmdLine, int nCmdShow)
{
::AttachConsole(); // появляется консолька
MSG msg;
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
some_window_handler(...)
{
getline() // упростил, консолька есть, значит можно читать из неё
// здесь мы выяснили, будет ожидание, хандлер вызывается прямо из DispatchMessage, стало быть ...
}
Итого если этот метод висит до получаения результат, то очевидно, что и UI loop висит, а соответсвенно и UI висит. Может короутина догадается что надо сделать луп ? Или догадается вызвать WinMain ?
I>>>>Предположим, это единственный код в приложении, а чтение из стрима занимает 5 минут. Итого — асинхронщина, в твоем понимании, это зависание UI на 5 минут. EP>>>Не будет зависания — до прихода данных из стрима управление передаться в другое место. Если там UI — то в UI loop
I>>В какое другое?
EP>В любое. Если надо — в event loop, если надо в asio, или ещё куда-нибудь.
Ты ждешь от короутины чудес. Все что она делает это передает управление двумя способами — по методу send и по методу yield. send активирует короутину, yield активирует вызывающий код. Больше ничего не делается.
I>>Или короутина такая умная, что пороется в адресном пространстве процесса и скажет "О, пока я буду спать, пусть повыполняется вот этот кусочек кода" и некоторым чудом окажетс так, что этот некоторый кусочек кода и будет тем который мне нужен ?
EP>Нигде она не будет рыться, она просто сделает yield.
EP>Давай ты сначала покажешь аналог, ок?
Аналог чего ? Я не вижу асинхронного кода, ты даже не можешь показать, каким образом короутина узнает про UI loop.
I>>Если UI loop и короутина работают асинхронно, покажи именно эту асинхронщину. Ну и до кучи покажи как руками написать метод навроде getline.
EP>getline тут самый стандартный, который std::getline.
Нет, так не пойдет. Я хочу простейший пример асинхронщины Пока что у тебя ничего нет.
Здравствуйте, Mazay, Вы писали:
I>>Покажи весь код, для полноты картины. Если UI loop и короутина работают асинхронно, покажи именно эту асинхронщину. Ну и до кучи покажи как руками написать метод навроде getline.
M>Я же тебе показал здесь: http://rsdn.ru/forum/philosophy/5209707.1
Здравствуйте, Evgeny.Panasyuk, Вы писали:
I>>потому никакой асинхронщины тут нет, когда работает один — другой спит и наоборот.
EP>В моём примере, при вызове getline, если данные сразу не готовы, то текущий засыпает и управление передаётся другому.
Кому другому ? Покажи как приготовить этого другого.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>По синтаксису вполне реально — либо через перегрузку операторов, либо через expression trees. Но да, в обоих случаях будет много динамики.
Ну так а зачем тогда кодировать парсер кодом, если он всё равно собирается динамично? Тогда уж более гибко его внешним текстом настраивать, а таких у нас полно. Bison тот же берём и всё. )))
Здравствуйте, Mazay, Вы писали:
I>>А где же асинхронщина ? Предположим, это единственный код в приложении, а чтение из стрима занимает 5 минут. Итого — асинхронщина, в твоем понимании, это зависание UI на 5 минут.
M>Так а после await когда придёт управление? Это же полный аналог твоего кода: M>
M>private async void handler(object sender, TaskArgs args)
M>{
M> string result = await new Task(() => Download(args.Url), args.Cancellation);
M> textBox.Text += result; // когда сюда придет управление
M>}
M>
Нет, это не аналог. Этот хандлер вернет управление сразу, без блокирования, то есть, отпустит UI Loop. А вот внутренности хандлера будут работать иначе — сколько раз эти внутренности пнет шедулер — зависит от кода хандлера.
Здравствуйте, Mazay, Вы писали:
EP>>getline тут самый стандартный, который std::getline. M>Ну ты не перебарщивай. К этому getline нужна таки обёртка, которая будет откидывать управление из корутины и получать его назад, по типу той что я писал выше.
Здравствуйте, Ikemefula, Вы писали:
I>Написать просто что бы написать а требования к производительности взяты от балды ? Цель какая у этой задач ?
Там много для чего можно использовать. Например те же самые Boost.Xpressive (регэкспы кодирующиеся прямо в C++ и компилирующиеся там же) релизованы через Spirit. Но лично я чаще всего вижу его как максимально быстрый и удобный парсер (хотя там есть и генератор и лексер).
I>Если таки речь про либу и патчить стек это нормально, то в дотнете, как и в джаве, никто не мешает сделать вот так https://code.google.com/p/coroutines/ I>Это собственно аналог boost.coroutines.
Между "никто не мешает сделать" и "продукт выпущен" большая разница. Так то я не спорю что в теории это возможно везде. А вот где можно прямо сейчас взять и использовать — это совсем другой вопрос.
I>"там реализация асинхронности обязательно резко возвращает управление из функции после вызова await" I>Это и есть асинхронность. Если управление не возвращать, асинхронности не получится. Как то так.
Не возвращать управление — это не значит заблокироваться на задаче, а значит ещё немного поисполнять некий наш код. Но вообще это всё вопрос терминологии. В том смысле какой уровень вложенности функций мы рассматриваем.
I>У тебя запускается 5 паралельных тасков. Покажи цитатой из кода ожидание именно этих пяти тасков, а не тех, что внутри этих пяти.
Аааа в этом смысле ожидать. Ну так в той задаче это просто не требовалось, но думаю что очевидно что прямо нужный код у нас имеется, т.к, он запускается для внутренних функций.
Здравствуйте, Ikemefula, Вы писали:
I>Покажи весь код, для полноты картины. Если UI loop и короутина работают асинхронно, покажи именно эту асинхронщину. Ну и до кучи покажи как руками написать метод навроде getline.
Асинхронность то кодируется совсем не с помощью coroutine, а например (как в моём коде) через std::async. A coroutine нужна что бы вернуть управление после выполнения асинхронной части в код расположенный после кода запуска асинхронной задачи.
Здравствуйте, alex_public, Вы писали:
I>>Написать просто что бы написать а требования к производительности взяты от балды ? Цель какая у этой задач ?
_>Там много для чего можно использовать. Например те же самые Boost.Xpressive (регэкспы кодирующиеся прямо в C++ и компилирующиеся там же) релизованы через Spirit. Но лично я чаще всего вижу его как максимально быстрый и удобный парсер (хотя там есть и генератор и лексер).
Цель этой максимальной быстрости ? Если быстро парсить регэкспы в компайлтайм, то не ясно, как часто это становится узким местом, ибо регэкспы в рантайме это совсем другая вещь. Да и ДСЛ для этого корявый.
I>>Если таки речь про либу и патчить стек это нормально, то в дотнете, как и в джаве, никто не мешает сделать вот так https://code.google.com/p/coroutines/ I>>Это собственно аналог boost.coroutines.
_>Между "никто не мешает сделать" и "продукт выпущен" большая разница. Так то я не спорю что в теории это возможно везде. А вот где можно прямо сейчас взять и использовать — это совсем другой вопрос.
Ты лучше помоги EP, а то он не может асинхрощину найти в синхронном коде. Если нужно решать конкретные задачи — их легко порешать через async/await, безо всяких либов.
Собтсвенно это короутины, к которым прикручен шедулер. В бусте точно так же и сделано и это одна из причин по которой EP не может объяснить, как короутина вызовт UI Loop — нужно руками добиться этого, например вынести UI loop в такую же короутину. Только здесь получается не асинхронщина, а кооперативная многозадачность, что собтсвенно и делает короутина. Больше ничего она не делает. Вообще. Никогда. Нигде.
I>>"там реализация асинхронности обязательно резко возвращает управление из функции после вызова await" I>>Это и есть асинхронность. Если управление не возвращать, асинхронности не получится. Как то так.
_>Не возвращать управление — это не значит заблокироваться на задаче, а значит ещё немного поисполнять некий наш код. Но вообще это всё вопрос терминологии. В том смысле какой уровень вложенности функций мы рассматриваем.
см выше про кооперативную многозадачность. Если интересно, есть статья про короутины в питоне, там пример такой же мульки. Короутины в C# кастрированые, но они есть — yield. Можно добиься аналогичного, но более многословного варианта по сравнению с питоном.
I>>У тебя запускается 5 паралельных тасков. Покажи цитатой из кода ожидание именно этих пяти тасков, а не тех, что внутри этих пяти.
_>Аааа в этом смысле ожидать. Ну так в той задаче это просто не требовалось, но думаю что очевидно что прямо нужный код у нас имеется, т.к, он запускается для внутренних функций.
Теперь никаких претензий нет или ты все еще хочешь что бы я добавил еще одну строчку в свой пример навроде result = await result.Content.GetBytes() ?
Здравствуйте, Ikemefula, Вы писали:
I>Здравствуйте, Mazay, Вы писали:
I>>>А где же асинхронщина ? Предположим, это единственный код в приложении, а чтение из стрима занимает 5 минут. Итого — асинхронщина, в твоем понимании, это зависание UI на 5 минут.
M>>Так а после await когда придёт управление? Это же полный аналог твоего кода: M>>
M>>private async void handler(object sender, TaskArgs args)
M>>{
M>> string result = await new Task(() => Download(args.Url), args.Cancellation);
M>> textBox.Text += result; // когда сюда придет управление
M>>}
M>>
I>Нет, это не аналог. Этот хандлер вернет управление сразу, без блокирования, то есть, отпустит UI Loop. А вот внутренности хандлера будут работать иначе — сколько раз эти внутренности пнет шедулер — зависит от кода хандлера.
Так тогда ещё проще:
boost::asio::ip::tcp::resolver::iterator it = ...;
auto textBox = new TextBox(...);
...
sock.async_connect(*it, [&textBox](const boost::system::error_code& ec)
{ if (not ec) textBox->text = "connected!!!"/*это хэндлер, который выполнится сразу после завершения асинхронного коннекта*/ }
);
textBox->text = "connecting ..."; // а это выполнится сразу после асинхронного вызова, то есть sock.async_connect вернёт управление сразу.
Здесь даже корутины ни к чему.
Слушай, у меня тут подозрения на счёт await возникло:
private async void handler(object sender, TaskArgs args)
{
string result = await new Task(() => Download(args.Url), args.Cancellation);
textBox.Text += result;
textBox.Color = Red; // а когда сюда придет управление ??
}
Здравствуйте, Ikemefula, Вы писали:
I>Судя по описанию boost.coroutine это аналог yield в сишарп или питоне, потому никакой асинхронщины тут нет, когда работает один — другой спит и наоборот.
Всё правильно. Только данный yield работает не просто как возврат из функции, а связывает два произвольных (!) куска кода в программе. Соответственно мы ставим одну метку на требуемый код, а вторую в обработчик ui потока и получаем нужный результат. И да, он при этом полностью синхронный. Но в самой асинхронности то вообще ни у кого никогда проблем не было. Вызываем любой вариант (например std::async) и добавляем асинхронность. Но фишка await/async же не в тупо асинхронности, а в продолжение исполнения кода внутри вызывающего потока после завершения вызванного, причём с точки запуска асинхронного вызова. Вот как раз это boot.coroutine и реализует.
Здравствуйте, alex_public, Вы писали:
I>>Покажи весь код, для полноты картины. Если UI loop и короутина работают асинхронно, покажи именно эту асинхронщину. Ну и до кучи покажи как руками написать метод навроде getline.
_>Асинхронность то кодируется совсем не с помощью coroutine, а например (как в моём коде) через std::async. A coroutine нужна что бы вернуть управление после выполнения асинхронной части в код расположенный после кода запуска асинхронной задачи.
Правильно, об чем и речь. Потому никаких фокусов нет и быть не может, о чем я и говорю. Короутина нужна для того, что бы сделать энергичный код ленивым, как результат, легко делается кооперативная многозадачность. В винде есть файберы, как раз это же и делают. В бусте сэмулировали эти файберы. В дотнет есть проблема — файберы не поддерживаются рантаймом, и по моему хорошо что так сделано
При этом повторяю — нет в короутинах асинхронщины, асинхронщину берет на себя шедулер, который надо еще правильно приготовить, скормить ему набор короутин между которыми он и будет переключаться.
Здравствуйте, Mazay, Вы писали:
M>Здесь даже корутины ни к чему.
Спасибо, капитан
M>Слушай, у меня тут подозрения на счёт await возникло:
M>
M>private async void handler(object sender, TaskArgs args)
M>{
M> string result = await new Task(() => Download(args.Url), args.Cancellation);
M> textBox.Text += result;
M> textBox.Color = Red; // а когда сюда придет управление ??
M>}
M>
После await, что очевидно. Хандлер развернется в класс, вызывающий метод просто инстанцирует класс и сразу получит управление. А дальше за выполнением кода собственно хандлера будет следить шедулер. Код между await заменится на промисы и замыкания.
async/await это не короутина, это сахар для вызова шедулера и заворачивания кода в промисы и замыкания, примерно так, короутина всего лишь будет использоваться этим сахаром.
Здравствуйте, alex_public, Вы писали:
I>>Судя по описанию boost.coroutine это аналог yield в сишарп или питоне, потому никакой асинхронщины тут нет, когда работает один — другой спит и наоборот.
_>Всё правильно. Только данный yield работает не просто как возврат из функции, а связывает два произвольных (!) куска кода в программе. Соответственно мы ставим одну метку на требуемый код, а вторую в обработчик ui потока и получаем нужный результат.
Покажи этот код, а то вот EP не может
> И да, он при этом полностью синхронный. Но в самой асинхронности то вообще ни у кого никогда проблем не было.
Сомневаюсь, на счет асинхронности.
>Вызываем любой вариант (например std::async) и добавляем асинхронность. Но фишка await/async же не в тупо асинхронности, а в продолжение исполнения кода внутри вызывающего потока после завершения вызванного, причём с точки запуска асинхронного вызова. Вот как раз это boot.coroutine и реализует.
короутина всего лишь передает управление. Больше ничего она не делает. await/async это сахар для шедулера, а не для короутины, этот сахар вызывает короутину, которую генерит компилер.