пятница, 29 декабря 2017 г.

[work-n-life] Послесловие к уходящему году...

В крайний рабочий день уходящего года можно попробовать сказать пару слов об итогах 2017-го в профессиональном плане. Да и не только в профессиональном.

2017-й оказался первым полным годом для нашей небольшой компании "СтифСтрим". В этом году мы закрыли свой первый контракт. В том числе и выполнили свои гарантийные обязательства по нему. Немного продвинули вперед SObjectizer. Больших релизов было всего два - версии 5.5.19 и 5.5.20, но зато было еще и несколько промежуточных, корректирующих релизов. SObjectizer получил поддержку vcpkg (спасибо Anton Stuk) и попал в ALT Linux (спасибо Pavel Vainerman).

Сделали пять больших докладов на различных конференциях. В том числе попали и на крупнейшую конференцию по C++ в СНГ -- C++Russia. Опыт очень интересный и полезный. Опубликовали одиннадцать статьей на Хабре.

Запустили два новых продукта: so_5_extra и RESTinio. Оба проекта стартовали с двойным лицензированием и прицелом на продажу лицензий. Но в отношении RESTinio наши намерения не нашли понимания у публики, поэтому мы перевели RESTinio под BSD-3-CLAUSE. Релизы RESTinio под пермиссивной лицензией были приняты очень благосклонно, в частности анонсы на reddit-е вызвали большой интерес. Так же RESTinio довольно неплохо показал себя в Mail.ru-шном HighloadCup-е.

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

Еще одна область, в которой ярчайшим образом проявилось отсутствие какого-либо опыта -- это маркетинг. Мы только начали учиться продвигать себя. Заработок на OpenSource-продуктах -- дело непростое и не быстрое, для поддержания штанов нужно брать заказы. Для этого нужен маркетинг самих себя, чему мы еще только-только учимся. Учиться трудно, т.к. область деятельности у нас специфическая, а популярная литература на этот счет, такое ощущение, ориентируется на обучение маркетингу товаров массового спроса. В общем, если кому-то нужно сделать что-то сложное на C++ или же нужно починить что-то сложное на C++, то вы знаете, к кому обращаться ;)

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


В завершение хочу сказать спасибо всем читателям блога. В этом году в блог я писал меньше. Интересных материалов, наверное, так же оказалось меньше. Может быть даже сильно меньше. Но спасибо, что продолжаете меня читать. Это и радует и, местами, вдохновляет. Плюс огромное количество полезной информации и соображений в комментариях. Так что еще раз спасибо. Да! Еще в 2017-ом удалось развиртуализироваться и пообщаться в живую с несколькими давними виртуальными знакомыми. Это было круто.

Этот пост, видимо, будет завершающим в 2017-ом. Подозреваю, что в этом месяце даже традиционного кинообзора не будет, впервые за много лет. Надеюсь, что исправлюсь в январе 2018-го. Так что...

С НАСТУПАЮЩИМ И ВСЕГО САМОГО ХОРОШЕГО В 2018-ом!

понедельник, 18 декабря 2017 г.

[prog.flame] Тут вот Boost-1.66 подтянулся с Beast-ом...

...и уже пошли восторженные отзывы о том, как же круто иметь поддержку HTTP в Boost-е и как же народу хочется поиграться с Beast-ом.

Ну что сказать? Посмотрим, как много из тех, кто попробует, всерьез возжелает работать с таким низкоуровневым кодом. Ну, чтобы было понятно, вот штатный пример асинхронного сервера на Beast-е. Страшно не стало? Ну тогда попробуйте туда добавить, скажем, контроль тайм-аутов для соединений. Все еще не страшно? ;)

А ведь многие попробовавшие, наверняка, будут довольны. И будут пользоваться таким низкоуровневым API. Ибо копипаста рулит и бибикает.

ЗЫ. Этот пост вовсе не наезд на библиотеку Beast. Сама-то она очень круто сделано. Но надо понимать, что Beast -- это конструктор, который позволяет вам собрать все, что вы захотите. Только вот собирать вам все придется самостоятельно и из очень мелких кусочков. Посему не очень правильно рассматривать Beast как готовый инструмент для конечных прикладных разработчиков. Это набор базовых строительных блоков. Хороший набор. Но только набор. Так что это скорее наезд на восторженных неофитов, которые ждут какого-то чуда уровня Go-шного fasthttp. Чуда не будет ;)

[prog.c++] Еще одна попытка упростить работу с отложенными сообщениями в SO-5

Прошу прощения у тех читателей блога, которым не интересно читать посты про SObjectizer. Но данный пост будет продолжением темы про отмену отложенных сообщений, начатую на прошлой неделе. Тогдашнее обсуждение показало, что предлагаемый способ вряд ли можно считать хорошим, к тому же он не решал определенных потребностей отдельных пользователей SO-5. Поэтому данная тема продолжила занимать мое внимание и вот очередная итерация. Кому интересно понаблюдать за эволюцией решений, которые со временем [не]попадают в SObjectizer, милости прошу под кат. Для всех остальных там ничего интересного не будет, сорри. Блог так устроен, что я пишу сюда о том, что занимает меня в конкретный момент времени...

четверг, 14 декабря 2017 г.

[prog.c++] Попытка упростить работу с отложенными сообщениями в SO-5

Удобная и простая работа с таймерами -- это одна из важных причин использования акторов вообще и SObjectizer-а в частности. Вот, скажем, в примере для вчерашней статьи на Хабре, мне потребовалось сгенерировать цепочку событий, происходящих спустя определенное время. Что элементарно выполняется посредством простого использования функции send_delayed:

std::vector<milliseconds> delays{ 125ms, 250ms, 400ms, 500ms, 700ms, 750ms, 800ms };

for(const auto d : delays) {
   const std::string msg = std::to_string(d.count()) + "ms";
   so_5::send_delayed<std::string>(env, ordinary_mbox, d, msg);
   so_5::send_delayed<std::string>(env, anti_jitter_mbox, d, msg);
}

За счет того, что работа с таймерами происходит легко и непринужденно, таймеры в SObjectizer-овских приложениях используются повсеместно. Инициируешь какую-то операцию, отсылаешь самому себе следом отложенное сообщение для проверки результата. Когда отложенное сообщение пришло, проверяешь есть ли результат или нет. Если результат пришел раньше, то вообще хорошо: на отложенное сообщение можно не обращать внимания.

Однако, при работе с отложенными сообщениями в SObjectizer-5 есть очень важный нюанс: не так-то просто отказаться от отосланного отложенного сообщения. Допустим, вы начали операцию, взвели отложенное сообщение, а результат операции пришел раньше. Вроде как отложенное сообщение вам больше не нужно. И тут вы можете оказаться в одной из двух ситуаций:

среда, 13 декабря 2017 г.

[prog.c++] SObjectizer-5.5.20 и so_5_extra-1.0.3

SObjectizer обновился до версии 5.5.20. Изменений в нем немного. Пожалуй, самое важное -- это обновленная и улучшенная поддержка CMake. Полный список изменений можно увидеть здесь.

Загрузить новую версию можно либо в виде архива с SourceForge, либо из svn-репозитория проекта, либо из зеркала на GitHub.

Уже пару месяцев SObjectizer доступен через систему управления зависимостями vcpkg. Так что сейчас последнюю версию SO-5 можно установить себе посредством команды vcpkg install sobjectizer

so_5_extra обновился до версии 1.0.3, в которой был добавлен еще один тип mbox-а: retained_msg mbox.

Взять so_5_extra можно либо в виде архива с SourceForge, либо из svn-репозитория.

Так же кого-то может заинтересовать свежая статья на Хабре, рассказывающая о такой важной штуке SObjectizer-а, как концепция mbox-ов.

понедельник, 11 декабря 2017 г.

[prog.c++] Хотелось бы побывать на C++Russia 2018

Стали известны даты и место проведения C++ Russia 2018: эта крупнейшая в СНГ конференция, посвященная языку C++, пройдет 20-21 апреля 2018-го года в Санкт-Петербурге (19-го апреля будет день мастерклассов).

Понятное дело, что хочется в ней поучаствовать. А дешевле всего это сделать в качестве докладчика ;) Посему нужно придумать тему для доклада.

В связи с этим я хочу спросить у своих читателей: а что бы вы услышать на C++ Russia 2018 в моем изложении?

Может быть что-то про SObjectizer? Может быть что-то про то, как C++ помогал/мешал нам в разработке SObjectizer-а? Может что-то еще?

В общем, есть возможность оставить свою заявку. А я ее внимательно рассмотрю :)

PS. Если кто не видел, вот мое выступление на С++ Russia 2017вот и слайды доклада).

понедельник, 4 декабря 2017 г.

[prog] А какие в Сети есть ресурсы, посвященные разработке middleware?

Поймал себя на том, что мониторинг русскоязычных профильных ресурсов, вроде Habrhabr, LOR, RSDN, opennet ведет к весьма низкому проценту полезного сухого остатка. Потому, что изрядная доля тамошних материалов касается прикладных задач. Яркий пример -- вот эта статья, которую я просмотрел из-за наличия тега Go (ну интересно, как и где используется Go).

Как по мне, так ниша прикладных задач для C++ (да и для Rust-а, полагаю), закрылась давным-давно. Может уже лет двадцать назад. Хотя я вообще придерживаюсь мнения, что для прикладных задач C++ вообще никогда не предназначался. Сейчас для применения C++ есть несколько ниш, в которых C++ может быть вполне разумным выбором. Ниши эти специфические, хотя и не такие уж маленькие.

Одна из таких ниш -- это разработка разнообразного middleware. Ну, например, это могут быть СУБД. Могут быть MQ-шные брокеры. Могут быть какие-то шлюзы, вроде SMTP-шлюзов. И т.д.

В связи с этим у меня вопрос к читателям: есть ли какие-то ресурсы, на которых вопросы разработки middleware представлены в концентрированном виде?

Ну вот, есть, скажем, ресурс highscalability.com. Интересный дайджест-ресурс для материалов из области высоконагруженных систем. Хотелось бы найти что-то похожее, но для направления middleware. Может кто-то что-то подскажет?

пятница, 1 декабря 2017 г.

[life.cinema] Очередной кинообзор (2017/11)

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

Тор: Рагнарек (Thor: Ragnarok, 2017). Безусловно, главный фильм месяца. Смешной. Отличный видеоряд и бодренькое, местами, музыкальное сопровождение. Но вот там, где плотность шуток снижалась, мне было скучновато. А так отличное кино, чтобы отключить мозги и получить удовольствие.

Удача Логана (Logan Lucky, 2017). Отличное кино, но по-началу неспешное и нудное. Это нужно перетерпеть, развязка, как по мне, все оправдывает.

Иностранец (The Foreigner, 2017). В принципе, мне понравился фильм. И Джекки Чан в некоммедийной роли был вполне себе. Хотя от своих фирменных трюков в рукопашных схватках все равно не ушел, что как раз и портило впечатление от фильма. Если бы не это, то фильм был бы гораздо лучше, как по мне.

Погром (Mayhem, 2017). Я любитель такого рода фильмов, главный смысл которых -- это "мочи их всех!". Поэтому и данную картину посмотрел с удовольствием. Но, если бы в него вложили чуть-чуть побольше денег, то получилось бы еще круче и убойнее.

Механика теней (La mécanique de l'ombre, 2016). Европейцы снимают кино не так, как американцы. Иногда получаешь удовольствие просто от того, что кино выглядит и воспринимается совсем не так, как голливудская продукция. Здесь именно такой случай. Вроде бы не динамично, вроде бы нет захватывающей истории, а смотреть все равно интересно. И герою сопереживаешь.

Жизнь впереди (2017). Смотреть было интересно. Но когда фильм закончился, то возник вопрос: "И это все?" Как по мне, так авторы только-только раскрыли своих персонажей, познакомили с ними зрителей, подготовили к неминуемой кульминации... Которой как раз и не случилось.

Виселица (Hangman, 2017). В общем-то добротно сделанный фильм с неким налетом ностальгии по аналогичным фильмам из 1990-х годов. К сожалению, в конце мотивация главного злодея не убеждает, да и сама развязка выглядит сделанной слишком халтурно для той интриги, которую начали закручивать с самого начала.

Смерть на Аляске (Sweet Virginia, 2017). Так себе. Все время ждешь, что вот-вот что-то такое произойдет, что оправдает потраченное время. А оно не происходит и не происходит. Хотя к актерам, например, претензий нет. Это скорее сама история такая, не цепляющая.

Наемник/Американций убийца (American Assassin, 2017). Первая половина или даже первые 2/3 фильма вполне себе OK. Но вот то, что происходит в финале, особенно с ядрёной бомбой... Это какой-то сплошной facepalm.jpg.

Геошторм (Geostorm, 2017). Жалкое поделие из категории "Что это, блин, было?" Наверное, фильм рассчитан на категорию детей младшего школьного возраста. Но даже и в этом случае спецэффекты хотелось бы более качественные, не оставляющие впечатление мультика.

среда, 29 ноября 2017 г.

[prog.c++] Смотрим в сторону SObjectizer-5.6 (самое первое приближение)

Прошло уже более трех лет с момента релиза версии 5.5.0. Все эти три года SObjectizer развивался в рамках ветки 5.5 с особым акцентом на совместимость между версиями. Может быть не всегда у нас получалось сохранять 100% совместимость и где-то что-то могло поломаться. Но, в подавляющем большинстве случаев, насколько мне известно, переход на новые версии SO-5.5.* происходил без каких-либо сложностей и необходимости что-то исправлять в коде.

В сохранении совместимости между релизами SObjectizer на продолжении многих лет есть много хорошего. Так уж получилось, что нам доводилось заниматься софтом, который находился в эксплуатации долгое время (большее 10 лет) и мы знаем, насколько важна обратная совместимость. Но есть и другая сторона: далеко не всегда получается расширять функциональность SObjectizer-а так, чтобы ничего не поломать. От чего-то приходится отказываться, откладывая новые фичи до следующего мажорного релиза, в котором совместимость можно будет поломать и это будет воспринято нормально.

Имхо, три года развития в рамках ветки 5.5 -- это вполне достаточный срок для того, чтобы задуматься о том, чтобы заняться версией 5.6, в которой уже не будет 100% обратной совместимости с SObjectizer-5.5. И переход на которую будет требовать модификации исходников, а может быть, местами, и перепроектирования. Посему под катом изложено несколько текущих мыслей на тему версии 5.6. Кому интересно -- милости прошу. Чем больше будет фидбэка, тем лучше.

[business] Какие способы продвижения себя работают, а какие нет?

Вопрос к читателям, которым приходилось продвигать/рекламировать себя/свою компанию (как исполнителя/подрядчика/субподрядчика) и/или свои продукты (особенно продукты не массового спроса). А так же ко всем, кто интересовался этим вопросом или видел полезные материалы по этой теме... Итак, вопрос: какие способы продвижения, по вашему опыту, работают, а какие -- нет?

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

Наверняка есть и другие способы, которые для большинства так же заведомо не работают. Хочется об этом узнать побольше.

Поясню откуда возник такой интерес. Наша компания занимается не только разработкой Open-Source продуктов, но и оказанием еще нескольких видов услуг. До сих пор это направление мы вообще никак не рекламировали и не акцентировали на нем внимание. Видимо, это было неправильно. Нужно устранить эту недоработку ;) Но, т.к. к своей работе мы подходим основательно, стараясь предварительно освоить материал, то хочется изучить опыт старших и более опытных в продажах товарищей.

Посему, если кто-то сочтет возможным поделиться своим опытом или ссылками на соответствующие материалы, то мы скажем большое человеческое спасибо!


Ну и да, если кому-то лень зайти на наш сайт в раздел Услуги, то кратко и по существу: мы разрабатываем софт и под заказ. Дорого (по крайней мере, по меркам РФ), долго, качественно. Хотя первые два пункта могут обсуждаться, а вот делать некачественно -- вот это вряд ли.

понедельник, 27 ноября 2017 г.

[prog] Ссылки, которые помогли мне в борьбе с CMake

Вроде как удалось забороть CMake и получить то, что хотелось. Зафиксирую в склерознике несколько ссылок, которые помогли лично мне. Может быть они помогут еще кому-нибудь.

Сразу скажу, что это ссылки на уже более-менее продвинутый материал. Если у вас нет опыта работы с CMake вообще, то нужно начать с чего-нибудь совсем простого. Благо тривиальных примеров работы с CMake в Сети очень много. Такое ощущение, что любой чайник, которому удалось самостоятельно собрать с помощью CMake простой HelloWorld из одного cpp-файла, считает своим долгом написать развернутую статью о том, как пользоваться CMake. В подавляющем большинстве все эти статьи ни о чем и на 90% повторяют друг друга. Из толковых вводных материалов я бы отметил вот этот репозиторий с примерами.

Если же говорить о более продвинутых материалов, то:

