Re[10]: Facebook и язык D - первый шаг наверх.
От: alex_public  
Дата: 06.11.13 00:39
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Перечитал, но так и не увидел полный код. Не было его тогда, нет и сейчас.


Ооо, замечательно. Ну тогда покажи чем этот код (твой)
private async void handler(object sender, TaskArgs args)
{
    var client = new HttpClient();
    var response = await client.GetAsync(args.Url, args.Cancellation);
    response.EnsureSuccessStatusCode();
    textBox.Text +=  await response.Content.ReadAsStringAsync();
}

лучше чем этот код (мой):
void handler(object& sender, TaskArgs& args) async_code
(
    HttpClient client;
    auto response=await_async(client.Get(args.Url, args.Cancellation));
    response.EnsureSuccessStatusCode();
    textBox.Text+=await_async(response.Content.ReadAsString());
)


Лично я вижу небольшие отличия, но как раз в пользу C++ варианта:
1. Не требуется заводить специальный асинхронный аналог для каждой библиотечной функции — достаточно наличия синхронного.
2. Можно написать например такой код:
void Handler(const list<string>& urls)
{
    for(auto url: urls)  async_code
    (
        result+=await_async([&]{return CheckServer(url);});
    )
}

который запустит параллельное выполнение CheckServer для каждого элемента в списке и соберёт все результаты в переменной result.


G>То что там писали про async в бусте, то это не более, чем аналог yield в C#. До полноценного async, как в C# ему очень далеко. Теоретически можно сделать, но начинаются проблемы с детерминированным освобождением памяти.


Для начала в Boost'e нет никаких async. Там есть только Coroutine, причём с реализацией намного более сильной, чем в .net. А уже на базе этого любой async и т.п. делается за пару минут. Причём эта реализация за пару минут оказывается ещё и с большими возможностями (см. пункт2 выше), чем async/await из .net.

На всякий случай приведу ещё раз один из примеров реализации await/async под код выше:
  Скрытый текст
using __Coro=boost::coroutines::coroutine<void()>;
void Post2UI(const void* coro);
template<typename L> auto __await_async(const __Coro* coro, __Coro::caller_type& yield, L lambda)->decltype(lambda())
{
    auto f=async(launch::async, [=](){
        auto r=lambda();
        Post2UI(coro);
        return r;
    });
    yield();
    return f.get();
}
void CallFromUI(void* c)
{
    __Coro* coro=static_cast<__Coro*>(c);
    (*coro)();
    if(!*coro) delete coro;
}
#define async_code(block) { __Coro* __coro=new __Coro; *__coro=__Coro([=](__Coro::caller_type& __yield){block});}
#define await_async(l) __await_async(__coro, __yield, l)


P.S. Самое забавное, что эта темка форума вроде как про язык D, который в этом смысле заметно сильнее и C++, не говоря уже о C#...
Re[11]: Facebook и язык D - первый шаг наверх.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.11.13 11:24
Оценка:
Здравствуйте, alex_public, Вы писали:

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


G>>Перечитал, но так и не увидел полный код. Не было его тогда, нет и сейчас.


_>Ооо, замечательно. Ну тогда покажи чем этот код (твой)

_>
_>private async void handler(object sender, TaskArgs args)
_>{
_>    var client = new HttpClient();
_>    var response = await client.GetAsync(args.Url, args.Cancellation);
_>    response.EnsureSuccessStatusCode();
_>    textBox.Text +=  await response.Content.ReadAsStringAsync();
_>}
_>

_>лучше чем этот код (мой):
_>
_>void handler(object& sender, TaskArgs& args) async_code
_>(
_>    HttpClient client;
_>    auto response=await_async(client.Get(args.Url, args.Cancellation));
_>    response.EnsureSuccessStatusCode();
_>    textBox.Text+=await_async(response.Content.ReadAsString());
_>)
_>



Тем что на C# это весь код. Он работает когда больше нет ни одной строки. А на C++ нужно еще исполнять танцы с бубном бустом.

_>Лично я вижу небольшие отличия, но как раз в пользу C++ варианта:

_>1. Не требуется заводить специальный асинхронный аналог для каждой библиотечной функции — достаточно наличия синхронного.
_>2. Можно написать например такой код:
_>
_>void Handler(const list<string>& urls)
_>{
_>    for(auto url: urls)  async_code
_>    (
_>        result+=await_async([&]{return CheckServer(url);});
_>    )
_>}
_>

_>который запустит параллельное выполнение CheckServer для каждого элемента в списке и соберёт все результаты в переменной result.

async_code это что?
Re[12]: Facebook и язык D - первый шаг наверх.
От: alex_public  
Дата: 06.11.13 12:07
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Тем что на C# это весь код. Он работает когда больше нет ни одной строки. А на C++ нужно еще исполнять танцы с бубном бустом.


Агаа... Т.е. чтобы сравнивать C# и C++ надо последнему запретить использовать сторонние библиотеки... Я приблизительно так и думал.

G>async_code это что?


Это макрос. Его определение было в моём сообщение (скрытый текст).
Re[13]: Facebook и язык D - первый шаг наверх.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.11.13 12:16
Оценка: :)
Здравствуйте, alex_public, Вы писали:

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


G>>Тем что на C# это весь код. Он работает когда больше нет ни одной строки. А на C++ нужно еще исполнять танцы с бубном бустом.


_>Агаа... Т.е. чтобы сравнивать C# и C++ надо последнему запретить использовать сторонние библиотеки... Я приблизительно так и думал.


А я разве говорил что надо запретить? Я лишь говорил что требуются дополнительные танцы, даже если в виде макросов (фу!). Как обычно макросы могут очень неоднозначно интерферировать с остальным кодом, а неудачно написанный\вставленный макрос может дать такую ошибку, что её сходу не найдешь. Про типизацию вообще говорить не буду. Не зря макросы считаются не рекомендуемым способом.

G>>async_code это что?


_>Это макрос. Его определение было в моём сообщение (скрытый текст).


Дык функция Post2UI как работает? Там за ней еще десятки строк и несколько макросов?
Re[14]: Facebook и язык D - первый шаг наверх.
От: alex_public  
Дата: 06.11.13 14:26
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>А я разве говорил что надо запретить? Я лишь говорил что требуются дополнительные танцы, даже если в виде макросов (фу!).


И в чём проблема, если это пишется один раз? Можно даже в библиотечку (из одного заголовочного файла) оформить, хотя это смешно при таких размерах.

G>Как обычно макросы могут очень неоднозначно интерферировать с остальным кодом, а неудачно написанный\вставленный макрос может дать такую ошибку, что её сходу не найдешь.


Не путай с шаблонами. У макросов как раз вполне краткие и однозначные сообщения об ошибках.

G>Про типизацию вообще говорить не буду. Не зря макросы считаются не рекомендуемым способом.


И снова путаешь. Макросы не рекомендуются там, где их использование является альтернативой какой-то конструкции языка. Например определение различных констант макросами довольно распространено и как раз это плохой стиль, т.к. есть enum'ы. А здесь макрос применяется только для своей изначальной цели — метапрограммирования, которое по другому никак не записывается. Т.е. все типизации здесь стандартные, а макрос используется для манипуляций блоками кода. Тут никаких странных ошибок не будет и никаких антирекомендаций нет.

G>Дык функция Post2UI как работает? Там за ней еще десятки строк и несколько макросов?


Не, это обычная функция в одну строчку. Просто она зависит от используемой приложением схемы управления сообщениями и поэтому должна определяться конкретным приложением. Например, если мы говорим об обычном win32 приложение с очередью сообщений, то реализация может выглядеть так:
void Post2UI(const void* coro) {PostMessage(coro);}
void OnAsync(Event& event) {CallFromUI(event.Get<void*>());}


Однако может быть и совсем другая реализация, например в приложение вообще без очереди сообщений или с вызовами продолжений внутри кусков нашего кода. И кстати это ещё одно заметное преимущество над реализацией .net'а, в которой одна схема зашита намертво.
Re[15]: Facebook и язык D - первый шаг наверх.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.11.13 21:09
Оценка:
Здравствуйте, alex_public, Вы писали:

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


