Re[36]: Что посоветуете как аналог С++
От: Evgeny.Panasyuk Россия  
Дата: 06.07.13 15:11
Оценка:
Здравствуйте, artelk, Вы писали:

A>1. Покажи, как это будет выглядеть, если foo возвращает результат? Причем, чтобы было, что "код который вызывает foo может ничего не знать об асинхронности".


Result foo(std::istream &client_stream)
{
    string msg;
    do
    {
        getline(client_stream, msg);
        cout << msg << endl; 
    } while(msg != "exit");
    // ...
    return result;
}
Result bar(std::istream &client1, std::istream &client2)
{
    auto result = foo(client1) + foo(client2);
    return result;
}


A>2. Покажи, как это будет выглядеть, если foo принимает не istream&, а, например, адрес или путь к файлу.


Result foo(Address &address)
{
    TcpStream client_stream(address); // or factory, or type template parameter
    string msg;
    // ... same as above
}


EP>>>>На await-те так не получится — в асинхронной версии будет await(+async в объявлении) + по всему call stack'у выше, вплоть до вызова handler'а, точно также будут добавляться await+await.

A>Async не является частью сигнатуры — можешь вызвать как обычную функцию и что-то делать с возвращаемым Task-ом.

Я знаю А ещё можно "просто вызвать" (ничего не делая с Task'ом), если результат не важен.

A>Но таки да, придется возвращать Task<TResult>, вместо TResult, чтобы можно было делать "TResult r = await foo();". А что, на C++ можно вернуть TResult и сделать асинхронщину?


Да, именно так — с помощью stackful coroutines.
Re[37]: Что посоветуете как аналог С++
От: artelk  
Дата: 06.07.13 17:18
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

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


A>>1. Покажи, как это будет выглядеть, если foo возвращает результат? Причем, чтобы было, что "код который вызывает foo может ничего не знать об асинхронности".


EP>
EP>Result foo(std::istream &client_stream)
EP>{
EP>    string msg;
EP>    do
EP>    {
EP>        getline(client_stream, msg);
EP>        cout << msg << endl; 
EP>    } while(msg != "exit");
EP>    // ...
EP>    return result;
EP>}
EP>Result bar(std::istream &client1, std::istream &client2)
EP>{
EP>    auto result = foo(client1) + foo(client2);
EP>    return result;
EP>}
EP>


Т.е. вызывающий поток блокируется до тех пор, пока Result не будет вычислен?

A>>2. Покажи, как это будет выглядеть, если foo принимает не istream&, а, например, адрес или путь к файлу.


EP>
EP>Result foo(Address &address)
EP>{
EP>    TcpStream client_stream(address); // or factory, or type template parameter
EP>    string msg;
EP>    // ... same as above
EP>}
EP>


TcpStream — это какой-то специальный stream, который периодически делает yield?
Re[38]: Что посоветуете как аналог С++
От: Evgeny.Panasyuk Россия  
Дата: 06.07.13 17:41
Оценка:
Здравствуйте, artelk, Вы писали:

A>>>1. Покажи, как это будет выглядеть, если foo возвращает результат? Причем, чтобы было, что "код который вызывает foo может ничего не знать об асинхронности".

EP>>
EP>>Result foo(std::istream &client_stream)
EP>>{
EP>>    string msg;
EP>>    do
EP>>    {
EP>>        getline(client_stream, msg);
EP>>        cout << msg << endl; 
EP>>    } while(msg != "exit");
EP>>    // ...
EP>>    return result;
EP>>}
EP>>Result bar(std::istream &client1, std::istream &client2)
EP>>{
EP>>    auto result = foo(client1) + foo(client2);
EP>>    return result;
EP>>}
EP>>

A>Т.е. вызывающий поток блокируется до тех пор, пока Result не будет вычислен?

По смыслу, это примерно тоже самое, что и:
async Task<Result> bar(istream client1, istream client2)
{
    var result = await foo(client1) + await foo(client2);
    return result;
}

Вызывающий поток(thread) не блокируется, а возвращается к другим задачам, например по event loop.

A>>>2. Покажи, как это будет выглядеть, если foo принимает не istream&, а, например, адрес или путь к файлу.

EP>>
EP>>Result foo(Address &address)
EP>>{
EP>>    TcpStream client_stream(address); // or factory, or type template parameter
EP>>    string msg;
EP>>    // ... same as above
EP>>}
EP>>

A>TcpStream — это какой-то специальный stream, который периодически делает yield?

Да, только не периодически, а по необходимости. Внутри у него что-то типа:
async_read(connection, buffer, /* completion callback: */ [coro]{ coro.resume(); } );
coro.yeild(); // "sleep", will be awakened by completion callback

Причём у него интерфейс как у обычного блокирующего потока, без намёков на асинхронность, поэтому он и совместим с std::istream.
Re[37]: Что посоветуете как аналог С++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.07.13 22:12
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

A>>Но таки да, придется возвращать Task<TResult>, вместо TResult, чтобы можно было делать "TResult r = await foo();". А что, на C++ можно вернуть TResult и сделать асинхронщину?


EP>Да, именно так — с помощью stackful coroutines.


Ну раз так, покажи два способа вызова getline, например один вызвали и ожидаем результата, второй раз вызвали и результата НЕ ожидаем а получаем когда нибудь потом.
Re[38]: Что посоветуете как аналог С++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.07.13 22:13
Оценка: -1 :)
Здравствуйте, artelk, Вы писали:

A>Т.е. вызывающий поток блокируется до тех пор, пока Result не будет вычислен?


Именно так и он это называет асинхронщиной, потому что де в этом потоке будет выполняться какая нибудь другая короутина, которая делает хрен знает что.
Re[39]: Что посоветуете как аналог С++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.07.13 22:16
Оценка: :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>По смыслу, это примерно тоже самое, что и:

EP>
EP>async Task<Result> bar(istream client1, istream client2)
EP>{
EP>    var result = await foo(client1) + await foo(client2);
EP>    return result;
EP>}
EP>

EP>Вызывающий поток(thread) не блокируется, а возвращается к другим задачам, например по event loop.

Для этого надо псать специальный код. А как сделать версию того кода, что не вызвает await ?

EP>Причём у него интерфейс как у обычного блокирующего потока, без намёков на асинхронность, поэтому он и совместим с std::istream.


То есть, его можно использовать ровно одним способом или синхронно или асинхронно. При этом await позволаяет включать ожидание там где тебе надо.
Re[35]: Что посоветуете как аналог С++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 06.07.13 22:16
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>>>
EP>void foo(std::istream &client_stream)
EP>{
EP>    string msg;
EP>    do
EP>    {
EP>        getline(client_stream, msg);
EP>        cout << msg << endl; 
EP>    } while(msg != "exit");
EP>}
EP>

EP>>>То этот код будет работать с любыми потоками — что с синхронными, что с асинхронными, потому что код одинаковый для обоих случаев, так как можно yield спрятать внутри сокета.

EP>Уверен
Автор: Evgeny.Panasyuk
Дата: 21.06.13
.

EP>Да, асинхронный код можно легко сделать синхронным, но как тут уже не раз обсуждалось — getline тут стандартный, изначально ничего не знающий об асинхронности — std::istream тоже самый обычный. Код который вызывает void foo также может ничего не знать об асинхронности — он просто передаёт istream&.

Ты лучше сделай наконец тот пример что я тебя просил. Ну или покажи как один раз вызвать getline с ожиданием а другой раз без ожидания.
Re[38]: Что посоветуете как аналог С++
От: Evgeny.Panasyuk Россия  
Дата: 06.07.13 22:48
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Ну раз так, покажи два способа вызова getline, например один вызвали и ожидаем результата,


уже было

I>второй раз вызвали и результата НЕ ожидаем а получаем когда нибудь потом.


auto future = asynchronous([&]{ getline(client_stream, msg); });
Re[39]: Что посоветуете как аналог С++
От: Evgeny.Panasyuk Россия  
Дата: 06.07.13 22:54
Оценка:
Здравствуйте, Ikemefula, Вы писали:

A>>Т.е. вызывающий поток блокируется до тех пор, пока Result не будет вычислен?

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

Так ты определись — либо блокируется, либо "в этом потоке"

I>которая делает хрен знает что.


цирк. async download
Автор: Ikemefula
Дата: 20.06.13

"во время download, будет выполняться какая-нибудь обработка UI события, которая делает хрен знает что"
Re[40]: Что посоветуете как аналог С++
От: Evgeny.Panasyuk Россия  
Дата: 06.07.13 23:05
Оценка:
Здравствуйте, Ikemefula, Вы писали:

EP>>По смыслу, это примерно тоже самое, что и:

EP>>
EP>>async Task<Result> bar(istream client1, istream client2)
EP>>{
EP>>    var result = await foo(client1) + await foo(client2);
EP>>    return result;
EP>>}
EP>>

EP>>Вызывающий поток(thread) не блокируется, а возвращается к другим задачам, например по event loop.
I>Для этого надо псать специальный код.

Этот код пишется один раз, и едет библиотеку, при этом ни каркас приложения, ни event loop — не меняются.

I>То есть, его можно использовать ровно одним способом или синхронно или асинхронно.


О, уже прогресс!

I>При этом await позволаяет включать ожидание там где тебе надо.


Так и тут при необходимости можно явно указать где не нужно ожидание
Re[36]: Что посоветуете как аналог С++
От: Evgeny.Panasyuk Россия  
Дата: 06.07.13 23:09
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Ты лучше сделай наконец тот пример что я тебя просил.


какой? тут уже было достаточно ликбез-примеров

I>Ну или покажи как один раз вызвать getline с ожиданием а другой раз без ожидания.


см выше.
Re[37]: Что посоветуете как аналог С++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 07.07.13 07:40
Оценка: -1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

I>>Ты лучше сделай наконец тот пример что я тебя просил.


EP>какой? тут уже было достаточно ликбез-примеров


Понятно, аргументы закончились

I>>Ну или покажи как один раз вызвать getline с ожиданием а другой раз без ожидания.


EP>см выше.


Ты не показал имеенно тот случай, где асинхронщины просто не избежать, то есть, вообще.
Re[41]: Что посоветуете как аналог С++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 07.07.13 07:43
Оценка: -1 :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>>>Вызывающий поток(thread) не блокируется, а возвращается к другим задачам, например по event loop.

I>>Для этого надо псать специальный код.

EP>Этот код пишется один раз, и едет библиотеку, при этом ни каркас приложения, ни event loop — не меняются.


Ну это просто вранье. alex_public показал, как event-loop "не меняется" — путем встраивания RunAll в event loop или прикручивая таймер


I>>При этом await позволаяет включать ожидание там где тебе надо.


EP>Так и тут при необходимости можно явно указать где не нужно ожидание


Продемонстрируй свой getline один раз с ожиданием, другой раз без ожидания. Надеюсь, ты не станешь эмулировать await путем параметризации gitline специальным потоком ?
Re[40]: Что посоветуете как аналог С++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 07.07.13 07:57
Оценка: -1 :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

A>>>Т.е. вызывающий поток блокируется до тех пор, пока Result не будет вычислен?

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

EP>Так ты определись — либо блокируется, либо "в этом потоке"


UI поток заблокируется, потому что буст не знает про message pump. В этом потоке будет чтото выполняться, при чем не ясно, как указать что именно должно выполняться.


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

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

http://rsdn.ru/forum/philosophy/5215721.1
Автор: Ikemefula
Дата: 30.06.13
Re[39]: Что посоветуете как аналог С++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 07.07.13 08:05
Оценка: :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

I>>второй раз вызвали и результата НЕ ожидаем а получаем когда нибудь потом.


EP>
EP>auto future = asynchronous([&]{ getline(client_stream, msg); });
EP>


А ведь кторо говорил что никакие уши асинхронщины нигде не торчат Похоже, у вас с vdimas стало модно брать свои слова назад.

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

string s = ::ReadFileAsUrl("someConfigPath")


То внезапно оказывается так, что асинхронщина пролезет даже в сигнатуру. Ну или как вариант, придется указывать наличие/отсутствие ожидания с помощью глобальных переменных

Остался один открытый вопрос — сделать так, что бы буст, наконец, узнал про message pump.
Re[41]: Что посоветуете как аналог С++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 07.07.13 08:20
Оценка: :)
Здравствуйте, Ikemefula, Вы писали:

EP>>Так ты определись — либо блокируется, либо "в этом потоке"


I>UI поток заблокируется, потому что буст не знает про message pump. В этом потоке будет чтото выполняться, при чем не ясно, как указать что именно должно выполняться.


Например пока UI поток блокирован, ни один из потоков не сможет внятно обратиться к этому потоку, потому что все синхронные вызовы замерзнут. То есть, снаружи потока не будет способа отличить блокированый UI поток от потока который надолго завис в короутинах.
Re[38]: Что посоветуете как аналог С++
От: Evgeny.Panasyuk Россия  
Дата: 07.07.13 09:05
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>>>Ты лучше сделай наконец тот пример что я тебя просил.

EP>>какой? тут уже было достаточно ликбез-примеров
I>Понятно, аргументы закончились

алле, какой пример?

EP>>>>Вызывающий поток(thread) не блокируется, а возвращается к другим задачам, например по event loop.

I>>>Для этого надо псать специальный код.
EP>>Этот код пишется один раз, и едет библиотеку, при этом ни каркас приложения, ни event loop — не меняются.
I>Ну это просто вранье. alex_public показал, как event-loop "не меняется" — путем встраивания RunAll в event loop или прикручивая таймер

Так я же выше показывал пример с полностью локальной трансформацией, без модификации event-loop

I>>>При этом await позволаяет включать ожидание там где тебе надо.

EP>>Так и тут при необходимости можно явно указать где не нужно ожидание
I>Продемонстрируй свой getline один раз с ожиданием, другой раз без ожидания. Надеюсь, ты не станешь эмулировать await путем параметризации gitline специальным потоком ?

Выше есть оба примера

A>>>>Т.е. вызывающий поток блокируется до тех пор, пока Result не будет вычислен?

I>>>Именно так и он это называет асинхронщиной, потому что де в этом потоке будет выполняться какая нибудь другая короутина,
EP>>Так ты определись — либо блокируется, либо "в этом потоке"
I>UI поток заблокируется, потому что буст не знает про message pump.

Так он и не должен ничего знать про message pump. Я же выше показывал пример

I>В этом потоке будет чтото выполняться, при чем не ясно, как указать что именно должно выполняться.


У асинхронных операций есть callback'и принимающие продолжения, вот в этот callback и нырнёт наша корутина — event loop это никак не трогает — всё полностью локально

I>Представь себе либу, которая ничего про твои короутины не знает. У ней ровно один метод, как водится, блокирующий, это именно то ради чего нужна асинхронщина:

I>http://rsdn.ru/forum/philosophy/5215721.1
Автор: Ikemefula
Дата: 30.06.13


То есть по твоему "асинхронщина" — это только выполнение в отдельном потоке?
Ничто не мешает закинуть post_event с unyield'ом корутины в конец нового потока Уже надоело объяснять банальные вещи
Re[40]: Что посоветуете как аналог С++
От: Evgeny.Panasyuk Россия  
Дата: 07.07.13 09:31
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Остался один открытый вопрос — сделать так, что бы буст, наконец, узнал про message pump.


ты действительно не понял, что трансформация полностью локальная?

EP>>>Так ты определись — либо блокируется, либо "в этом потоке"

I>>UI поток заблокируется, потому что буст не знает про message pump. В этом потоке будет чтото выполняться, при чем не ясно, как указать что именно должно выполняться.

Тебе что-то неясно != "UI поток заблокируется"

I>Например пока UI поток блокирован, ни один из потоков не сможет внятно обратиться к этому потоку, потому что все синхронные вызовы замерзнут. То есть, снаружи потока не будет способа отличить блокированый UI поток от потока который надолго завис в короутинах.


Почему завис на корутинах? Ты о чём?
Если в случае C# долгие операции будут выполнятся в отдельном потоке, и ожидаться по await:
await Task.Factory.StartNew(() => DoAction());

То и на stackful coroutines никто не заставляет всё пилить в одном потоке:
async([]{ DoAction(); }).then([=]
{
    synchronization_context_post( [=]{ coro.un_yield(); } );
}); // without syntax sugar
coro.yield();

Неважно где будет выполнятся асинхронная операция — в отдельном потоке или позже в этом, главное чтобы была возможность присоединить продолжение в виде:
synchronization_context_post( [=]{ coro.un_yield(); } );
Re[41]: Что посоветуете как аналог С++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 07.07.13 10:17
Оценка: -1 :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

I>>Остался один открытый вопрос — сделать так, что бы буст, наконец, узнал про message pump.


EP>ты действительно не понял, что трансформация полностью локальная?


Я утверждаю, что ты показал эмуляцию асинхронщины, а не саму асинхронщину, то есть, синхъронный код с нелокальные переходами.

I>>>UI поток заблокируется, потому что буст не знает про message pump. В этом потоке будет чтото выполняться, при чем не ясно, как указать что именно должно выполняться.


EP>Тебе что-то неясно != "UI поток заблокируется"


Покажи каким образом буст узнает про message pump.

EP>Почему завис на корутинах? Ты о чём?


Очень просто. твой пример с getline именно это и демонстрирует. Если ты делаешь вызов с ожиданием, то надо РУКАМИ пнуть message pump. В С# это делает компилятор.

Если ты не согласен, напиши внятно, почему это не надо делать.

EP>То и на stackful coroutines никто не заставляет всё пилить в одном потоке:

EP>
EP>async([]{ DoAction(); }).then([=]
EP>{
EP>    synchronization_context_post( [=]{ coro.un_yield(); } );
EP>}); // without syntax sugar
EP>coro.yield();
EP>


И снова торчит та самая асинхронщина, которая, как ты утверждал, нигде не торчит ?

EP>Неважно где будет выполнятся асинхронная операция — в отдельном потоке или позже в этом, главное чтобы была возможность присоединить продолжение в виде:

EP>
EP>synchronization_context_post( [=]{ coro.un_yield(); } );
EP>


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

Итого — одним сообщением ты взял все свои слова назад

В сухом остатке, так сказать, все по прежнему — все что надо, в С++ пилится и контролируется руками, в сигнатуре и коде торчит ровно то же, что торчит в C#.
Re[39]: Что посоветуете как аналог С++
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 07.07.13 10:24
Оценка: -2 :))
Здравствуйте, Evgeny.Panasyuk, Вы писали:

I>>Понятно, аргументы закончились


EP>алле, какой пример?


Да все тот же, где Sleep используется.

I>>Ну это просто вранье. alex_public показал, как event-loop "не меняется" — путем встраивания RunAll в event loop или прикручивая таймер


EP>Так я же выше показывал пример с полностью локальной трансформацией, без модификации event-loop


Тот где торчит asynchronous или тот где getline ? Если getline сам по себе, то он блокирует message pump и что бы это пофиксить, нужно научить буст запускать message pump.

I>>UI поток заблокируется, потому что буст не знает про message pump.


EP>Так он и не должен ничего знать про message pump. Я же выше показывал пример


Да, я в курсе, asynchronous.

EP>У асинхронных операций есть callback'и принимающие продолжения, вот в этот callback и нырнёт наша корутина — event loop это никак не трогает — всё полностью локально


То есть, вместо линейного кода на ровном месте получаются continuations

EP>То есть по твоему "асинхронщина" — это только выполнение в отдельном потоке?


Асинхронщина это обращение к некоторой сущности, у которой время отличное от времени центрального процессора. Все что ты показывал, это просто другая форма эвентов, т.е. все выполняется в одном процессоре а стало быть асинхронщины нет и быть не может, только эмуляция.
То есть, синхронный код с нелькальными переходами.

EP>Ничто не мешает закинуть post_event с unyield'ом корутины в конец нового потока Уже надоело объяснять банальные вещи


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