вторник, 28 января 2020 г.

[prog.c++] Перевел демо-проект so5-dining-philosophers на свежие версии SObjectizer, so5extra, fmtlib

Год назад на Хабре была опубликована большая статья "«Современные» обедающие философы на C++ посредством акторов и CSP", в которой рассматривалось несколько реализаций решения задачи "Обедающих философов" на SObjectizer (как на базе агентов, так и на базе голых нитей с mchain-ами).

За прошедшее время многое поменялось: вышли новые версии SObjectizer-а (5.6 и 5.7) несовместимые с SO-5.5, на котором были написаны примеры для статьи. А Atlassian принял решение удалить в 2020-ом году с BitBucket-а все Mercurial репозитории. Эта участь ожидает и исходный репозиторий, в котором были собраны примеры кода для статьи.

Так что этот демо-проект подвергся модернизации. Во-первых, он переехал на GitHub: so5-dining-philosophers. Во-вторых, код был переведен на свежие версии зависимостей: SObjectizer-5.7.0, so5extra-1.4.0 и fmtlib-6.1.2.

Поэтому теперь для so5-dining-philosophers нужен C++17. Старая версия под C++14 и SO-5.5 доступа под тегом 20190129.

Несколько слов про адаптацию старых решений под новый SObjectizer:

  • потребовалось исправить сигнатуру метода state_watcher_t::changed. Этот метод в SO-5.6/5.7 должен быть noexcept. В данном демо-примере noexcept означает не то, что changed() не будет бросать исключений, а то, что нет возможности продолжить работу, если исключение все-таки выскочило, поэтому нужно грохнуть все через std::terminate;
  • потребовалось исправить сигнатуру метода do_deliver_message в собственном типе mbox-а. В SO-5.6/5.7 этот метод уже не помечен как const, а в SO-5.5 эта отметка долго сохранялась по соображениям совместимости;
  • пришлось изменить подписку у некоторых агентов. Ранее использовалась нотация state.event<Signal>([]{...}), теперь она не поддерживается и нужно использовать унифицированный вариант: state.event([](mhood_t<Signal>){...}). Это было одним из ломающих совместимость изменений в SO-5.6;
  • в нескольких вызовах receive для чтения входящих сообщений из mchain-ов потребовалось указать handle_all(), поскольку SO-5.6/5.7 требуют, чтобы для receive/select было указано количество обрабатываемых сообщений (т.е. нужно вызывать handle_n/handle_all/extract_n явным образом). Контролируется это во время компиляции. О том, как этого удалось достичь была отдельная статья на Habr-е;
  • потребовалось поменять создание диспетчеров. Вместо вызовов вида create_private_disp(env)->binder() начиная с SO-5.6 нужно писать make_dispatcher(env).binder(). Собственно, это одно из принципиальных отличий SO-5.6 от SO-5.5.

В общем, перевод не занял много времени. И не потребовал каких-то серьезных усилий. Компилятор сам бил по рукам в местах, которые нужно поправить. После правок все ожидаемо завелось и поехало :)

Но важность сохранения совместимости все равно осознал. Постараюсь больше ломающих нововведений в SObjectizer не вносить и держать совместимость в рамках SO-5.7 как можно дольше.

Комментариев нет: