суббота, 7 сентября 2013 г.

await добрался до C++

Смотрю GoingNative 2013.

Особенно интересно выступление по теме "Bringing await to C++". "Асинронность" (ожидаемо) идет в массы и становится трендом. Настолько, что ее поддержку внедряют в компилятор и в будущий стандарт C++ (надеюсь, что последнее все-таки свершится). Понятное дело, это все для того, чтобы сделать программирование "асинхронности" максимально удобным для обывателей "среднестатистического программиста" и лучше оптимизировать.

Stackfull coroutines (наконец-то) идут в массы. Всего какой-то год назад "текли слюни" при взгляде на поддержку await в C#! Видимо, компании, которые массово используют C++ и потому влияют на его развитие, действительно активно используют асинхронные алгоритмы и остро нуждаются в средствах, способных облегчить их реализацию на C++ (а заодно и лучше оптимизировать подобный код).

Кто еще сомневается в необходимости работать с вводом-выводом асинхронно даже в клиентской части (например, уеt another messenger)? На "рельсы асинхронности" уже планируют перевести не только сетевой ввод-вывод - смотрите, примеры-то у всех (кто говорит, про PPL, std::future::then и даже про уже существующий WinRT) работают со "старыми добрыми" файлами (а, может быть, просто у них пока нет чего-то более-менее стандартного и краткого для сетевого ввода вывода?). И не только (правда, там уже делают больший упор на lazy-вычисления).

P.S. Q&A Panel особенно порадовала. Определенно, нынешний GoingNative гораздо лучше предыдущего и лучше уже прошедшего C++Now. Отличные докладчики (хотя их состав почти не меняется) с неплохим чувством юмора!

воскресенье, 1 сентября 2013 г.

::boost::asio::io_service::strand и лишние проверки

Среди заголовочных файлов "asio samples" лежит "скромный" ma/strand_wrapped_handler.hpp. Когда-то, разбираясь с invocation strategy и io_service::strand, я наткнулся на то, что стандартно обернутый через asio::io_service::strand::wrap() функциональный объект делает проверку (на исполнение в контексте strand-а) и в asio_handler_invoke, и в своем operator(). Так вот, обычно достаточно делать такую проверку только в asio_handler_invoke. "Обычно" в этом предложении означает: для всех классов Boost.Asio и вообще везде, где вы сами не вызываете напрямую operator() у функционального объекта, "обернутого" через strand. В противном случае, при использовании asio_handler_invoke с таким образом обернутым функциональным объектом (вспоминаем, что Boost.Asio всегда вызывает все user-defined обработчики только так), проверка на исполнение в контексте strand будет выполняться дважды! Данная операция не такая уж и легкая (использует мютексы/критические секции). Кому интересно, загляните в исходники Asio.

С тех пор (давно) вместо asio::io_service::strand::wrap() везде в "asio samples" я использую свой макрос MA_STRAND_WRAP(strand, handler), определенный в том самом ma/strand_wrapped_handler.hpp. Моя strand-"обертка" для функционального объекта использует asio::io_service::strand::dispatch только в asio_handler_invoke.

Автору Asio я писал (давно, в список рассылки). Он ответил, что те, кого волнуют подобные двойные проверки (я согласен с тем, что еще не известно, как/насколько они скажутся на производительности) смогут аналогично мне сами написать свою обертку. Кхм... В свете того, что Asio все чаще используется даже высоконагруженными гигантами вроде Mail.ru (и, кажется, уже давно в Yandex), хотел бы порекомендовать пользователям Asio по-чаще смотреть в исходники самой библиотеки Asio.