• [sobjectizer] Можно ли написать один обработчик сразу для нескольких типов сообщений? И если нет, то как быть?

      Сегодняшняя статья написана по следам недавнего вопроса, который можно сформулировать следующим образом: "Можно ли в SObjectizer написать обработчик, который бы обрабатывал сразу нескольких типов сообщений?"

      Вопрос интересный.

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

      Если изображения передаются в виде SObjectizer-овских сообщений, а блоками обработки являются SObjectizer-овские агенты, то можно ли сделать как-то так:

      Читать далее
    • Проект arataga: реальный пример использования SObjectizer и RESTinio для работы с большим количеством HTTP-соединений

        В последние 4.5 года я много рассказывал на Хабре про такие OpenSource проекты, как SObjectizer и RESTinio. Но вот об использовании SObjectizer и/или RESTinio в реальных проектах пока еще ни разу не удавалось поговорить (была лишь одна статья от стороннего автора).

        Причина простая: мы не можем обсуждать те проекты, в которых мы сами применяли SObjectizer/RESTinio, ибо NDA. Равно как и не можем рассказывать о тех чужих проектах, о которых узнали в частном общении. Так что с наглядными примерами использования SObjectizer/RESTinio в реальной жизни всегда была напряженка.

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

        К счастью или к несчастью, но далеко не самый удачный 2020-й год предоставил нам возможность показать как же выглядит реальный проект, в разработке которого SObjectizer и RESTinio активно используются. И в данной статье я попробую рассказать о том, как и для чего SObjectizer и RESTinio применяются в arataga, исходники которого можно найти на GitHub.

        Читать далее
      • RESTinio-0.6.13: последний большой релиз RESTinio в 2020 и, вероятно, последний в ветке 0.6


          RESTinio — это относительно небольшая C++14 библиотека для внедрения HTTP/WebSocket сервера в C++ приложения. Мы старались сделать RESTinio простой в использовании, с высокой степенью кастомизации, с приличной производительностью. И, вроде бы, пока что это получается.


          Ранее здесь уже были статьи про RESTinio, но в них речь больше шла о том, что и как было сделано в потрохах библиотеки. Сегодня же хочется рассказать о том, что появилось в свежей версии RESTinio, и зачем это появилось. А так же сказать несколько слов о том, почему этот релиз, скорее всего, станет последним большим обновлением в рамках ветки 0.6. И о том, чего хотелось бы достичь при работе над веткой 0.7.


          Кому интересно, милости прошу под кат.

          Читать дальше →
        • Не хочется ждать в очереди? Напишем свой диспетчер для SObjectizer с приоритетной доставкой


            SObjectizer — это небольшой фреймворк для C++, который дает возможность разработчику использовать такие подходы, как Actor Model, Communicating Sequential Processes и Publish/Subscribe.


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


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


            Сегодня мы еще раз поговорим об этом. На примере уже другой задачи. Да и реализация будет отличаться, поскольку за прошедшее время SObjectizer успел обновиться сперва до версии 5.6, а затем и 5.7. И в этих версиях много отличий от версии 5.5, про которую в основном и рассказывалось в прошлом. В том числе и в механизме диспетчеров.


            О решаемой задаче в двух словах


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


            Сообщения msg_status могут идти большим потоком. Например, на одно msg_result может приходиться до 1000 msg_status. И нам бы хотелось, чтобы когда в очереди уже стоит 900 сообщений msg_status, новое сообщение msg_result вставало не в конец очереди, а в самое ее начало. Чтобы msg_result не ждало, пока разгребутся 900 старых msg_status.

            Читать дальше →
          • Новая функциональность в RESTinio и опять с помощью C++ных шаблонов

              Увидело свет очередное обновление небольшой библиотеки для встраивания асинхронного HTTP-сервера в C++ приложения: RESTinio-0.6.12. Хороший повод рассказать о том, как в этой версии с помощью C++ных шаблонов был реализован принцип "не платишь за то, что не используешь".



              Заодно в очередной раз можно напомнить о RESTinio, т.к. временами складывается ощущение, что многие C++ники думают, что для встраивания HTTP-сервера в современном C++ есть только Boost.Beast. Что несколько не так, а список существующих и заслуживающих внимания альтернатив приведен в конце статьи.


              О чем речь пойдет сегодня?


              Изначально библиотека RESTinio никак не ограничивала количество подключений к серверу. Поэтому RESTinio, приняв очередное новое входящее подключение, сразу же делала новый вызов accept() для принятия следующего. Так что если вдруг на какой-то RESTinio-сервер придет сразу 100500 подключений, то RESTinio не заморачиваясь постарается принять их все.


              На такое поведение до сих пор никто не жаловался. Но в wish-list-е фича по ограничению принимаемых подключений маячила. Вот дошли руки и до нее.


              В реализации были использованы C++ные шаблоны, посредством которых выбирается код, который должен или не должен использоваться. Об этом-то мы сегодня и поговорим.

              Читать дальше →
              • +13
              • 1.5k
              • 9
            • can_throw или не can_throw?


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


                К сожалению, далеко не везде исключения можно задействовать. Во-первых, исключения не бесплатны и, во-вторых, не всякий код способен "пережить" возникновение исключений.


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


                По большому счету, у нас в распоряжении есть только спецификатор noexcept. Штука полезная, конечно, но недостаточная.


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

                Читать дальше →
              • Сколько кода на C++ нужно написать для разбора HTTP-заголовка Authorization с помощью easy_parser из RESTinio?


                  Мы продолжаем развивать бесплатный и открытый встраиваемый в С++ приложения HTTP-сервер RESTinio. В реализации RESTinio активно используются C++ные шаблоны, о чем мы здесь регулярно рассказываем (недавний пример).


                  Одной из точек приложения C++ной шаблонной магии стал easy_parser, небольшая реализация нисходящего рекурсивного парсера на базе PEG. Easy_parser был добавлен в RESTinio в прошлом году для того, чтобы упростить работу с HTTP-заголовками.


                  Мы уже немного обсуждали easy_parser-е в предыдущей статье. А сегодня хочется показать как же easy_parser применяется при разработке RESTinio. На примере разбора содержимого HTTP-заголовка Authorization. Попробуем, так сказать, заглянуть в потроха RESTinio.


                  Грамматика Authorization


                  Структура заголовка Authorization определена в RFC7235 следующим образом:

                  Читать дальше →
                • Продолжаем упарываться многоэтажными С++ными шаблонами в RESTinio: безопасная по типам альтернатива express-js роутеру


                    RESTinio, наш небольшой встраиваемый HTTP-сервер, продолжает развиваться. Одной из отличительных особенностей RESTinio является то, что в его реализации активнейшим образом используются многоэтажные C++ные шаблоны (о чем уже рассказывалось ранее: 1, 2).


                    C++ные шаблоны в RESTinio задействованы не ради любви к искусству, а потому, что именно шаблоны являются основным способом достижения главной цели, преследуемую при разработке RESTinio: получить удобный в использовании и гибко настраиваемый инструмент, который был бы при этом и достаточно производительным.


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


                    easy_parser_router как альтернатива express-router-у


                    express-router и что с ним не так?


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

                    Читать дальше →
                    • +19
                    • 2.1k
                    • 9
                  • Что нового в SObjectizer-5.7.0 и ждет этот проект дальше?

                      SObjectizer — это относительно небольшой C++17 фреймворк, который позволяет использовать в С++ программах такие подходы, как Actor Model, Publish-Subscribe и Communicating Sequential Processes (CSP). Что существенно упрощает разработку сложных многопоточных приложений на C++. Если читатель в первый раз слышит о SObjectizer-е, то составить впечатление о нем можно по этой презентации, или из этой уже достаточно старой статьи.


                      Вообще говоря, подобных открытых, все еще живых и все еще развивающихся инструментов для C++ не так уж и много. Можно вспомнить разве что QP/C++, CAF: C++ Actor Framework, actor-zeta и совсем молодой еще проект rotor. Выбор есть, но не сказать, что большой.


                      Недавно стала доступна очередная "мажорная" версия SObjectizer-а, где наконец-то появилась штука, о которой разговоры ходили давно, и к реализации которой я несколько раз безуспешно подступался. Можно сказать, что достигнута знаковая веха. Это также повод, чтобы рассказать о том, что ждет SObjectizer после релиза версии 5.7.0.


                      Поддержка send_case в select()


                      Итак, самое важное нововведение, которое появилось в v.5.7.0 и ради которого даже сломана совместимость с вышедшей в прошлом году v.5.6 (а совместимость мы просто так не ломаем) — это поддержка send_case в функции select(). Что сделало SObjectizer-овский select() гораздо более похожим на select из языка Go. Теперь посредством select() можно не только читать сообщения из нескольких CSP-шных каналов, но и отсылать исходящие сообщения в те каналы, которые оказались готовы для записи.

                      Читать дальше →
                      • +15
                      • 1.8k
                      • 7
                    • noexcept-ctcheck или несколько простых макросов, чтобы компилятор помогал при написании noexcept кода

                        При разработке на C++ время от времени приходится писать код, в котором исключения не должны возникать. Например, когда нам нужно написать не бросающий исключений swap для собственных типов или определить noexcept move-оператор для своего класса, или вручную реализовать нетривиальный деструктор.


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


                        Например, если у меня есть вот такие типы и функции:


                        class first_resource {...};
                        class second_resource {...};
                        
                        void release(first_resource & r) noexcept;
                        void close(second_resource & r);

                        и есть некий класс resources_owner, который владеет объектами типа first_resource и second_resource:


                        class resources_owner {
                           first_resource first_resource_;
                           second_resource second_resource_;
                           ...
                        };

                        то я могу написать деструктор resources_owner следующим образом:


                        resources_owner::~resources_owner() noexcept {
                           // Функция release() не бросает исключений, поэтому просто вызываем ее.
                           release(first_resource_);
                        
                           // А вот функция close() может бросать исключения, поэтому
                           // обрамляем ее try-catch.
                           try{ close(second_resource_); } catch(...) {}
                        }

                        В каком-то смысле noexcept в C++11 сделал жизнь C++ разработчика легче. Но у текущей реализации noexcept в современном C++ есть одна неприятная сторона...


                        Компилятор не помогает контролировать содержимое noexcept функций и методов

                        Читать дальше →
                      • Усложнение C++ неизбежно. И не только C++

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


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


                          Язык программирования — это технологичный продукт, но не все так просто


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


                          Один из самых ярких примеров: цифровая фотография, которая в 1990-х была вообще никакой, но спустя всего 20 лет привела к краху такого монстра XX-го века, как Kodak (который, кстати говоря, первым и сделал прототип цифровой камеры).


                          image
                          Читать дальше →
                        • RESTinio — это асинхронный HTTP-сервер. Простой пример из практики: отдача большого объема данных в ответ


                            Недавно мне довелось поработать над приложением, которое должно было контролировать скорость своих исходящих подключений. Например, подключаясь к одному URL приложение должно было ограничить себя, скажем, 200KiB/sec. А подключаясь к другому URL — всего 30KiB/sec.


                            Самым интересным моментом здесь оказалось тестирование этих самых ограничений. Мне потребовался HTTP-сервер, который бы отдавал трафик с какой-то заданной скоростью, например, 512KiB/sec. Тогда бы я мог видеть, действительно ли приложение выдерживает скорость 200KiB/sec или же оно срывается на более высокие скорости.


                            Но где взять такой HTTP-сервер?


                            Поскольку я имею некоторое отношение к встраиваемому в С++ приложения HTTP-серверу RESTinio, то не придумал ничего лучше, чем быстренько набросать на коленке простой тестовый HTTP-сервер, который способен отдавать клиенту длинный поток исходящих данных.


                            О том, насколько это было просто и хотелось бы рассказать в статье. Заодно узнать в комментариях, действительно ли это просто или же я сам себя обманываю. В принципе, данную статью можно рассматривать как продолжение предыдущей статьи про RESTinio под названием "RESTinio — это асинхронный HTTP-сервер. Асинхронный". Посему, если кому-то интересно прочитать о реальном, пусть и не очень серьезном применении RESTinio, то милости прошу под кат.

                            Читать дальше →
                          • A declarative data-processing pipeline on top of actors? Why not?

                              Some time ago, in a discussion on one of SObjectizer's releases, we were asked: "Is it possible to make a DSL to describe a data-processing pipeline?" In other words, is it possible to write something like that:


                              A | B | C | D


                              and get a working pipeline where messages are going from A to B, and then to C, and then to D. With control that B receives exactly that type that A returns. And C receives exactly that type that B returns. And so on.


                              It was an interesting task with a surprisingly simple solution. For example, that's how the creation of a pipeline can look like:


                              auto pipeline = make_pipeline(env, stage(A) | stage(B) | stage(C) | stage(D));

                              Or, in a more complex case (that will be discussed below):


                              auto pipeline = make_pipeline( sobj.environment(),
                                      stage(validation) | stage(conversion) | broadcast(
                                          stage(archiving),
                                          stage(distribution),
                                          stage(range_checking) | stage(alarm_detector{}) | broadcast(
                                              stage(alarm_initiator),
                                              stage( []( const alarm_detected & v ) {
                                                      alarm_distribution( cerr, v );
                                                  } )
                                              )
                                          ) );

                              In this article, we'll speak about the implementation of such pipeline DSL. We'll discuss mostly parts related to stage(), broadcast() and operator|() functions with several examples of usage of C++ templates. So I hope it will be interesting even for readers who don't know about SObjectizer (if you never heard of SObjectizer here is an overview of this tool).

                              Read more →
                            • Just take a look at SObjectizer if you want to use Actors or CSP in your C++ project


                                A few words about SObjectizer and its history


                                SObjectizer is a rather small C++ framework that simplifies the development of multithreaded applications. SObjectizer allows a developer to use approaches from Actor, Publish-Subscribe and Communicating Sequential Processes (CSP) models. It's an OpenSource project that is distributed under BSD-3-CLAUSE license.


                                SObjectizer has a long history. SObjectizer itself was born in 2002 as SObjectizer-4 project. But it was based on ideas from previous SCADA Objectizer that was developed between 1995 and 2000. SObjectizer-4 was open-sourced in 2006, but its evolution was stopped soon after that. A new version of SObjectizer with the name SObjectizer-5 was started in 2010 and was open-sourced in 2013. The evolution of SObjectizer-5 is still in progress and SObjectizer-5 has incorporated many new features since 2013.


                                SObjectizer is more or less known in the Russian segment of the Internet, but almost unknown outside of the exUSSR. It's because the SObjectizer was mainly used for local projects in exUSSR-countries and many articles, presentations, and talks about SObjectizer are in Russian.


                                A niche for SObjectizer and similar tools


                                Multithreading is used in Parallel computing as well as in Concurrent computing. But there is a big difference between Parallel and Concurrent computing. And, as a consequence, there are tools targeted Parallel computing, and there are tools for Concurrent computing, and they are different.

                                Read more →
                              • Достраиваем в RESTinio четвертый этаж из C++ных шаблонов. Зачем и как?

                                  RESTinio — это относительно небольшой проект, представляющий из себя встраиваемый в C++приложения асинхронный HTTP-сервер. Его характерной особенностью является широкое, можно сказать, повсеместное применение C++ных шаблонов. Как в реализации, так и в публичном API.


                                  C++ные шаблоны в RESTinio используются настолько активно, что первая статья, которая рассказывала о RESTinio на Хабре, называлась "Трехэтажные C++ные шаблоны в реализации встраиваемого асинхронного HTTP-сервера с человеческим лицом".


                                  Трехэтажные шаблоны. И это, в общем-то, была не фигура речи.


                                  А недавно мы в очередной раз обновили RESTinio и для добавления новой функциональности в версию 0.5.1 пришлось сделать "этажность" шаблонов еще выше. Так что местами C++ные шаблоны в RESTinio уже четырехэтажные.



                                  И если кому-то интересно зачем нам такое потребовалось и как мы шаблоны использовали, то оставайтесь с нами, под катом будет немного подробностей. Матерые C++ гуру вряд ли найдут для себя что-нибудь новое, а вот менее продвинутые C++ники смогут посмотреть на то, как шаблоны применяются для вставки/изъятия кусков функциональности. Почти что в "дикой природе".

                                  Читать дальше →
                                • SObjectizer-5.6.0: режем по живому, чтобы расти дальше


                                    Третьего дня стала доступна новая версия SObjectizer-а: 5.6.0. Ее главная особенность — это отказ от совместимости с предыдущей стабильной веткой 5.5, поступательно развивавшейся на протяжении четырех с половиной лет.


                                    Основные принципы работы SObjectizer-5 остались прежними. Сообщения, агенты, кооперации и диспетчеры все еще с нами. Но что-то серьезно изменилось, что-то вообще было выброшено. Поэтому просто взять SO-5.6.0 и перекомпилировать свой код уже не получится. Что-то потребуется переписать. Что-то, возможно, придется перепроектировать.


                                    Почему мы несколько лет заботились о совместимости, а потом решились взять и все поломать? И что поломали наиболее основательно?


                                    Об этом я и попробую рассказать в данной статье.


                                    Зачем вообще потребовалось что-то ломать?


                                    Тут как раз все просто.

                                    Читать дальше →
                                  • RESTinio — это асинхронный HTTP-сервер. Асинхронный

                                      Пару лет назад мы опубликовали RESTinio — свой небольшой OpenSource C++фреймворк для встраивания HTTP-сервера в C++ приложения. Мегапопулярным за это время RESTinio не стал, но и не потерялся. Кто-то выбирает его за "родную" поддержку Windows, кто-то за какие-то отдельные фичи (вроде поддержки sendfile), кто-то за соотношение возможностей, простоты использования и настраиваемости. Но, думаю, изначально многих RESTinio привлекает вот этим лаконичным "Hello, World"-ом:


                                      #include <restinio/all.hpp>
                                      int main()
                                      {
                                          restinio::run(
                                              restinio::on_this_thread()
                                              .port(8080)
                                              .address("localhost")
                                              .request_handler([](auto req) {
                                                  return req->create_response().set_body("Hello, World!").done();
                                              }));
                                          return 0;
                                      }

                                      Это, действительно, все, что нужно чтобы запустить HTTP-сервер внутри C++ приложения.


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


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

                                      Читать дальше →
                                      • +18
                                      • 6.9k
                                      • 8
                                    • С сожалением об отсутствии в C++ полноценного static if или…

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


                                        Когда-то, уже довольно давно, язык D начали делать как "правильный C++" с учетом накопившегося в C++ опыта. Со временем D стал не менее сложным и более выразительным языком, чем C++. И уже C++ стал подсматривать за D. Например, появившийся в C++17 if constexpr, на мой взгляд, — это прямое заимствование из D, прототипом которому послужил D-шный static if.


                                        К моему сожалению, if constexpr в С++ не обладает такой же мощью, как static if в D. Тому есть свои причины, но все-таки бывают случаи, когда остается только пожалеть, что if constexpr в C++ не позволяет управлять наполнением C++ного класса. Об одном из таких случаев и хочется поговорить.


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


                                        Задача, которую требуется решить


                                        Требуется создать хитрый вариант "умного указателя" для хранения объектов-сообщений. Чтобы можно было написать что-то вроде:

                                        Читать дальше →
                                      • Немного C++ной шаблонной магии и CRTP для контроля за корректностью действий программиста в компайл-тайм

                                          Недавно, работая над новой версией SObjectizer-а, довелось столкнуться задачей контроля в компайл-тайм действий разработчика. Суть была в том, что ранее программист мог делать вызовы вида:


                                          receive(from(ch).empty_timeout(150ms), ...);
                                          receive(from(ch).handle_n(2).no_wait_on_empty(), ...);
                                          receive(from(ch).empty_timeout(2s).extract_n(20).stop_on(...), ...);
                                          receive(from(ch).no_wait_on_empty().stop_on(...), ...);

                                          Операция receive() требовала набор параметров, для указания которых использовались цепочки методов, вроде показанных выше from(ch).empty_timeout(150ms) или from(ch).handle_n(2).no_wait_on_empty(). При этом вызов методов handle_n()/extract_n(), ограничивающих количество извлекаемых/обрабатываемых сообщений, был необязательным. Поэтому все показанные выше цепочки были корректными.


                                          Но в новой версии потребовалось заставить пользователя обязательно явно указывать количество сообщений для извлечения и/или обработки. Т.е. цепочка вида from(ch).empty_timeout(150ms) теперь становилась некорректной. Её следовало заменить на from(ch).handle_all().empty_timeout(150ms).


                                          Причем хотелось сделать так, чтобы именно компилятор бил бы программиста по рукам, если программист забыл сделать вызов handle_all(), handle_n() или extract_n().


                                          Может ли C++ помочь в этом?


                                          Да. И если кому-то интересно как именно, то милости прошу под кат.

                                          Читать дальше →
                                          • +16
                                          • 3.7k
                                          • 7
                                        • «Современные» обедающие философы на C++ посредством акторов и CSP

                                            Некоторое время назад ссылка на статью "Modern dining philosophers" распространилась по ресурсам вроде Reddit и HackerNews. Статья интересная, она показывает несколько решений этой известной задачи, реализованных на современном C++ с использованием task-based подхода. Если кто-то это статью еще не читал, то имеет смысл потратить время и прочесть ее.


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


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


                                            Посему попробовал посмотреть и реализовал несколько решений этой задачи как с использованием Акторов, так и с использованием CSP. Код этих решений можно найти в репозитории на GitHub-е. А под катом пояснения и объяснения, так что кому интересно, милости прошу под кат.

                                            Читать дальше →