Две презентации от Daniel Pfeifer: "CMake - Introduction and best practices" и "Effective CMake". Для тех, кто пытается жить с современным CMake, эти презентации, как говорится, must have and must read.

Очень мне помог краткий тутуриал по использованию CMake от проекта KDE. Вроде как там ничего секретного не раскрывается. Но именно там мне стало понятно, как делаются какие-то вещи.

В качестве примеров CMake-файлов помогли исходники проектов Cinder и AWS SDK C++.

Ну и куда же без официальной документации по самому CMake. Для меня основным мануалом стал раздел cmake-packages (ну и ссылки оттуда на другие документы). Не скажу, что описано толково и понятно. Но вкурить, в конце-концов, удалось.

Надеюсь, эти ссылки помогут в освоении современного CMake.


За минувшую неделю я уже достаточно набросил на CMake. Но, даже после того, как мне удалось его более-менее забороть, я все равно думаю, что если CMake -- это лучшее, что C++-сообщество смогло для себя сделать, и если CMake -- это и есть то "светлое" будущее, которое ждет мир C++, то C++ вместе с его миром и "светлым будущим" под ручку с CMake нужно закапывать. Быстро и безжалостно.

пятница, 24 ноября 2017 г.

[prog.c++] Альфа-версия обновленной поддержки CMake в SObjectizer

Задышала первая версия обновленных CMake-скриптов для SObjectizer-5.5.20. Взять и попробовать можно вот из этого архива. Взять и попробовать очень желательно, ибо сами мы не местные CMake в своей работе не используем. Поэтому на своих повседневных задачах проверить правильность сделанных CMake-скриптов не можем. А вот тем, кто использует SObjectizer именно через CMake наши изменения могут помочь. Или навредить :)

Итак, что было сделано? Было сделано так, чтобы SObjectizer можно было через CMake собрать, затем выполнить make install, затем задействовать у себя в проекте посредством find_package.

Попробую пояснить на пальцах. Для Unix-подобных систем, т.к. там проще.

Скачиваем архив с SObjectizer-ом, распаковываем его: unzip so-5.5.20-alpha2-201711251230.zip и заходим в образовавшийся каталог so-5.5.20-alpha2-201711251230. Там выполняем следующие действия:

mkdir cmake_build
cd cmake_build
cmake ../dev
cmake --build . --config Release
cmake --build . --config Release --target install

Будет скомпилирован только SObjectizer в виде статической и динамической библиотек. После этого он будет установлен в стандартных для вашего Unix-а путях (например, в /usr/local/include, /usr/local/lib).

Если у вас CMake-3.8 или более новый, то для того, чтобы использовать SObjectizer в своем CMake проекте вы пишете что-то вроде:

cmake_minimum_required(VERSION 3.1)

project(hello_world)

find_package(so_5 5.5.20 REQUIRED)

add_executable(hello_world_static hello_world.cpp)
target_link_libraries(hello_world_static so_5::StaticLib)

Тут строится приложение hello_world_static, которое линкуется к статической версии SObjectizer-а.

Если нужно слинковаться с динамической библиотекой SObjectizer-а, тогда пишете что-то вроде:

cmake_minimum_required(VERSION 3.1)

project(hello_world)

find_package(so_5 5.5.20 REQUIRED)

add_executable(hello_world_shared hello_world.cpp)
target_link_libraries(hello_world_shared so_5::SharedLib)

Ну и компилируете это обычным образом.

Если же вы под Windows или не хотите гадить в своем уютненьком Unix-е в стандартные пути для размещения библиотек, то можно поступить, например, так (предполагаем, что ~ -- это ваш рабочий каталог, в рамках которого вы хотите оставаться, и в который вы уже скачали so-5.5.20-alpha2-201711251230.zip):


~$ unzip so-5.5.20-alpha2-201711251230.zip
~$ cd so-5.5.20-alpha2-201711251230
~/so-5.5.20-alpha2-201711251230$ mkdir cmake_build
~/so-5.5.20-alpha2-201711251230$ cd cmake_build
~/so-5.5.20-alpha2-201711251230/cmake_build$ cmake -DCMAKE_INSTALL_PREFIX=target -G "Visual Studio 12 2013" ../dev
~/so-5.5.20-alpha2-201711251230/cmake_build$ cmake --build . --config Release
~/so-5.5.20-alpha2-201711251230/cmake_build$ cmake --build . --config Release --target install
~/so-5.5.20-alpha2-201711251230/cmake_build$ cd ~/hello_world
~/hello_world$ mkdir cmake_build
~/hello_world/cmake_build$ cmake -DCMAKE_PREFIX_PATH=~/so-5.5.20-alpha2-201711251230/cmake_build/target -G "Visual Studio 12 2013" ..
~/hello_world/cmake_build$ cmake --build . --config Release

Для Unix-а, естественно, придется поменять значение в -G (либо вообще -G не указывать, т.к. под Unix-ами обычно имеется всего один тулсет).

Если у вас более старый CMake, чем CMake-3.8, то придется выполнить в своих CMakeLists.txt дополнительные действия: нужно указать, что вам требуется C++11. Например, это можно сделать в вашем главном CMakeLists.txt:

cmake_minimum_required(VERSION 3.1)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

project(hello_world)

find_package(so_5 5.5.20 REQUIRED)

add_executable(hello_world_shared hello_world.cpp)
target_link_libraries(hello_world_shared so_5::SharedLib)

Пример того, как можно подключать SObjectizer через find_package, можно увидеть в этом репозитории (см. dev/CMakeLists.txt).


Вообще говоря, должен продолжать работать и другой сценарий использования SObjectizer и CMake. Вы можете включить SObjectizer в свое дерево исходников. Чтобы у вас было что-то вроде:


~/your_project_root
  `- so_5/
  `- timertt/
  `- your_another_project/
  `- your_main_project/
  ...
  CMakeLists.txt

И вот в своем главном CMakeLists.txt вы имеете возможность сделать просто add_subdirectory(so_5) и все. Далее вы должны получить возможность использовать so_5::StaticLib и so_5::SharedLib в своих CMake-овских командах target_link_libraries.

Пример того, как можно подключать SObjectizer через add_subdirectory, можно увидеть в этом репозитории (см. dev/CMakeLists.txt).


В общем, еще раз просьба к тем, кто использует SObjectizer совместно с CMake: попробуйте новую версию. Любой фидбек нам будет полезен и поможет сделать поддержку CMake более удобной.

среда, 22 ноября 2017 г.

[prog.c++] Шаблоны против копипасты 7: вывод нужных типов из указателей на методы

В коде решения для Highload Cup-а Коли Гродзицкого обнаружился интересный способ использования C++ных шаблонов для того, чтобы избавится от копипасты. Насколько я понимаю, суть проблемы была в следующем:

Есть класс database_t, который нужно наполнить экземплярами структур user_t, location_t и visit_t. Структуры же эти вычитываются из JSON-файлов. Т.е. есть файлик вроде users_1.json, из которого нужно прочитать все JSON-объекты, преобразовать их в экземпляры user_t и запихнуть все эти экземпляры в database_t. Тоже самое нужно сделать с visits_1.json (структуры visit_t) и locations_1.json (структуры location_t).

Видимо, код всех этих операций был настолько однотипным, что за счет шаблонов его удалось свести вот к такому:

[prog.c++] Что и как следует улучшить в CMake-овских скриптах для SObjectizer?

Благодаря помощи Алексея Сырникова в SObjectizer уже несколько лет есть поддержка CMake. Сейчас, по ходу разработки очередной версии, мы хотим улучшить эту поддержку. Посему обращаемся ко всем, кто пытался использовать SO-5 и CMake с вопросами:

Что вам мешало в существующих CMake-скриптах для SO-5?

Чего вам не хватает в существующих CMake-скриптах для SO-5?

Что вам хотелось бы видеть в CMake-скриптах для SO-5?

К счастью, сами-то мы не настоящие сварщики пользуемся CMake, поэтому нам самим сложно судить о том, насколько удобны или неудобны существующие скрипты. Соответственно, нужна помощь тех, кто попробовал воспользоваться CMake для SO-5 и столкнулся с какими-либо сложностями/проблемами/недостатками.

понедельник, 20 ноября 2017 г.

[prog.thoughts] В догонку к докладу на GECon-2017

В презентации к докладу на GECon-2017 почти 90 слайдов. При этом довелось выбросить еще с десяток слайдов, которые могли бы сделать изложение более интересным и плавным, что ли. Все-таки временные рамки в 40 минут на доклад дали о себе знать.

При этом осталось впечатление, что если не ограничиваться 40 минутами, а исходить хотя бы из часа-полутора, то на базе этого доклада можно было бы сделать неплохую лекцию о том, как C++ появился, почему оказался востребованным, почему его востребованность снизилась, почему при этом C++ так и не закопали (и не закопают), где и как можно (нужно) применять C++ в современных условиях, насколько сильна конкуренция со стороны других языков и почему тут все далеко не так однозначно (даже в случае с Rust-ом).

В общем, если кто-то заинтересуется такой лекцией, то дайте знать. Я сам пока не очень понимаю, зачем это лично мне (наверное, просто потому, что могу). Но, если будут интересные идеи, то почему бы и не сотворить что-нибудь? В конце-концов, не думаю, что у нас в РБ так уж много действующих C++ разработчиков, использующих C++ на протяжении 25 лет.

[prog] Краткие впечатления от участия в GECon-2017

18-го ноября 2017-го в Гомеле EPAM провел очередную большую и бесплатную ИТ-конференцию GECon-2017. Для нашего небольшого города событие, прямо скажем, далеко не рядовое. Мне довелось поучаствовать в конференции в качестве докладчика (насколько я понял, в качестве единственного не-EPAM-овского докладчика).

20171120-112042-DSCF8919

В целом мне очень понравилось. В этом году мне довелось поучаствовать в нескольких конференциях, могу сказать, что подготовка к GECon-у была одной из самых серьезных. Может быть даже жестче и строже, чем подготовка к C++Russia. Так что в качестве результата сомневаться не приходилось изначально. На фоне этого мне даже удивительно, что на конференцию заявилось всего 300 человек, а не в 2-3 раза больше. Высокий уровень подготовки, докладчики, имеющие опыт работы на очень серьезных проектах, бесплатность и место проведения прям в центре Гомеля... Как по мне, так глупо упускать шанс принять участие в таком мероприятии.

Огромный пласт положительных эмоций связан с тем, что на конференции довелось встретить много своих бывших коллег. Даже не ожидал, насколько их много. И насколько приятно пообщаться с людьми, с которыми был съеден не один пуд соли. Собственно, и свой доклад я читал практически "для своих": было ощущение, что процентов 70% слушателей доклада составляли те, кто либо работал со мной, либо просто знает меня.

По субъективным впечатлениям доклад получился. Не смотря на обилие слайдов и не очень удобную аудиторию (вместо экрана проектора в аудитории были установлены телевизоры, на которых слайды смотрелись довольно мелко), все прошло достаточно бодренько. Во время уложился, на вопросы отвечал, может быть даже слишком развернуто. Могу ошибаться, но мне показалось, что на этой конференции мой доклад был самым хардкорным и насыщенным.

Слайды доклада лежат здесь. Ссылку на видео добавлю когда организаторы конференции зальют видео выступлений на какой-нибудь публичный ресурс.

Однако, мне показалось, что есть несколько моментов, которые могли бы сделать конференцию еще круче, интереснее и полезнее.

Во-первых, организаторам надо бы более четко определиться с тем, какова основная цель конференции. У меня сложилось ощущение, что сами организаторы не очень понимали, какую именно цель они преследуют. Если цель в том, чтобы "прорекламировать" ЕПАМ, рассказать, насколько это крутая компания, насколько хорошо для ИТ-специалиста в ней работать, какие перспективы там ждут классных специалистов, то это одно. Если цель в том, чтобы создать площадку для независимого обмена опытом, типа "у нас в ЕПАМе есть куча опыта, вокруг ЕПАМа есть куча другого опыта, давайте соберемся и обменяемся этим опытом", то это другое. Если цель в том, чтобы организовать обмен опытом между сотрудниками самого ЕПАМа (а их много, компания ведет тысячи разнообразных проектов, поэтому даже сотрудники одного регионального офиса ЕПАМа могут иметь совершенно разный опыт), то это третье.

На этой конференции мне временами мешало то, что в докладах всплывала какая-то внутренняя ЕПАМовская специфика, которую не понимали люди извне. При этом какая-то важная информация не могла быть озвучена (например, имена заказчиков, для которых выполнялись те или иные работы, параметры нагрузки и другая интересная информация). В результате складывалось такое ощущение: "мы хотим прорекламировать себя, но сделать под видом обмена опытом, но без учета того, что может быть интересно людям не из ЕПАМа".

Во-вторых, мне показалось, что регламент докладов, пауз и перерывов на обед был неудачным. Тайм-слот для докладов на 1 час -- это правильно. 40 минут на сам доклад, затем 20 минут на вопросы -- это очень удобно. По-моему и для докладчика, и для слушателей. Но вот потом нужно делать совсем небольшой перерыв, скажем, минут 10, не больше. Чтобы можно было обменяться контактами с тем, кто тебя заинтересовал. И занять место на следующем докладе. Со всего одним перерывом на обед (кофе-брейк). Причем сделать длинный кофе-брейк надо было так, чтобы людям никуда не нужно было уходить. Чтобы все общение проходило на относительно небольшом пятачке.

В этот же раз было два небольших кофе-брейка между докладами (один до обеда, второй после обеда) + перерыв на обед в полтора часа. Причем чтобы пообедать людям нужно было покидать место проведения конференции. В результате, на кофе-брейках основная часть народа просто выстраивалась в очереди к столам раздачи печенек. А на время обеда место проведения конференции просто опустело. Имхо, это был самый большой просчет организаторов.


В завершении же хочу поблагодарить компанию ЕПАМ и ее сотрудников, причастных к проведению GECon-а: большое спасибо за вашу работу. Для нашего города и нашего ИТ-сообщества GECon-2017 стал, пожалуй, самым ярким и масштабным событием года.

пятница, 17 ноября 2017 г.

[prog.c++.thoughts] Какой вклад в сложность C++ вносит борьба с самой сложностью C++?

Давеча один из интересующихся SObjectizer-ом пользователей задал вопрос: а можно ли использовать в SO-5 в качестве обработчиков сообщений const-методы? Вопрос оказался, что называется, внезапным. Мы используем SO-5 в разработке софта уже лет семь (как раз где-то в конце 2010 первые стабильные версии SO-5 пошли в дело, если мне не изменяет склероз). Но ни разу нам не пришлось столкнуться с тем, чтобы обработчик сообщения следовало бы пометить модификатором const. Видимо, это потому, что обработчики сообщений в подавляющем большинстве случаев меняют состояние агента, поэтому не было смысла использовать const-методы в качестве обработчиков. А тут новый человек, другие задачи, другой взгляд на решение этих задач. И const-методы оказались нужны.

Ну, OK. Какие проблемы, будем делать.

Только вот как это сделать так, чтобы трудоемкость и сопровождаемость получившегося решения не зашкалила? Речь идет о том, чтобы преобразовать 6-7 методов вот такого формата:

templateclass RESULT, class ARG, class AGENT >
subscription_bind_t &
event(
   RESULT (AGENT::*pfn)( ARG ),
   thread_safety_t thread_safety = not_thread_safe );

которые живут в SO-5 давно, и используются повсеместно.

Нужно было получить методы, которые бы могли принять как RESULT(AGENT::*pfn)(ARG), так и RESULT(AGENT::*pfn)(ARG) const.

Простейший вариант, который приходит в голову -- это тупое дублирование:

четверг, 16 ноября 2017 г.

[prog.c++] Наткнулся на странное в VC++12

Разбавляя код SObjectizer-а шаблонной магией наткнулся на странную штуку в VC++12 (который из VS2013). Такое ощущение, что когда вложенность лямбд оказывается достаточно большой и очередная лямбда не захватывает контекст (т.е. может быть конвертирована в обычную функцию), то VC++ в качестве типа лямбды начинает использовать не анонимный класс с operator(), а указатель на функцию с соответствующей сигнатурой. Т.е. тупо конвертирует лямбду в функцию и дальше использует тип этой функции в качестве типа лямбды. Проявилось это вот на такой строчке. Там реально лямбда на лямбде и лямбдой погоняет :)

К счастью, в более новых версиях VC++ уже такого нет, там лямбда остается лямбдой. Надо бы закругляться с поддержкой VC++12.0. Видимо, в 2018 мы перестанем поддерживать этот компилятор в SO-5.

Еще захотелось, чтобы в C++ таки концепты завезли. Ибо набирать такое, наверное, прикольно, но уж больно муторно:

templatetypename Method_Pointer >
typename std::enable_if<
      details::is_agent_method_pointer<Method_Pointer>::value,
      subscription_bind_t & >::type
event(
   Method_Pointer pfn,
   thread_safety_t thread_safety = not_thread_safe );

Хотелось бы один раз определить концепт MethodAsHandler, а потом указывать этот концепт в декларации метода:

subscription_bind_t &
event(
   MethodAsPointer pfn,
   thread_safety_t thread_safety = not_thread_safe );

Осталось каких-то три годика подождать... :)

понедельник, 13 ноября 2017 г.

[prog.c++] Полку парсеров аргументов командной строки для современного C++ прибыло

Давеча на глаза попалась информация о двух новых библиотеках для работы с аргументами командной строки в современном C++. Поскольку в G+ ленте нет возможности поиска по своим же собственным постам (что печально), то зафиксирую информацию об этих библиотеках в блоге, дабы было проще найти при случае. Сразу скажу, я эти библиотеки пока не использовал, даже в код не заглядывал. Но судя по тому, что видно на поверхности, выглядит очень вкусно.

Итак, первая библиотека -- Clara от автора отличного инструмента для TDD и BDD в C++, Catch/Catch2 (с недавних пор библиотека называется именно Catch2). Clara изначально развивалась внутри Catch, но при подготовке Catch2 ее выделили в отдельный проект. Получается, что Clara является более-менее проверенной библиотекой, все-таки Catch2 используется весьма активно. Плюс работает на разных платформах и с разными компиляторами. Но, с другой стороны, документация пока оставляет желать много лучшего.

Пример того, как может выглядеть работа с Clara я выдрал из unit-тестов для нее:

using namespace clara;
struct TestOpt {
    std::string processName;
    std::string fileName;
    int number = 0;
    int index = 0;
    bool flag = false;
    std::string firstPos;
    std::string secondPos;
    std::vector<std::string> unpositional;

    auto makeCli() -> Parser {
        return ExeName( processName )
          | Opt( fileName, "filename" )
              ["-o"]["--output"]
              ( "specifies output file" )
          | Opt( number, "an integral value" )
              ["-n"]
          | Opt( [&]( int i ) {
                    if (i < 0 || i > 10)
                        return ParserResult::runtimeError("index must be between 0 and 10");
                    else {
                        index = i;
                        return ParserResult::ok( ParseResultType::Matched );
                    }
                }, "index" )
              ["-i"]
              ( "An index, which is an integer between 0 and 10, inclusive" )
          | Opt( flag )
              ["-f"]
              ( "A flag" )
          | Arg( firstPos, "first arg" )
              ( "First position" )
          | Arg( secondPos, "second arg" )
              ( "Second position" );
    }
};

Здесь метод TestOpt::makeCli как раз и создает парсер аргументов командной строки, который сохраняет разобранные значения внутри экземпляра структуры TestOpt.

Как и положено такого рода инструментам Clara автоматически генерирует usage-string, который можно отобразить пользователю.


Второй инструмент -- это clipp. Так же header-only, так же ему достаточно только стандартной библиотеки современного C++. Средства описания аргументов командной строки похожи на таковые в Clara, но, как мне показалось, здесь все более продвинуто:

#include <iostream>

#include "clipp.h"

using namespace clipp;
using std::cout;
using std::string;

int main(int argc, char* argv[]) { 
    bool rec = false, utf16 = false;
    string infile = "", fmt = "csv";

    auto cli = (
        value("input file", infile),
        option("-r""--recursive").set(rec).doc("convert files recursively"),
        option("-o") & value("output format", fmt),
        option("-utf16").set(utf16).doc("use UTF-16 encoding")
    );

    if(!parse(argc, argv, cli)) cout << make_man_page(cli, argv[0]);
    // ...
}

Если с аргументами что-то не так, то можно автоматически сгенерировать вот такой текст:

SYNOPSIS
    convert <input file> [-r] [-o <output format>] [-utf16]

OPTIONS
    -r, --recursive  convert files recursively
    -utf16           use UTF-16 encoding

Библиотека использует перегрузку операторов, что позволяет записывать вот такие-вот DSL-и:

auto cli = ( 
    option("-b")          % "activates b"   >> b,             
    option("-c""--noc") % "deactivates c" >> set(c,false),
    option("--hi")        % "says hi"       >> []{cout << "hi!\n";} );

Вообще, документация оставляет самые приятные впечатления. А вот по поводу кода на Reddit-е высказали замечания. С которыми автор библиотеки согласился и пояснил, что разработка еще не завершена и, например, под MSVC он пока особо ничего не проверял. Так что дока хорошая, а вот либа еще сырая. Хотя желание попробовать вызывает.

суббота, 11 ноября 2017 г.

[life.books] Коротко о четырех книгах, которые я пытался прочитать в последнее время

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

Первая книга -- "Просто гениально" за авторством Уильяма Тейлора.

С трудом добрался до середины. Так и не понял, что это было: либо попытка донести до читателя обилие фактов, которые известны автору, или же желание похвастаться знакомствами с кучей людей и знанием большого количества фактов из истории тех или иных компаний. Мне показалось, что второе. Т.к. нет связного изложения, в котором бы озвучивался некий тезис, а потом этот тезис последовательно доказывался бы опытом тех или иных компаний/предпринимателей. Вместо этого идет какой-то сумбур из примеров, отсылок к каким-то персоналиям, цитатам из этих персоналей, перескакиваний от одного примера к другому...

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

Вторая книга -- "Покер лжецов" Майкла Льюиса.

Просто оказалась не моя тема. В книге рассказывается о том, что происходило на Уолл-стрит с конца 1970-х и начала 1980-х. Рассказывается, в основном, о людях, но с сильной привязкой к финансовым механизмам, которые работали в то время. Но, поскольку в торговле ценными бумагами я вообще ничего не понимаю, то не понимаю и контекста, внутри которого происходят описываемые автором события. Без такого понимания читать просто не интересно. Но вообще книга написана живым, может быть местами грубоватым, языком. Так что если кто-то знаком с рынком облигаций, то ему книга может быть покажется интересной. Я же не дочитал и до половины.

Третья книга -- "«Do not disturb». Записки отельера". Автор Юнис Теймурханлы.

Отличная подборка небольших баек из опыта владельца одного из питерских отелей. Читал с интересом, получил большое удовольствие. Так что если кто-то любит читать профессиональные байки, то рекомендую.

Наконец, четвертая книга -- "Ген директора" Владимира Моженкова.

Просто отличная книга. Все четко, по делу, без воды, хождения по кругу и лишних соплей. Тем, кто собирается открывать свое дело или же пытается чем-то управлять, имеет смысл прочесть. Какие-то моменты могут конкретно зацепить. Например, меня зацепил момент, связанный как раз с чтением книг. Автор рассказывал, как он прививал в своей компании привычку к чтению. И как затем начал спрашивать "Ну вот ты прочитал, а что применил? Ничего? Так зачем читал?". Я вроде как чего-то по менеджменту читал. Но не скажу, что применял. Скорее читал для того, чтобы лучше понимать происходящее и расширить свой кругозор. Поэтому такой вопрос "в лоб" меня самого застал врасплох :)

пятница, 10 ноября 2017 г.

[prog.c++] Пересмотр приоритетов для SO-5.5.20

Долго не было возможности вплотную заняться работами над очередной версией SObjectizer под номером 5.5.20. Сейчас такая возможность появилась. Но за прошедшее время произошел некоторый пересмотр приоритетов по хотелкам для версии 5.5.20. Полный список хотелок можно найти здесь (именно хотелок, не все их них в принципе должны были попасть в бэклог).

Первоначально планировалось начать с того, чтобы дать возможность пользователю параметризовать диспетчеры собственным типом thread. Т.е. если кому-то не хочется использовать std::thread, а хочется подсунуть что-то свое, на базе, скажем pthreads (с надобностью задавать специфические параметры для новых нитей), тот мог бы указать свой тип вместо std::thread.

Однако, время показало, что нам в stiffstream прямо сейчас эта функциональность нигде не нужна. Посему приоритет этой работы снижается до минимума.

Если же кому-то возможность использовать собственные нити вместо std::thread нужна уже сейчас или в обозримом будущем, то дайте нам знать. Если это реально кому-то нужно, то приоритет мы поднимем и такую функциональность реализуем. Но хочу, чтобы было понятно: в SO-5 сейчас и так уже достаточно фич. Просто так добавлять туда очередную фичу просто "шоб было" a) не интересно и b) не выгодно. Все-таки мы делаем SO-5 за свои и тратить свои ресурсы на то, что останется лежать мертвым грузом -- это сомнительная идея.

Так что если вам что-то нужно в SO-5, то найдите способ сказать нам об этом (например, в комментариях к этой заметке, а еще лучше по email: info at stiffstream dot com или eao197 at stiffstream dot com, или на мой gmail-овый ящик). То, что нужно реальным или потенциальным пользователям, мы будем добавлять в SO-5.

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

  • более простая и тесная интеграция mchain-ов и агентов. Суть в том, чтобы сообщение, которое кто-то отсылает в mchain, могло поступать напрямую конкретному агенту. Тем самым mchain работал бы как естественный механизм overload control. Подробнее это описано здесь;
    • эта фича сейчас под вопросом до тех пор, пока не появятся какие-то дополнительные типы mchain-ов (например, в рамках so_5_extra). Когда будут разные типы mchain-ов, с разной логикой поведения, тогда будет лучше понятно, можно ли сделать универсальную интеграцию агента с разнотипными mchain-ами.
  • возможность каскадировать mbox-ы. Это выглядит актуальным в связи с появлением новых типов mbox-ов в so_5_extra. Например, может быть MPMC-mbox, одним из подписчиков которого будет collecting_mbox, а подписчиком collecting_mbox-а может быть round-robin mbox, подписчиком которого могут быть mchain-ы. Сейчас подписчиком mbox-а можно сделать только агента и это не позволяет выстраивать подобные цепочки без использования промежуточных агентов. Может быть такая возможность каскадирования mbox-ов поможет, например, в реализации реактивного программирования поверх SO-5;
    • разбирательство с текущим механизмом доставки сообщений показало, что эту функциональность сложно сделать без слома API. Делать такой слом в ветке 5.5 неразумно (следует сохранять совместимость в рамках релизов 5.5.*). А выделять версию 5.6 только ради одной фичи -- это преждевременно;
  • какое-то приближение к идее сессионных типов. Это когда сценарий взаимодействия между агентами описывается на уровне типов: сперва в одну сторону может пойти сообщение request, а обратно может прийти либо response, либо timeout, а затем может пойти только finish, но не request. Либо же это может быть какое-то приближение к типизированным mbox-ам и/или агентам. Опять же, прямо на уровне типов описывается, какие воздействия воспринимаются mbox-ом/агентом. Данная тема поднималась ранее;
  • какие-то инструменты для упрощения тестирования агентов. Этот вопрос задавали на последней C++ CoreHard. И он действительно актуален, т.к. тестирование агентов, которые общаются с внешним миром через асинхронные сообщения -- это не просто. Но в данной теме еще и конь не валялся.

В общем, пока вот такие приоритеты. Опять же повторюсь, если будут какие-то конкретные предложения (вроде идеи с мутабельными сообщениями или возможности проверить существование подписки), то мы их внимательно рассмотрим. И, с большой вероятностью, реализуем. Так что есть более чем реальная возможность повлиять на развитие SO-5.

вторник, 7 ноября 2017 г.

[life] Ну, с юбилеем!

В детстве, когда празднование дня Великой Октябрьской революции еще воспринималось на полном серьезе и еще не было омрачено угаром перестройки, казалось, что 100-летний юбилей -- это очень и очень далеко. Конечно, сейчас невозможно вспомнить, о чем тогда думалось. Но, наверняка, я и представить себе не мог двух вещей. Во-первых, того, что все, что тогда было, будет благополучно просрано. И, во-вторых, что 100-летний юбилей я буду встречать, пусть и формальным, но капиталистом.

Вот такая вот история. Капиталист с грустью отмечает столетний юбилей Великой Октябрьской социалистической революции...

С праздником!

[prog.actors] Хотите решить задачу с помощью акторов? Спросите меня как! :)

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

  1. Отсутствие понимания того, что такое Модель Акторов вообще. Это, на самом-то деле, совсем не проблема. Очевидно, что всего на свете знать нельзя, а объяснить основные принципы работы Модели Акторов можно буквально на пальцах (что, кстати говоря, подтверждается практикой).
  2. Отсутствие понимания того, как эту самую Модель Акторов, принципы которой можно объяснить на пальцах, применить для решения практических задач.

Тут можно провести аналогию с молотком: понять как действовать молотком не сложно, не сложно и научить им бить. Гораздо сложнее разобраться куда же именно и с какой силой стукнуть молотком дабы получить нужный результат. Вот с Моделью Акторов, имхо, происходит тоже самое. Когда у человека есть конкретная задача, то не факт, что он может представить себе, как же ее решение будет выглядеть на акторах. Ибо понимать принцип -- это одно, а сделать декомпозицию конкретной задачи -- это другое.

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

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

Зачем это нужно мне? Очевидно, что мои цели исключительно корыстные ;) Прежде всего мне нужен материал, на основе которого можно было бы убедительно рассказывать людям о том, где применение Модели Акторов уместно, а где нет. Кстати говоря, неуместность применения Модели Акторов -- это актуальный вопрос. Бывает, что люди слушая про Модель Акторов теряют представление о том, что данная модель применима далеко не всегда. И хорошо бы уметь вовремя различать, где имеет смысл брать акторов, а где этого делать не нужно. Так же мне полезно прикидывать, насколько наш SObjectizer пригоден для решения тех или иных задач. Опыт показывает, что это сильно идет на пользу SObjectizer-у. А т.к. сам SObjectizer распространяется под BSD-лицензией (бездвоздме т.е. даром), то это пойдет на пользу и всем, кто воспользуется SObjectizer-ом.

Зачем это нужно вам? Ну мало ли :) Может вы хотите убедиться, какая все-таки гадость, эта ваша Модель Акторов, а вот вы молодец, когда придумали свое решение без использования акторов ;) Или может вы правда ломаете голову над чем-то и не прочь бы посоветоваться с умным человеком простофилей, который готов тратить свое время бесплатно. Ну или вам просто захотелось пообщаться ;)

В общем, если есть задачка и желание ее обсудить, то милости прошу. Описывайте свои задачки в комментариях к этой заметке (можно в G+), либо по почте eao197 на gmail тчк com, либо со мной можно связаться через FB, LinkedIn или Habrhabr.

PS. Запись специально повисит вверху до сентября. Но, если дело пойдет, можно будет заказать продление ;)

пятница, 3 ноября 2017 г.

[prog.c++] timertt-1.2.1

Сегодня мы выкатили небольшое обновление для нашей библиотеки для работы с таймерами -- timertt. Изменений в ней совсем мало, поэтому никаких громких анонсов мы не делаем.

Во-первых, мы добавили макрос TIMERTT_VERSION, которых хранит в себе версию библиотеки. В десятичном формате YXXXZZZ, где Y -- это мажорный номер версии, X и Z -- минорный номер и номер патча с лидирующими нулями. Т.е. версия 1.2.1 кодируется как 1002001, а версия 1.3.14 будет кодироваться как 1003014. Каюсь, такой макрос нужно было ввести еще в 1.2.0, но хорошая мысля, как говорится, приходит опосля...

Во-вторых, добавились методы reschedule, которые позволяют переназначить таймер на другое время всего одной операцией. Так, ранее нужно было делать:

auto t = tt.allocate();
tt.activate(t, std::chrono::seconds(30), []{...});
...
// Timer needs to be rescheduled.
// Deactivate it first.
tt.deactivate(t);
// Reactivate it.
tt.activate(t, std::chrono::seconds(45), []{...});

В случае, если использовался thread-safe механизм (например, такой, как timer_thread), то эта двойная операция обрабатывалась не очень эффективно -- требовалось два раза захватывать mutex.

Теперь же reschedule выполняет это все внутри себя захватив mutex всего один раз:

auto t = tt.allocate();
tt.activate(t, std::chrono::seconds(30), []{...});
...
// Timer needs to be rescheduled.
tt.reschedule(t, std::chrono::seconds(45), []{...});

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

Однако, с reschedule все не так просто, поэтому мы пока рассматриваем данную функциональность как экспериментальную. Дело в том, что если переназначаемый таймер уже активирован, то нет гарантии, что он будет успешно деактивирован. Подробнее проблемы с деактивацией таймеров описаны здесь, но вкратце суть в следующем: есть стадия обработки таймеров, когда сработавшие таймеры перемещаются в отдельное хранилище, после чего начинается вызов заданных для таймеров действий. Так вот, пока сработавший таймер находится в этом специальном хранилище, деактивировать и переактивировать его нельзя. Использование хранилища -- это цена за высокую скорость обработки таймеров и масштабируемость. Если в reschedule будет передан таймер, который сейчас находится в процессе обработки (т.е. он уже в специальном хранилище), то reschedule выбросит исключение.

Поэтому reschedule следует использовать с большой осторожностью. Например, достаточно безопасно вызывать reschedule при работе с однопоточными timer_manager-ами. Там вы сами определяете, когда вы вызываете process_expired_timers. Соответственно, если вы находитесь вне process_expired_timers, то reschedule вызывать безопасно. А вот внутри process_expired_timers, т.е. внутри таймерного события, reschedule вызывать нельзя.

Так что еще раз: при работе с reschedule нужно проявлять двойную осмотрительность.

Вообще, в timertt с самого начала существует рекомендация: вместо реактивации таймеров лучше создавать таймеры заново. Т.е. сперва вы вызваете deactivate для старого таймера, затем создаете новый таймер и вызываете для него activate. С учетом того, что timertt может поддерживать темп активации в несколько миллионов таймеров в секунду, мы считаем, что это приемлемый подход. Однако, если кому-то приходится сталкиваться с ситуациями, когда прямо внутри deactivate нужно точно знать, что таймер полностью деактивирован (может быть даже он успел сработать прямо внутри deactivate), то дайте знать. Будем думать, как это побороть. Но не бесплатно. Ну, в том смысле, что это не сможет не сказаться на скорости работы timertt. Хотя, если кто-то возьмется проспонсировать такую доработку, мы тоже не откажемся ;)

среда, 1 ноября 2017 г.

[life.cinema] Очередной кинообзор (2017/10)

Прошел очередной месяц и настало время публиковать список просмотренных фильмов. Как обычно, вначале то, что понравилось больше, затем то, что понравилось меньше. Ну и несколько слов о двух фильмах вне списка в качестве бонуса :)

Джунгли (Jungle, 2017). Не являюсь большим любителем приключенческих фильмов, да и давно не попадалось ничего достойного на эту тему. Но вот "Джунгли" посмотрел с удовольствием. Пожалуй, первый фильм, в котором Дэниэл Рэдклифф у меня не ассоциировался с Гарри Потером.

Авантюристы (The Adventurers, 2017). Простенько, незамысловато, но для развлекательного боевичка -- как раз то, что нужно. Отличный фильм, чтобы отключить мозги и расслабиться.

Сделано в Америке (American Made, 2017). Не фанат байопиков. Так что этот фильм, хоть и сделан качественно, но не зацепил. Единственно, что меня действительно впечатлило, так это то, с какой иронией в американском фильме показаны махинации ЦРУ в Центральной Америке в 1980-е годы. Вот уж, действительно: самое ужасное в советской пропаганде было то, что она говорила правду. Забавно получать подтверждение этому из продукции Голливуда.

Зеленая комната (Green Room, 2015). Более чем скромненько, но, на удивление, атмосферненько и почти что смотрибельно. Мне не хватило логики в поведении злодеев и кровищи в происходящих разборках. Но, если другого выбора нет, то можно глянуть.

Овердрайв (Overdrive, 2017). Фильм явно на аудиторию лет на 30 помладше меня: благородные и остроумные грабители, лихие парни, красивые девушки, крутые тачки, погони по горным серпантинам. При полном отсутствии реалистичности происходящего. Подросткам, наверное, понравится.

Водила (Wheelman, 2017). Как-то уже не первый ловлю себя на одинаковом впечатлении от фильмов Netflix: замах на рубль, а удар... Ну так себе удар. И этот фильм не исключение. Вроде как по ходу дела все было вполне себе смотрибельно и увлекательно, но потом остаешься в недоумении -- а что же это все было? Как-то логические концы у меня не связались и это испортило впечатление о фильме.

Обет молчания (Acts of Vengeance, 2017). Сильно так себе. Не покидало ощущение, что стареющий Антонио Бандерас пытается проделать тот же фокус, который получился у Лиама Нисона: стать брутальной звездой боевиков на шестом десятке. Только у Нисона с первой "Заложницей" это получилось на отлично, а вот у Бандероса с его последними фильмами как-то не очень.

Планета обезьян: Война (War for the Planet of the Apes, 2017). Наконец-то засмотрел. Потерянное время. Снято красиво, конечно же. Но какой же бред! Можно посмотреть только для того, чтобы постоянно стебаться с происходящего на экране.


Отдельно хочу пройтись по двум фильмам, которые не стал включать в общий обзор.

Бегущий по лезвию 2049 (Blade Runner 2049). Как по мне, так это фильм, который не следовало снимать. И не следовало бы смотреть, если первый Blade Runner оставил сильные впечатления. Первый фильм, в свое время, сильно разрывал шаблоны, во-первых, своей визуальной составляющей (которая по тем временам была фантастикой, да и сейчас еще вполне себе смотрится). Во-вторых, сюжетом, который в те времена буквально пленял, т.к. компьютеры и роботы -- это был манящее далекое будущее. В-третьих, отлично показанными характерными героями (особенно мне понравился фрик-ботаник Дж.Ф.Себастиан со своими домашними роботами). Ну и, в-четвертых, конечно же, волшебный саундрек Вангелиса. В новом фильме ничего этого нет. По крайней мере для меня.

Тачки 3 (Cars 3, 2017). Обычно я не включаю в обзоры мультфильмы. Но этот меня приятно поразил. Отличный, добрый мультик. И, как мне показалось, вовсе не детский. В общем, не ожидал, был приятно удивлен.

воскресенье, 29 октября 2017 г.

[prog.c++] Какой код на С++11/14 произвел на вас самое большое впечатление?

В процессе подготовки доклада к GECon-2017 столкнулся с необходимостью привести небольшой, но яркий пример отличия кода на C++11/14 от кода на C++98. Пока в качестве примера я хочу привести код, который наполняет std::vector несколькими значениями, копирует оттуда те элементы, которые удовлетворяют некоторому условию в другой вектор, затем результирующий вектор сортируется и отображается через std::cout. В коде на С++98 это будет сделано через функторы и итераторы. В коде на C++11/14 это уже будет с initializer lists, лямбдами, туплами и range-for.

Однако, есть подозрение, что данный пример окажется слишком объемным и невыразительным. А это не есть хорошо.

К сожалению, с хорошими примерами происходит как с анекдотами: когда очень нужно, то хрен вспомнишь. А когда вспоминаешь, то вокруг уже никого нет.

Посему обращаюсь к читателям: есть ли у вас самые яркие впечатления от знакомства с C++11/14? Вот увидели какой-то код на C++11/14 и поняли, что C++ стал другим и то, что в С++98 требовало кучи приседаний, в C++11/14 записывается легко и непринужденно. Если есть, то не сочтите за труд, поделитесь, пожалуйста.

Upd. Под катом варианты, которые есть на данный момент.

пятница, 27 октября 2017 г.

[prog.c++] Библиотека timertt обновилась до версии 1.2.0

Мы обновили свою легковесную библиотеку для работы с отложенными и периодическими таймерами (wallclock-таймеры не поддерживаются в принципе). В этой версии добавлены две важные фичи:

1. Раньше действие для таймера всегда имело тип std::function<void()>, что было гибко и удобно, но имело скрытые накладные расходы, связанные с std::function (по сути, std::function тут выступал как умный указатель для лямбд и функторов). Если от этих скрытых расходов хочется избавиться, то можно задать свой собственный тип. Например:

class operation_canceler {
    operation_manager & manager_;
    operation_id id_;
public:
    operation_canceler(operation_manager & manager, operation_id id)
        : manager_{manager}, id_{id}
    {}
    void operator()() const noexcept
    {
        manager_.cancel(id_);
    }
};
...
// Define type of timer thread which was use operation_canceler as
// a timer action type.
using my_timer_wheel_thread = timertt::timer_wheel_thread_template<
    operation_canceler,
    timertt::default_error_logger,
    timertt::default_actor_exception_handler >;
...
// Create and use this timer thread.
my_timer_wheel_thread tt;
tt.start();
...
tt.activate( std::chrono::milliseconds(750), operation_canceler{manager, current_id});

Тип должен быть Moveable и MoveConstructible. Соответственно, теперь когда создается объект-таймер, там резервируется место для пользовательского объекта-функтора. А при активации таймера пользовательский функтор мувится в этот зарезервированный кусок памяти. Тем самым не происходит дополнительных аллокаций памяти (как это временами может происходить с std::function).

2. Теперь пользователь сам может создавать объекты-таймеры на стеке или внутри других своих объектов. Ранее объекты-таймеры создавались исключительно динамически. Теперь можно избежать дополнительных аллокаций, но зато пользователь сейчас сам должен следить за тем, чтобы таймер не закончил свою жизнь раньше времени. Например:

void do_something_complex() {
    timertt::default_timer_wheel_thread tt;
    tt.start();
    ...
    timertt::default_timer_wheel_thread::scoped_timer_object timer;
    // Activate
    tt.activate(timer, std::chrono::milliseconds(250), ...);
    ...
    // Timer can be deactivated in usual way.
    tt.deactivate(timer);
    ...
    tt.shutdown_and_join();
}

Правда, в этой версии мы несколько сломали совместимость на уровне исходного кода. Поэтому номер версии 1.2.0, а не 1.1.4.

Пару слов о происхождении и назначении библиотеки. Когда-то мы долго и с удовольствием использовали большую библиотеку ACE. В том числе и тамошние таймеры (реализация которых была добротной и продвинутой). Но по мере перехода на C++11 мы постепенно отказывались от ACE и в один прекрасный момент оказалось, что из ACE нам нужны только таймеры. Чтобы не таскать дистрибутив ACE только ради таймеров, мы сделали свою легковесную header-only либу, которая базируется только на штатных возможностях C++11.

У нас timertt в работе уже года три. Проблем не замечено. Работает стабильно, может поддерживать изрядное количество таймеров (десятки и сотни миллионов). Реализует три разных таймерных механизма: wheel, heap и list, каждый из которых хорош в своей ситуации.

Предыдущие версии timertt могли работать и с компиляторами, которые не очень хорошо поддерживали C++11 (в частности, VS2013). Начиная с 1.2.0 мы на такие компиляторы уже не оглядываемся. Нужно что-то более-менее нормальное (gcc 4.8-7.2, clang 3.5-5.0, vs2015/2017). Однако, основная часть кода пока еще под все возможности C++ (вроде noexcept и constexpr там, где это разумно) еще не адаптирована. Сделаем это со временем.

Новые фичи были только-только добавлены. Наверняка что-то можно улучшить и сделать удобнее. Это мы так же сделаем со временем, а если будет положительный фидбэк, то это произойдет быстрее.

Архивы с исходниками библиотеки можно найти здесь. Сами исходники живут здесь. Документация здесь.

суббота, 21 октября 2017 г.

[prog.memories] С++ с 1985-го по 2017: краткая ретроспектива

В процессе подготовки доклада к GECon-2017 раскопал небольшой список основных, на мой взгляд, вех в развитии C++. Вроде как этот список впервые был написан для RSDN-а, ну и для того, чтобы искать его было проще, решил утащить в блог.

Любопытно, что если выбрать любую временную точку из истории развития C++, то в ней будет свое понятие "modern C++". Хотя у тех, кто оказался покусан Александреску и все еще находится в здравом уме и трезвой памяти, "modern C++" все-таки связан с тенденциями, которые начались в начале 2000-х именно с книги Андрея Александреску "Modern C++ Design" (хотя корни, по моему, уходят в 1992-1993, когда Алекс Степанов взялся за STL на C++). Ну и как по мне, только где-то с C++14 язык C++ стал достаточно удобным для того, чтобы описанные Александреску в 2001-ом году приемы могли бы использоваться массово. Но это мое личное мнение, никому его не навязываю.

Вот, собственно, моя краткая ретроспектива основных вех в развитии C++:

  • С++ вышел в свет в 1985-ом году, без множественного наследования, пространств имен, шаблонов и исключений;
  • в 1988-ом году в C++ добавилось множественное наследование, const-методы, protected-модификатор;
  • в 1990-ом в C++ добавили пространства имен, шаблоны и исключения. Где-то через год-полтора после этого Степанов выбрал C++ в качестве языка для своих экспериментов в области обобщенного программирования (используемые до этого Степановым Scheme и Ada оказались недостаточно(!) выразительными для этого);
  • в 1993-ом году про STL Степанова стало известно и начались работы по включению STL в стандарт C++;
  • в 1994-ом году выходит "Design and Evolution of C++", в которой Страуструп говорит о C++, как о мультпарадигменном языке программирования. И о том, что не следует относиться к C++ как к "чисто объектно-ориентированному" или "чисто процедурному" языку программирования;
  • где-то в 1994-1995-годах в C++ случайно открыли такую штуку, как template metaprogramming. Что дало старт теме программирования на C++ных шаблонах;
  • в 1998-ом году зафиксирован стандарт C++98, в котором оказался STL от Степанова (причем и сам STL был доработан, и C++ был "дотянут" до того, чтобы уметь поддерживать STL);
  • в 1999-ом году началось развитие Boost-а. В качестве полигона для новых идей для C++. Откуда затем в стандарт C++ придут shared_ptr и пр.;
  • в 2001-ом году вышла книга Александреску "Modern C++ Design", которая максимально популяризировала тему программирования на C++ных шаблонов (этой теме к тому времени уже было порядка 7 лет);
  • в 2003-ом году был зафиксирован корректирующий стандарт C++03. Приблизительно тогда же более-менее полные реализации C++98 стали доступны на большинстве платформ;
  • 2003-й год: в Boost попадает MPL -- фреймворк для метапрограммирования на шаблонах;
  • в 2003-ом году в свет выходит LLVM, проект, который затем попадет под крыло Apple и приведет к появлению clang;
  • 2004-2005-й годы: Boost становится двигателем новых библиотек в стиле Modern C++, изрядная часть Boost-а представляет из себя header-only библиотеки шаблонов;
  • в 2007-ом году появляется первая публичная версия компилятора clang. Который стал очень быстро развиваться и быстро стал основным компилятором для платформ от Apple, затем для FreeBSD и, позднее, для Android-а. Появление clang-а очень сильно подстегнуло развитие других мейнстримовых компиляторов, в первую очередь GCC и MSVC;
  • 2011-й год: стандарт C++11. Целая куча нововведений, расширяющих возможности шаблонов и метапрограммирования: variadic templates, constexpr, auto, decltype, ...;
  • 2014-й год: стандарт C++14. Еще больше возможностей для шаблонов и метапрограммирования, в частности, снятие ряда ограничений для constexpr, более простой auto для функций;
  • 2015-2016: появление библиотек вроде Boost.Hana;
  • 2017-й: зафиксирован драфт стандарта С++17, значительная его часть уже доступна в GCC и Clang, часть проектов уже активно использует C++17 в продакшене.

Если вы выделяете какие-то другие вехи в развитии C++, то не сочтите за труд поделиться в комментариях. Ну, например, появление такой штуки, как expression templates, библиотека MFC, начало использования C++ в разработке операционных систем Windows и BeOS, библиотека Qt, среда KDE, проект LLVM, решение о переходе на C++ в GCC и т.д.

четверг, 19 октября 2017 г.

[prog.c++] Буду выступать на GECon-2017

Компания EPAM проводит вторую большую ИТ-конференцию у нас в Гомеле: GECon-2017.

Я там собираюсь сделать доклад на тему "C++ -- монстр, которого никто не любит, но который всех переживет". Где собираюсь рассказать о том, как C++ стал мейнстримом, как он развивался, к чему пришел, где применяется, какое будущее его ждет и как C++ выглядит на фоне имеющихся конкурентов (в первую очередь C, D, Go, Rust).

В общем, к чему я это? А к двум вещам:

Во-первых, если кто-то еще не слышал про проведение GECon-2017 у нас в городе, то теперь вы знаете. Имеет смысл прийти и послушать. В прошлом году было более чем любопытно, и сама конференция была организована очень хорошо.

Во-вторых, если кто-то поделится какими-то интересными примерами использования C++ или интересными примерами того, как современный C++ упростил вам работу, то поделитесь, пожалуйста. Не сочтите за труд. У меня есть свои примеры, конечно же, но все равно чем больше таких примеров будет перед глазами, тем интереснее получится доклад. Ну вот, например, несколько лет назад было интересно узнать, что Dropbox стал активно использовать C++ для разработки мобильных приложений. Выгода здесь в том, что ядро приложение пишется всего один раз и остается общим для всех платформ, а уже GUI-часть навешивается своя для каждой платформы. Или другой пример: на одной из CppCon (вроде бы 2015-го года) был доклад о использовании C++ на больших вычислительных кластерах для расчета прогнозов погоды. Вот за такого рода примеры я буду сильно признателен.

Как, кстати говоря, и обратным примерам. Типа того, что вот была система на C++ и все просто замучались ее поддерживать, потом посадили 3-х вчерашних студентов и они все за месяц переписали на Go, после чего волосы у всех стали мягкими и шелковистыми, а стул нормализовался... ;) Серьезно, на C++ я давно смотрю без розовых очков и хочу сделать более-менее объективый доклад, а не агитку о том, как же все круто в C++ (на самом деле нет).