G>>А я разве говорил что надо запретить? Я лишь говорил что требуются дополнительные танцы, даже если в виде макросов (фу!).


_>И в чём проблема, если это пишется один раз? Можно даже в библиотечку (из одного заголовочного файла) оформить, хотя это смешно при таких размерах.

Проблема в том что такой код тяжело поддерживать. Сегодня у вас все маршалится в UI поток, завтра в отдельный поток, послезавтра вы используете IOCP, который потом маршлит в UI.
Библиотечку оформить это примерно х10 затраты по сравнению с просто написать, и х3 с учетом поддержки.



G>>Как обычно макросы могут очень неоднозначно интерферировать с остальным кодом, а неудачно написанный\вставленный макрос может дать такую ошибку, что её сходу не найдешь.

_>Не путай с шаблонами. У макросов как раз вполне краткие и однозначные сообщения об ошибках.
Видел эти "однозначные сообщения", спасибо, хватило.


G>>Дык функция Post2UI как работает? Там за ней еще десятки строк и несколько макросов?


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

_>
_>void Post2UI(const void* coro) {PostMessage(coro);}
_>void OnAsync(Event& event) {CallFromUI(event.Get<void*>());}
_>


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

_>Однако может быть и совсем другая реализация, например в приложение вообще без очереди сообщений или с вызовами продолжений внутри кусков нашего кода. И кстати это ещё одно заметное преимущество над реализацией .net'а, в которой одна схема зашита намертво.


Чувак, ты слишком плохо разбираешься в .NET чтобы подобные утверждения делать. Посмотри на channel9 как устроен async и таски. Много нового для себя откроешь.
Re[16]: Facebook и язык D - первый шаг наверх.
От: alex_public  
Дата: 07.11.13 01:12
Оценка: +2 -1
Здравствуйте, gandjustas, Вы писали:

G>Проблема в том что такой код тяжело поддерживать. Сегодня у вас все маршалится в UI поток, завтра в отдельный поток, послезавтра вы используете IOCP, который потом маршлит в UI.

G>Библиотечку оформить это примерно х10 затраты по сравнению с просто написать, и х3 с учетом поддержки.

Ооо, этот классический подход в стиле Java/C#, когда мы заранее наворачиваем горы никчемных интерфейсов и классов... Нет, такого нам не надо. )))

G>Ту то есть разбор очереди задач надо руками делать, плачевно... Переключить с UI на пул потоков так просто не выйдет, особенно с точки зрения вызывающего кода.


Применение await/async вне возврата управления в ui поток не имеет вообще никакого смысла. Только лишние накладные расходы и никакой пользы.

G>Чувак, ты слишком плохо разбираешься в .NET чтобы подобные утверждения делать. Посмотри на channel9 как устроен async и таски. Много нового для себя откроешь.


Ну да, конечно. Только вот я выложил уже несколько примеров кода, а от тебя пока не видно ни одного — одна пафосная болтовня. Раз ты считаешь, что я недооцениваю возможности async в .net, то предлагаю тебе показать тут реализацию на C# следующей простейшей задачки:

Предположим, что у нас есть некая сложная библиотечная функция, причём написанная не нами, т.е. переписать её самим вообще не вариант. Изначально она рассчитана только на синхронную работу — читает (многократно) данные из некого блокирующего потока ввода и сама обязательно должна исполняться только в ui потоке. Т.е. синхронный код выглядит так:
ComplexFunction(input_stream);//блокирует исполнение ui потока, пока не обработает все входные данные.

Соответственно задача в том, чтобы сделать этот код асинхронным. На C++ это можно решить тривиально:
async_code(
    ComplexFunction(async_stream(input_stream));
)

Этот код вернёт управление сразу же и при этом ComplexFunction будет периодически (по мере поступления данных) отрабатывать в ui потоке. Функцию ComplexFunction мы естественно вообще не трогали.

А как решить эту задачку на C# с его крутыми "async и тасками"?
Re[17]: Facebook и язык D - первый шаг наверх.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.11.13 08:52
Оценка:
Здравствуйте, alex_public, Вы писали:

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


G>>Проблема в том что такой код тяжело поддерживать. Сегодня у вас все маршалится в UI поток, завтра в отдельный поток, послезавтра вы используете IOCP, который потом маршлит в UI.

G>>Библиотечку оформить это примерно х10 затраты по сравнению с просто написать, и х3 с учетом поддержки.

_>Ооо, этот классический подход в стиле Java/C#, когда мы заранее наворачиваем горы никчемных интерфейсов и классов... Нет, такого нам не надо. )))


В .NET это уже все есть, а Java скорее всего тоже, а в C++ надо таки писать.

G>>Ту то есть разбор очереди задач надо руками делать, плачевно... Переключить с UI на пул потоков так просто не выйдет, особенно с точки зрения вызывающего кода.

_>Применение await/async вне возврата управления в ui поток не имеет вообще никакого смысла. Только лишние накладные расходы и никакой пользы.
В С++ наверное не имеет смысла, а в .NET:
а) накладных расходов на async\await для синхронных вызовов нет
б) повсеместно используется асинхронный IO, который еще и масштабируемость улучшает.



G>>Чувак, ты слишком плохо разбираешься в .NET чтобы подобные утверждения делать. Посмотри на channel9 как устроен async и таски. Много нового для себя откроешь.


_>Ну да, конечно. Только вот я выложил уже несколько примеров кода, а от тебя пока не видно ни одного — одна пафосная болтовня. Раз ты считаешь, что я недооцениваю возможности async в .net, то предлагаю тебе показать тут реализацию на C# следующей простейшей задачки:


_>Предположим, что у нас есть некая сложная библиотечная функция, причём написанная не нами, т.е. переписать её самим вообще не вариант. Изначально она рассчитана только на синхронную работу — читает (многократно) данные из некого блокирующего потока ввода и сама обязательно должна исполняться только в ui потоке. Т.е. синхронный код выглядит так:

_>
_>ComplexFunction(input_stream);//блокирует исполнение ui потока, пока не обработает все входные данные.
_>

_>Соответственно задача в том, чтобы сделать этот код асинхронным. На C++ это можно решить тривиально:
_>
_>async_code(
_>    ComplexFunction(async_stream(input_stream));
_>)
_>

_>Этот код вернёт управление сразу же и при этом ComplexFunction будет периодически (по мере поступления данных) отрабатывать в ui потоке. Функцию ComplexFunction мы естественно вообще не трогали.

_>А как решить эту задачку на C# с его крутыми "async и тасками"?



await Dispatcher.RunTask(() => ComplexFunction(input_stream))


Я же говорю, ты слишком плохо .NET знаешь.
Но это слишком примитивный способ использования async\await. Ты вот лучше расскажи как из из одного async метода вызвать другой, чтобы они корректно построились в цепочку асинхронных вызовов.

ЗЫ. Обычно "знатоки", которые пытаются доказать что .NET что-то не умеет нихрена в нем не понимают
Re[18]: Facebook и язык D - первый шаг наверх.
От: alex_public  
Дата: 07.11.13 11:55
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>
G>await Dispatcher.RunTask(() => ComplexFunction(input_stream))
G>


Это не то, это обычная синхронная работа ComplexFunction (блокирующая ui на время ожидания прихода всех данных), только отложенная на потом. В этом никакого особого смысла нет. А нам надо чтобы ComplexFunction отдавал управление, когда во входном потоке нет данных. Как видно на C++ это делается очень просто...

G>Я же говорю, ты слишком плохо .NET знаешь.


Ага, ага. Только пока что глядя на тебя видно много понтов, а когда доходит до дела, то только пшик.
Re[19]: Facebook и язык D - первый шаг наверх.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 07.11.13 12:11
Оценка: :))
Здравствуйте, alex_public, Вы писали:

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


G>>
G>>await Dispatcher.RunTask(() => ComplexFunction(input_stream))
G>>


_>Это не то, это обычная синхронная работа ComplexFunction (блокирующая ui на время ожидания прихода всех данных), только отложенная на потом. В этом никакого особого смысла нет. А нам надо чтобы ComplexFunction отдавал управление, когда во входном потоке нет данных. Как видно на C++ это делается очень просто...


Пффф... ну напиши так
await Dispatcher.RunTask(async () => ComplexFunction(await input_stream));


Только я тебя попрошу показать реализацию async_stream(input_stream) и ты опять напишешь 30 и более строк ада с макросами и бустом, а в .NET, с вероятностью 95%, уже есть готовый класс, который решит твою задачу.


G>>Я же говорю, ты слишком плохо .NET знаешь.

_>Ага, ага. Только пока что глядя на тебя видно много понтов, а когда доходит до дела, то только пшик.
Какого дела? Ты выососал из пальца какую-то хрень. В реальной програмее ComplexFunction тупо перепишут, потыкав везде await и она станет идеально асинхронной и будет сама маршалить вызовы в UI если надо.

Я же говорю, твое понимание .NET на уровне плинтуса. Ты можешь миллион таких пшиков нагенерить, и все они будут бесконечно далеки от реальной жизни.
Re[20]: Facebook и язык D - первый шаг наверх.
От: alex_public  
Дата: 07.11.13 13:58
Оценка: -1
Здравствуйте, gandjustas, Вы писали:

G>Пффф... ну напиши так

G>
G>await Dispatcher.RunTask(async () => ComplexFunction(await input_stream));

Гыгы, и снова не то. Здесь тоже самое что и в предыдущем варианте, только блокирующий ComplexFunction запустится после прихода первой порции данных.

G>Только я тебя попрошу показать реализацию async_stream(input_stream) и ты опять напишешь 30 и более строк ада с макросами и бустом, а в .NET, с вероятностью 95%, уже есть готовый класс, который решит твою задачу.


Хы, это же просто асинхронная обёртка под конкретный поток. Т.е. это класс, реализущий интерфейс InputStream и при этом пересылающий все вызовы к имеющейся у него ссылке на реальный поток ввода. Точнее все функции пересылаются напрямую, а одна главная (типа ReadBuf, которую многократно вызывает ComplexFunction) через асинхронный вызов (через await_async как в коде выше) той же функции реального синхронного потока.

G>Какого дела? Ты выососал из пальца какую-то хрень. В реальной програмее ComplexFunction тупо перепишут, потыкав везде await и она станет идеально асинхронной и будет сама маршалить вызовы в UI если надо.


G>Я же говорю, твое понимание .NET на уровне плинтуса. Ты можешь миллион таких пшиков нагенерить, и все они будут бесконечно далеки от реальной жизни.


Воот, до тебя наконец то начала доходить ситуация, хотя признавать это ты конечно же не хочешь. .Net не позволяет нам использовать готовые синхронные функции (которых миллиарды в различных библиотеках) в асинхронном коде, а заставляет нас переписывать их заново. В отличие от C++, где мы можем получить "идеально асинхронную" функцию из синхронной не трогая её код. Но конечно, если ты не видишь в невозможности использовать старые рабочие функции никакого недостатка, то тут уже ситуация безнадёжная...
Re[17]: Facebook и язык D - первый шаг наверх.
От: artelk  
Дата: 07.11.13 16:52
Оценка:
Здравствуйте, alex_public, Вы писали:

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


G>>Ту то есть разбор очереди задач надо руками делать, плачевно... Переключить с UI на пул потоков так просто не выйдет, особенно с точки зрения вызывающего кода.

_>Применение await/async вне возврата управления в ui поток не имеет вообще никакого смысла. Только лишние накладные расходы и никакой пользы.

Хотелось бы увидеть обоснование этому утверждению.
Re[21]: Facebook и язык D - первый шаг наверх.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 08.11.13 06:40
Оценка:
Здравствуйте, alex_public, Вы писали:

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


G>>Пффф... ну напиши так

G>>
G>>await Dispatcher.RunTask(async () => ComplexFunction(await input_stream));
_>

_>Гыгы, и снова не то. Здесь тоже самое что и в предыдущем варианте, только блокирующий ComplexFunction запустится после прихода первой порции данных.
Покажи как внтури работает твой ComplexFunction, async_code и async_stream. Желательно компилируемый пример, я напишу такой же на C# в 3 раза короче.

G>>Только я тебя попрошу показать реализацию async_stream(input_stream) и ты опять напишешь 30 и более строк ада с макросами и бустом, а в .NET, с вероятностью 95%, уже есть готовый класс, который решит твою задачу.


_>Хы, это же просто асинхронная обёртка под конкретный поток. Т.е. это класс, реализущий интерфейс InputStream и при этом пересылающий все вызовы к имеющейся у него ссылке на реальный поток ввода. Точнее все функции пересылаются напрямую, а одна главная (типа ReadBuf, которую многократно вызывает ComplexFunction) через асинхронный вызов (через await_async как в коде выше) той же функции реального синхронного потока.

Код покажи.

G>>Какого дела? Ты выососал из пальца какую-то хрень. В реальной програмее ComplexFunction тупо перепишут, потыкав везде await и она станет идеально асинхронной и будет сама маршалить вызовы в UI если надо.


G>>Я же говорю, твое понимание .NET на уровне плинтуса. Ты можешь миллион таких пшиков нагенерить, и все они будут бесконечно далеки от реальной жизни.


_>Воот, до тебя наконец то начала доходить ситуация, хотя признавать это ты конечно же не хочешь. .Net не позволяет нам использовать готовые синхронные функции (которых миллиарды в различных библиотеках) в асинхронном коде, а заставляет нас переписывать их заново. В отличие от C++, где мы можем получить "идеально асинхронную" функцию из синхронной не трогая её код. Но конечно, если ты не видишь в невозможности использовать старые рабочие функции никакого недостатка, то тут уже ситуация безнадёжная...

ОК, покажи компилируемый пример. Я чето не верю что ты его сможешь написать.
Re[17]: Facebook и язык D - первый шаг наверх.
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 08.11.13 11:56
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Применение await/async вне возврата управления в ui поток не имеет вообще никакого смысла. Только лишние накладные расходы и никакой пользы.


Чудеса да и только. UI поток это частный случай потока с эвенлупом. Сейчас чуть более чем все приложения сложнее helloworld используют эти эвентлупы.

Асинхронщина сама по себе не нужна. Она нужна там, где работа с внешней системой где другое время. Без малого, весь сихронный ввод-вывод делается одинаково — шлется запрос и потом ожидание до окончания.
Re[21]: Facebook и язык D - первый шаг наверх.
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 08.11.13 12:17
Оценка: :)
Здравствуйте, alex_public, Вы писали:

_>Воот, до тебя наконец то начала доходить ситуация, хотя признавать это ты конечно же не хочешь. .Net не позволяет нам использовать готовые синхронные функции (которых миллиарды в различных библиотеках) в асинхронном коде, а заставляет нас переписывать их заново. В отличие от C++, где мы можем получить "идеально асинхронную" функцию из синхронной не трогая её код. Но конечно, если ты не видишь в невозможности использовать старые рабочие функции никакого недостатка, то тут уже ситуация безнадёжная...


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

function(){
                    var value = read();
                    write(next(value));
                }


Вот функция, у ней в синхронном коде простой инвариант, проще не придумаешь. Проблема следующая — когда read или write становится асинхронным, между read и write может произойти нарушение инварианта. Вот из за этого и нужно переписывать код самой функции. Что характерно, в С++ ровно то же самое.

Итого — если ты решительно не согласен — покажи эту секретную технику " можем получить "идеально асинхронную" функцию из синхронной не трогая её код" что бы показаный инвариант сохранился.
Re[22]: Facebook и язык D - первый шаг наверх.
От: alex_public  
Дата: 09.11.13 14:46
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Покажи как внтури работает твой ComplexFunction, async_code и async_stream. Желательно компилируемый пример, я напишу такой же на C# в 3 раза короче.


O, отлично. Только теперь смотри, не забудь в это раз о своём обещание. Я то тебя за язык не тянул...

Кстати, мне нравится какое развитие получила наша дискуссия. Последние несколько сообщений ты пытаешься (естественно безуспешно) доказать, что реализация async/await в C# не хуже чем один из вариантов (мой) реализации async/await на C++. Это выглядит весьма забавно с учётом того, что сама дискуссия началась с твоего выкрика "попробуйте сделать подобное на C++". )))

Ну да ладно, перейдём к коду:

1. Синхронный библиотечный код.
  Скрытый текст
class OutputStream;//Реализация не важна. Выводит данные+отладочную информацию в некое окно (т.е. только для ui потока)
class InputStream{//Тестовый блокирующий поток ввода. Можно вызывать из любого потока.
public:
    virtual InputStream& operator>>(vector<int>& buf)
    {
        this_thread::sleep_for(chrono::seconds(1));
        static int d=0;
        for(auto& b: buf) b=d++;
        return *this;
    }
};
void ComplexFunction(InputStream& input, OutputStream& output)//Тестовая синхронная функция. Только для ui потока.
{
    vector<int> buf(16);
    do{
        input>>buf;
        output<<buf<<nl;
    }while(buf.back()<100);
}

2. Его обычное использование.
Такой код (часть класса приложения):
  Скрытый текст
void OnTest()
{
    output<<L"Вход в OnTest"<<nl;
    auto input=InputStream();
    ComplexFunction(input, output);
    output<<L"Выход из OnTest"<<nl;
}
void OnTimer()
{
    output<<L"Таймер!"<<nl;
}
будет выдавать в окно такой результат:
  Скрытый текст
18:39:43 из потока 1. Таймер!
18:39:44 из потока 1. Таймер!
18:39:44 из потока 1. Вход в OnTest
18:39:45 из потока 1. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
18:39:47 из потока 1. 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 
18:39:48 из потока 1. 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 
18:39:49 из потока 1. 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 
18:39:50 из потока 1. 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 
18:39:51 из потока 1. 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 
18:39:52 из потока 1. 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 
18:39:52 из потока 1. Выход из OnTest
18:39:52 из потока 1. Таймер!
18:39:53 из потока 1. Таймер!


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

3. Реализация асинхронности.
Берём мой вариант реализации await/async (скрытый текст здесь http://www.rsdn.ru/forum/philosophy/5353890
Автор: alex_public
Дата: 06.11.13
) и добавляем реализацию асинхронного потока вокруг данного библиотечного:
  Скрытый текст
#define AsyncInputStream(s) __AsyncInputStream(s, __yield, __coro)
class __AsyncInputStream: public InputStream{
    InputStream& syn_stream;
    __Coro::caller_type& __yield;
    __Coro* __coro;
public:
    __AsyncInputStream(InputStream& s, __Coro::caller_type& y, __Coro* c): syn_stream(s), __yield(y), __coro(c){}
    InputStream& operator>>(vector<int>& buf) override {await_async([&]{syn_stream>>buf; return *this;});}
};

4. Использование асинхронного варианта.
Такой код (часть класса приложения):
  Скрытый текст
void OnTest() async_code
(
    output<<L"Вход в OnTest"<<nl;
    auto input=InputStream();
    auto async_input=AsyncInputStream(input);
    ComplexFunction(async_input, output);
    output<<L"Выход из OnTest"<<nl;
)
void OnTimer()
{
    output<<L"Таймер!"<<nl;
}
будет выдавать в окно такой результат:
  Скрытый текст
18:41:13 из потока 1. Таймер!
18:41:14 из потока 1. Таймер!
18:41:15 из потока 1. Вход в OnTest
18:41:15 из потока 1. Таймер!
18:41:16 из потока 1. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 
18:41:16 из потока 1. Таймер!
18:41:17 из потока 1. 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 
18:41:17 из потока 1. Таймер!
18:41:18 из потока 1. 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 
18:41:18 из потока 1. Таймер!
18:41:19 из потока 1. 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 
18:41:19 из потока 1. Таймер!
18:41:20 из потока 1. 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 
18:41:20 из потока 1. Таймер!
18:41:21 из потока 1. 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 
18:41:21 из потока 1. Таймер!
18:41:22 из потока 1. 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 
18:41:22 из потока 1. Выход из OnTest
18:41:22 из потока 1. Таймер!
18:41:23 из потока 1. Таймер!


Теперь показывай решение этой примитивной тестовой задачки на C#.
Re[18]: Facebook и язык D - первый шаг наверх.
От: alex_public  
Дата: 09.11.13 14:51
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Чудеса да и только. UI поток это частный случай потока с эвенлупом. Сейчас чуть более чем все приложения сложнее helloworld используют эти эвентлупы.


I>Асинхронщина сама по себе не нужна. Она нужна там, где работа с внешней системой где другое время. Без малого, весь сихронный ввод-вывод делается одинаково — шлется запрос и потом ожидание до окончания.


Ну я собственно это и имел в виду. Т.е. не принципиально ui это поток или нет (я просто называю так для краткости), главное что продолжение исполняется в том же потоке, который и инициировал асинхронный вызов. Вот в таком использование смысл имеется. А вот вариант, когда мы продолжим исполнение в каком-то произвольном пуле потоков (про что и писал gandjustas), уже на мой взгляд не приносит никакой пользы.
Re[23]: Facebook и язык D - первый шаг наверх.
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 09.11.13 15:03
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Теперь показывай решение этой примитивной тестовой задачки на C#.


Компилируемый код дай.
Re[22]: Facebook и язык D - первый шаг наверх.
От: alex_public  
Дата: 09.11.13 15:37
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Ты как то особенным образом понимаешь асинхронщину. В общем случае переписывать надо не из за дотнета, а из за того, что есть некоторое разделяемое состояние.


Не, переписывать надо исключительно из-за особенностей реализации await/async в .net.

I>Вот простой пример

I>function(){
I>                    var value = read();
I>                    write(next(value));
I>                }
I>

I>Вот функция, у ней в синхронном коде простой инвариант, проще не придумаешь. Проблема следующая — когда read или write становится асинхронным, между read и write может произойти нарушение инварианта. Вот из за этого и нужно переписывать код самой функции. Что характерно, в С++ ровно то же самое.

I>Итого — если ты решительно не согласен — покажи эту секретную технику " можем получить "идеально асинхронную" функцию из синхронной не трогая её код" что бы показаный инвариант сохранился.


Ты что-то всё путаешь. Всё зависит от того, как реализованы read и write. А точнее в каких потоках их можно вызывать. Есть варианты:

1. И read и write можно вызывать только в изначальном потоке. Тогда вообще ничего сделать нельзя и функция обречена быть синхронной.

2. И read и write можно вызывать в любых потоках. Тогда вообще всё просто и не нужны все эти хитрости типа await/async. Вот корректный асинхронный код:
thread([]{
    auto value=read();
    write(next(value));
}).detach();

А если нам требуется максимальное быстродействие и read и write относятся к разным устройствам, то можно вообще завести 2 независимых потока со своими буферами и синхронизацией (например через обмен сообщений по модели акторов). Но здесь уже понятно что не обойтись без модификации кода.

3. Смешанный вариант. Допустим read можно в любых потоках, а write только в изначальном. И только вот тут нам становятся нужны обсуждаемые хитрости. В C++ варианте я просто подменю функцию read на свою, содержащую вызов await_async([]{return read();}), и тогда напишу просто:
async_code(
    auto value=read();
    write(next(value));
)

В C# всё тоже самое, за исключением того, что обязательно требуется менять указанный код (добавить await). Причём менять надо не только его, но и весь стек вызова (добавить async).
Re[24]: Facebook и язык D - первый шаг наверх.
От: alex_public  
Дата: 09.11.13 15:50
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Компилируемый код дай.


Это он и есть. ) Точнее его часть, отвечающая за обсуждаемый вопрос. Остальной код касается исключительно вывода на экран окошка с кнопкой, причём реализованного через жирную GUI библиотеку, так что ты его всё равно у себя не соберёшь. Или же не поленишься поставить себе эту GUI библиотеку ради форумного спора? )))
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.