На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
[!] Как относитесь к модерированию на этом форуме? Выскажите свое мнение здесь
Модераторы: Qraizer
  
> SObjectizer 5.3.0
    SObjectizer -- это реализация модели акторов для C++, позволяющая программировать на C++ с использованием работающих на разных нитях агентов, общающихся между собой посредством сообщений. SObjectizer существенно упрощает разработку событийно-ориентированных приложений, для параллельной и независимой обработки событий в которых требуется многопоточность и/или распределенность. SObjectizer использовался для создания как для мелких утилит, так и серьезных распределенных приложений, работающих под большой нагрузкой в режиме 24x7.

    Сегодня состоялся один из ключевых релизов, SObjectizer 5.3.0.

    SObjectizer является Opensource проектом.

    В последние несколько лет SObjectizer развивается на SourceForge под BSD-лицензией. Версия 5.3.0 является очередным существенным шагом по наращиванию возможностей SObjectizer при одновременном упрощении его использования.

    В версии 5.3.0 произведены значительные улучшения:
    * добавлена возможность организации синхронного взаимодействия агентов: инициатор запроса может синхронно ожидать результата на объекте std::future, в то время как обработчик запроса работает обычным образом на своей рабочей нити;
    * более активно используются лямбда-функции, введенные в C++11. Например, теперь обработчики событий могут быть заданы посредством лямбда-функций, что позволяет уменьшить объем кода агентов;
    * добавлена возможность создавать ad-hoc агентов, формируя агента из лямбда-функций, а не описывая отдельный, унаследованный от so_5::rt::agent_t, класс;
    * доработана модель реагирования на выпущенные из обработчиков событий исключения.

    Эта версия так же содержит несколько более мелких исправлений, улучшений, доработок и примеров.

    Традиционный пример “Hello, World” теперь может быть записан вот так:

    ExpandedWrap disabled
      so_5::api::run_so_environment(
        []( so_5::rt::so_environment_t & env ) {
          auto coop = env.create_coop( “hello” );
          coop->define_agent().on_start( [&env]() {
            std::cout << “Hello, World” << std::endl;
            env.stop();
          } );
          env.register_coop( std::move( coop ) );
        } );

    А более интересный пример ping_pong, где каждый агент работает на контексте своей собственной нити, вот так:

    ExpandedWrap disabled
      int pings_left = 10000;
      so_5::api::run_so_environment(
        [&pings_left]( so_5::rt::so_environment_t & env )
        {
          struct msg_ping : public so_5::rt::signal_t {};
          struct msg_pong : public so_5::rt::signal_t {};
       
          auto mbox = env.create_local_mbox();
          auto coop = env.create_coop( “ping_pong”,
             so_5::disp::active_obj::create_disp_binder( “active_obj” ) );
          coop->define_agent()
            .on_start( [mbox]() { mbox->deliver_signal< msg_ping >(); } )
            .on_event( mbox, so_5::signal< msg_pong >,
              [&pings_left, &env, mbox]() {
                if( --pings_left > 0 )
                  mbox->deliver_signal< msg_ping >();
                else
                  env.stop();
              } );
          coop->define_agent()
            .on_event( mbox, so_5::signal< msg_ping >,
              [mbox]() { mbox->deliver_signal< msg_pong >(); } );
          env.register_coop( std::move( coop ) );
        },
        []( so_5::rt::so_environment_params_t & params )
        {
          params.add_named_dispatcher( “active_obj”, so_5::disp::active_obj::create_disp() );
        } );


    Версия распространяется в виде сборки so-201407-00, в которую кроме SObjectzer 5.3.0 входит еще несколько SObjectizer-библиотек, предназначенных для разработки больших, распределенных приложений на основе SObjectizer, а именно:
    * so_log, служащая оберткой над ACE Logging и упрощающая логирование для агентов;
    * so_sysconf, позволяющая собирать большое приложение из маленьких кусочков, оформленных в виде dll/so-библиотек;
    * so_5_transport, оформляющая работу с TCP/IP соединениями в виде транспортных SObjectizer-агентов;
    * mbapi, являющаяся высокоуровневой библиотекой для обмена сообщениями между агентами или между компонентами распределенного приложения.

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

    Wiki-раздел SObjectizer-а на SourceForge содержит более подробную информацию как об особенностях версии 5.3.0, так и о самом SObjectizer и его основах.

    ---

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

    Сама же тема предназначена для любых вопросов, пожеланий и уточнений, которые всячески приветствуются.
      bsivko, вы - автор?
        Скажем так - числюсь в команде разработчиков.

        Если вы что-либо тут спросите, то получите ответы непосредственно от авторов.
          Цитата bsivko @
          Традиционный пример “Hello, World” теперь может быть записан вот так:

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

          Цитата bsivko @
          А более интересный пример ping_pong, где каждый агент работает на контексте своей собственной нити, вот так:

          Это всё наверное дико круто, но хотелось бы, чтоб оно выглядело менее адово.
          Сообщение отредактировано: korvin -
            Цитата korvin @
            Это всё наверное дико круто, но хотелось бы, чтоб оно выглядело менее адово.

            Например. Но, я думаю, ты согласишься, что это всё не дотягивает до нормальных акторов без сопоставления с образцом.
            IMHO, libcppa более вменяемая в этом плане. bsivko, что скажете о конкуренте?
              Цитата MyNameIsIgor @
              Но, я думаю, ты согласишься, что это всё не дотягивает до нормальных акторов без сопоставления с образцом.

              Да в принципе можно и без сопоставления, если использовать тегированые (типом) значения и автоматически кастить их в нужный тип typecase'ом или типа того. А динамику можно эмулировать автоматическим же маршаллингом/демаршаллингом. Ну, просто мне кажется это будет попроще реализовать в C++, чем сопоставление с образцом, а результат практически тот же.
                Как-то так например.
                  Цитата korvin @
                  Это всё наверное дико круто, но хотелось бы, чтоб оно выглядело менее адово.

                  Так в C++ не получится. Если хочется писать так, нужно продолжать пользоваться Go :)

                  Можно писать и не злоупортребляя возможностями C++11. Например, в рамках "C с классами".
                    Цитата eao197 @
                    Так в C++ не получится

                    Т.е. boost.fiber не существует? :lool:
                      Цитата eao197 @
                      Так в C++ не получится.

                      Выше был пример с fiber, вполне читаемый код.

                      Добавлено
                      MyNameIsIgor, тебе за что уже RO прописали? =)
                        Цитата MyNameIsIgor @
                        Но, я думаю, ты согласишься, что это всё не дотягивает до нормальных акторов без сопоставления с образцом.
                        IMHO, libcppa более вменяемая в этом плане. bsivko, что скажете о конкуренте?

                        Понятие "нормальный актер" для C++ не определено. В Erlang-е да, одна, диктуемая языком форма актеров. В Scala своя, взятая из Akka. Хотя для той же JVM Akka не единственный такой инструмент.

                        Для C++ нет эталонной реализации модели актеров. И нужен ли в С++ паттерн-матчинг из Erlang-а или Scala -- тот еще вопрос. Пока же его нет, то какой смысл его имитировать абы как? В свое время в Boost-е пытались лямбды имитировать, как по мне, так был страх и ужас.

                        Что до сравнения с libcppa, то...

                        Если брать только аспект сопоставления с образцом, то в SObjectizer-е его вообще нет. У каждого сообщения должен быть свой уникальный тип, при этом данный тип должен быть наследником от message_t или signal_t. По typeid этого типа и производится связывание обработчика с типом сообщения. В этом плане SObjectizer не идет ни в какое сравнение с libcppa.

                        Если же вообще сравнивать SO и libcppa, то libcppa выглядит как максимально близкая калька с Erlang-а. Т.е. если хочется писать на C++ в стиле Erlang-а, то libcppa может и хорош. Но больше кажется, что для C++ это не очень подходящий стиль. Могу попробовать перечислить пару мест, которые сразу бросились в глаза.

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

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

                        Очень много libcppa-специфики в коде агентов. Всякие become/unbecome и пр. Плюс тип агента, если используется наследование, нужно жестко прибивать -- event_based, sb_actor и пр. В SObjectizer агент -- это агент, контекст для него определяется диспетчером. Можно запустить агента на отдельной нити, можно с кем-нибудь еще -- он об этом особо и знать не будет. Опять же, состояния могут быть, а могут и не быть. Сегодня не нужны они агенту, он их не определяет. Через 3 года потребовались, добавили, и не нужно базовый тип для агента менять.

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

                        Общее же впечатление, как от Boost-а в свое время, когда Boost библиотеками пытался решить проблемы языка (тот же Boost.Lambda или Boost.Bind). Когда язык подкрутили, от этих вещей уже и проку нет. Вот так и libcppa -- пытается притянуть за уши то, чего в языке нет.

                        А вообще, libcppa мы не рассматриваем как конкурента. Слишком разные подходы у нас к модели актеров.
                        Пусть потенциальные пользователи сами смотрят и выбирают, что им ближе. Кому-то имитация Erlang-а на максимуме возможностей C++11. Кому-то более примитивный вариант, близкий к ООП. Ну и может кому-то будет важно, что SObjectizer поддерживает Windows "из коробки" :)

                        Добавлено
                        Цитата korvin @
                        Выше был пример с fiber, вполне читаемый код.


                        Пример с fiber не является аналогом приведенного bsivko примера ping_pong-а на SObjectizer-е.
                          Цитата korvin @
                          MyNameIsIgor, тебе за что уже RO прописали? =)

                          За пьяный дебош :D
                          Цитата eao197 @
                          Если брать только аспект сопоставления с образцом, то в SObjectizer-е его вообще нет

                          Да я заметил по if'у в ping-pong :D
                          Цитата eao197 @
                          У каждого сообщения должен быть свой уникальный тип, при этом данный тип должен быть наследником от message_t или signal_t

                          И чем обусловлено сие ограничение, при условии что
                          Цитата eao197 @
                          По typeid этого типа и производится связывание обработчика с типом сообщения

                          ?
                          Цитата eao197 @
                          В этом плане SObjectizer не идет ни в какое сравнение с libcppa

                          Да, SO тут как каменный топор по сравнению со стальным :yes:
                          Цитата eao197 @
                          Взять привязывание обработчика к типу сообщения. В libcppa это делается через явное указание всех элементов сообщения (или их части).

                          Простите, а у вас вот тут
                          ExpandedWrap disabled
                            .on_event( mbox, so_5::signal< msg_pong >

                          тип сообщения указывается как-то неявно? :wacko: Или вы про сопоставление с образцом? Да, там при привязке указывается образец. Но в случае SO всё равно будет этот код в обработчике в виде if'ов, да только сопоставление даёт структурированный код.
                          Цитата eao197 @
                          Это хорошо в коротких демо-примерах. Но когда код сопровождается годами, то типы сообщений обязательно модифицируются. Что-то добавляется, что-то убирается. Подход libcppa приведет к геморрою по поиску и замене всех нужных обработчиков. Либо же придется все равно использовать тот же самый подход, что и в SO.

                          А какая для поддержки кода половая разница как вы обрабатываете сообщения - сопоставлением с образцом или if'ами внутри обработчика? При изменении сообщения вам всё равно придётся заниматься "поиском и заменой", так что низачот.
                          Цитата eao197 @
                          Все в libcppa завязано на лямбдах.

                          На функторах, а не лямбдах.
                          Цитата eao197 @
                          Но вот как это будет в промышленном коде, который живет 10+ лет...

                          Будет жить 10+ лет...
                          Цитата eao197 @
                          Когда обработчик сообщения -- это метод класса, то с этим вообще проблем нет, обычное ООП. В libcppa же нужно будет эти методы-обработчики обрамлять лямбда-функциями.

                          bind же.
                          Цитата eao197 @
                          Очень много libcppa-специфики в коде агентов. Всякие become/unbecome и пр

                          Эммм... И что? Ну, переходят акторы в другие состояния... Вы предлагаете отказаться от этого, чтобы навелосипедить свою машину состояния и руками создать очередь сообщений? :blink:
                          Цитата eao197 @
                          Плюс тип агента, если используется наследование, нужно жестко прибивать -- event_based, sb_actor и пр. ... Опять же, состояния могут быть, а могут и не быть. Сегодня не нужны они агенту, он их не определяет. Через 3 года потребовались, добавили, и не нужно базовый тип для агента менять.

                          Ну, поменяли базовый тип, и что? Это трагедия?
                          Цитата eao197 @
                          Опять же, притянутая из Erlang-а модель связывания и мониторинга, т.е. если порожденный актором дочерний актор падает, то можно словить сигнал об этом. В C++ толку от такого механизма чуть больше чем ноль. (и далее по тексту)

                          Правильно ли я понимаю, что libcppa позволяет обработать исключение и падает приразыменовании nullptr, а SO падает в обоих случаях, и этот факт выдаётся за преимущество SO? Серьёзно?
                          Цитата eao197 @
                          Общее же впечатление, как от Boost-а в свое время, когда Boost библиотеками пытался решить проблемы языка (тот же Boost.Lambda или Boost.Bind). Когда язык подкрутили, от этих вещей уже и проку нет.

                          Да не пытались, а решали. И не убрали - bind в стандартной библиотеке. А некоторые преимущества в короткой записи boost.lambda можно увидеть в libcppa на примере guard'ов :) У вас их тоже нет, да.
                          Цитата eao197 @
                          Вот так и libcppa -- пытается притянуть за уши то, чего в языке нет

                          Мы тут пилим либу, которая притягивает в язык модель акторов, но обвиняем других :crazy:
                          Цитата eao197 @
                          А вообще, libcppa мы не рассматриваем как конкурента. Слишком разные подходы у нас к модели актеров.

                          Я не вижу разницы в подходах. Вижу разницу в продвинутости реализации - это да.
                          Цитата eao197 @
                          Ну и может кому-то будет важно, что SObjectizer поддерживает Windows "из коробки"

                          При чём здесь ОС? Речь идёт о поддержке компиляторов.
                          Цитата eao197 @
                          Пример с fiber не является аналогом приведенного bsivko примера ping_pong-а на SObjectizer-е.

                          Извините, за ручным созданием ящиков и каких-то диспетчеров активных объектов я просто не увидел разницы. В чём же она состоит?

                          Добавлено
                          D_KEY, подключайся ;)
                            Цитата MyNameIsIgor @
                            D_KEY, подключайся ;)

                            У вас итак хорошо получается, испорчу еще.
                              Цитата D_KEY @
                              У вас итак хорошо получается, испорчу еще.

                              Ну, вот, ты как всегда :yes-sad:
                                Цитата MyNameIsIgor
                                Да я заметил по if'у в ping-pong :D

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

                                Цитата MyNameIsIgor
                                И чем обусловлено сие ограничениех

                                Необходимостью хранения счетчика ссылок на экземпляр сообщения.

                                Цитата MyNameIsIgor
                                Будет жить 10+ лет...

                                Остается пожелать только, чтобы через 10+ лет сопровождением подобного кода пришлось заниматься именно вам.

                                Цитата MyNameIsIgor
                                Ну, поменяли базовый тип, и что? Это трагедия?

                                Нет. Просто не нужная работа.

                                Цитата MyNameIsIgor
                                Правильно ли я понимаю, что libcppa позволяет обработать исключение и падает приразыменовании nullptr, а SO падает в обоих случаях, и этот факт выдаётся за преимущество SO? Серьёзно?

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

                                Цитата MyNameIsIgor
                                Да не пытались, а решали. И не убрали - bind в стандартной библиотеке. А некоторые преимущества в короткой записи boost.lambda можно увидеть в libcppa на примере guard'ов :) У вас их тоже нет, да.

                                Без guard-ов жизни нет, совсем.

                                Цитата MyNameIsIgor
                                Мы тут пилим либу, которая притягивает в язык модель акторов, но обвиняем других :crazy:

                                Мы привносим в язык агентов без попытки создания нового поддиалекта языка.

                                Цитата MyNameIsIgor
                                Я не вижу разницы в подходах.

                                Как показали ваши высказывания выше, вы вообще мало чего видите.

                                Цитата MyNameIsIgor
                                Извините, за ручным созданием ящиков и каких-то диспетчеров активных объектов я просто не увидел разницы. В чём же она состоит?

                                Да у вас вообще со зрением что-то. Возьмите пример, указанный kovrin, перепишите его на Boost.Fiber и посмотрите, получится ли у вас менее адово. А потом попробуйте на тех же boost.fiber переписать пример, который bsivko привел на SObjectizer. И опять же посмотрите, будет ли это сопоставимо с кодом на Go.
                                  Цитата MyNameIsIgor @
                                  Цитата D_KEY @
                                  У вас итак хорошо получается, испорчу еще.

                                  Ну, вот, ты как всегда :yes-sad:

                                  Ну когда-то я лез в любые споры. Сейчас деградировал.

                                  Добавлено
                                  eao197, замечу, что у вас конструктива от сообщения к сообщению все меньше. "Не умеете читать C++" и пр. - не аргументы.
                                    Цитата eao197 @
                                    Вы не то что-то заметили. if там используется не для определения типа сообщения, а для проверки количества оставшихся попыток для отсылки ping-а.

                                    Именно это я и заметил. Только дело в том, что это можно решить с помощью сопоставления с образцом, как, например, здесь. Кстати, как это будет на SO?
                                    Цитата eao197 @
                                    Необходимостью хранения счетчика ссылок на экземпляр сообщения.

                                    И для чего здесь наследование от какого-то типа?
                                    Цитата eao197 @
                                    Остается пожелать только, чтобы через 10+ лет сопровождением подобного кода пришлось заниматься именно вам.

                                    Договорились :D
                                    Цитата eao197 @
                                    Нет. Просто не нужная работа.

                                    Ну, не такая большая работа, прямо скажем :)
                                    Цитата eao197 @
                                    Не правильно

                                    Ну, скажите как правильно.
                                    Цитата eao197 @
                                    Без guard-ов жизни нет, совсем.

                                    Ага, нету, как и без акторов :crazy: Я говорю не о возможности жизни, а об её облегчении.
                                    Цитата eao197 @
                                    Возьмите пример, указанный kovrin, перепишите его на Boost.Fiber и посмотрите, получится ли у вас менее адово

                                    Хорошо, попробую.
                                    Цитата eao197 @
                                    А потом попробуйте на тех же boost.fiber переписать пример, который bsivko привел на SObjectizer

                                    Там слишком много артефактов реализации/библиотеки, чтобы ясно уловить смысл. Я же попросил вас пояснить разницу.

                                    Ну, а теперь самая приятная часть ответа :D
                                    Цитата eao197 @
                                    Хотя вряд ли вы вообще что-то понимаете в C++ и последствиях таких ошибок, как деление на ноль, выход за пределы массива с перезаписью чужой памяти, обращение по неверному указателю и т.д.

                                    Цитата eao197 @
                                    Как показали ваши высказывания выше, вы вообще мало чего видите.

                                    Цитата eao197 @
                                    Да у вас вообще со зрением что-то

                                    У-тю-тю-тю-тю :lool: Раз такие переходы на личности, то всё же мои аргументы по существу.
                                    Ну, я вам так скажу: я достаточно знаю C++, чтобы не звать целого Энтони Уильямса для решения школьной задачи определения сигнаты функтора.

                                    Добавлено
                                    eao197, знаете, а я ведь давно ваш блог читаю. Даже ваши аргументы по поводу D нравятся, часто на них ссылался. А сейчас смотрю - да вы обычный... чудак ;)

                                    Добавлено
                                    Цитата D_KEY @
                                    Ну когда-то я лез в любые споры. Сейчас деградировал

                                    У тебя есть ценное качество не вызывать в оппоненте ненависть. А то вон его как понесло, крутого то нашего :lol:
                                      простите за нубский вопрос, но я так и не понял, SO работает на green threads или на обычных OS threads? если на зеленых, то как планировщик организовывает вытесняющую многозадачность между акторами?
                                        Цитата Radagast @
                                        простите за нубский вопрос, но я так и не понял, SO работает на green threads

                                        Да вы мечтатель! :D У них подход другой - нефиг тянуть в язык всякую эрланговскую хрень!

                                        Обещанный код пинг-понга на boost.fibers. С комментария соответствующего кода на Go для оценки адовости :)
                                        ExpandedWrap disabled
                                          using namespace boost::fibers;
                                           
                                          struct Ball {       //type Ball struct {
                                              int hints;      //  hits int
                                          };                  //}
                                           
                                          void player(str::string title, unbounded_queue<Ball>& table, unbounded_queue<std::string>& lose) {          //func player(title string, table chan *Ball, lose chan string) {
                                              for(Ball ball; table.pop(ball) == queue_op_status::success;) {                                          //  for ball := range table {
                                                  if(ball.hints > 0) {                                                                                //      if ball.hits > 0 {
                                                      std::cout << title << ' ' << ball.hints << std::endl;                                           //          fmt.Println(title, ball.hits)
                                                      ball.hints--;                                                                                   //          ball.hits--
                                                      table.push(ball);                                                                               //          table <- ball
                                                  } else {                                                                                            //      } else {
                                                      lose.push(title);                                                                               //          lose <- title
                                                      breal;                                                                                          //          break
                                                  }                                                                                                   //      }
                                              }                                                                                                       //  }
                                          }                                                                                                           //}
                                           
                                          int main() {                                                                                                //func main() {
                                              unbounded_queue<Ball> table;                                                                            //  table := make(chan *Ball)
                                              unbounded_queue<std::string> lose;                                                                      //  lose  := make(chan string)
                                              fiber ping { [&table, &lose] { player("ping", table, lose); } };                                        //  go player("ping", table, lose)
                                              fiber pong { [&table, &lose] { player("pong", table, lose); } };                                        //  go player("pong", table, lose)
                                           
                                              table.push(Ball{10});                                                                                   //  table <- &Ball{10}
                                              std::string title;                                                                                      //  ...
                                              lose.pop(title);                                                                                        //  ...
                                              std::cout << title << " lost" << std::endl;                                                             //  fmt.Println(<-lose, "lost")
                                                                                                                                                      //  close(table)
                                              ping.join();                                                                                            //  ...
                                              pong.join();                                                                                            //  ...
                                          }                                                                                                           //  }


                                        Добавлено
                                        Ах, да, Radagast, libcppa может работать на green threads с помощью boost.context.
                                        Сообщение отредактировано: MyNameIsIgor -
                                          Цитата
                                          Цитата eao197 @
                                          Вы не то что-то заметили. if там используется не для определения типа сообщения, а для проверки количества оставшихся попыток для отсылки ping-а.

                                          Именно это я и заметил. Только дело в том, что это можно решить с помощью сопоставления с образцом, как, например, здесь. Кстати, как это будет на SO?


                                          Решить что? Счетчик попыток -- это состояние агента. Его нужно хранить в самом агенте. Оттуда там и if.

                                          В приведенном вами примере состояние передается в сообщении. SO это было бы как-то так:
                                          ExpandedWrap disabled
                                            struct msg_step : public so_5::rt::message_t
                                            {
                                              size_t pos;
                                              msg_step( size_t a ) : pos( a ) {}
                                            }
                                             
                                            coop->define_agent()
                                              .on_start( [mbox]() { mbox->deliver_signal( new msg_step(0) ); }
                                              .on_event( [&env, mbox]( const msg_step & msg ) {
                                                if( msg.pos != array_size(animation_step) )
                                                {
                                                  draw_kirby(animation_step[msg.pos]);
                                                  env.schedule_timer( new msg_step( msg.pos+1 ), mbox, 150 );
                                                }
                                                else
                                                {
                                                  std::cout << std::endl;
                                                  env.stop();
                                                }
                                              } );


                                          Поскольку в SO нет сопоставления с образцом, он использует typeid(msg_step) для того, чтобы имея список поток сообщений понять, что именно это сообщение должно быть передано агенту. А вот на структуру сообщения SO не смотрит -- его задача доставить, а как будет разбираться с сообщением пользователь, это уже задача пользователя.

                                          Цитата
                                          Цитата eao197 @
                                          Необходимостью хранения счетчика ссылок на экземпляр сообщения.

                                          И для чего здесь наследование от какого-то типа?


                                          Ну вот libcppa создает обертку вокруг тупла неявно. В SO это делается путем наследования от базового типа.

                                          Цитата
                                          Цитата eao197 @
                                          Нет. Просто не нужная работа.

                                          Ну, не такая большая работа, прямо скажем :)


                                          Фиг знает. Я так понимаю, что наследование там не спроста сделано. Видимо, кроме наследования нужно еще что-то менять в класса. И не известно, как от этого зависят клиенты или наследники.

                                          Цитата
                                          Цитата eao197 @
                                          Не правильно

                                          Ну, скажите как правильно.


                                          Я уже все написал. Раз вы так хорошо знаете C++, как об этом думаете, то знаете, что большой класс ошибок в C++ не ловится вовремя вообще, либо же, в лучшем случае, ведет к краху всего приложения. В отличии от Erlang-а. Соответственно, в Erlang-е можно писать процесс не сильно заморачиваясь на многие вещи. А в C++ нельзя. Поэтому акторы в C++ требуют более пристального внимания. А когда оно есть, то польза от мониторинга агентов оказывается меньше, чем в Erlang-e.

                                          Если же обработчик события выбрасывает обычного наследника std::exception, то SO дает возможность пользователю определить, что делать. Поступить по-умолчанию (т.е. грохнуть приложение), остановить RunTime SO, дерегистрировать только кооперацию с этим агентом, или вообще проигнорировать.

                                          Цитата
                                          Цитата eao197 @
                                          Без guard-ов жизни нет, совсем.

                                          Ага, нету, как и без акторов :crazy: Я говорю не о возможности жизни, а об её облегчении.


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

                                          Цитата
                                          Цитата eao197 @
                                          А потом попробуйте на тех же boost.fiber переписать пример, который bsivko привел на SObjectizer

                                          Там слишком много артефактов реализации/библиотеки, чтобы ясно уловить смысл. Я же попросил вас пояснить разницу.


                                          Смысл прост, очень похож на тот, который в приведенном kovrin-ым примере на Go: пинги шлются не более N раз, понг отсылается только в ответ на полученный ping, следующий ping (если это возможно) отсылается только после получения pong-а.

                                          Цитата
                                          У-тю-тю-тю-тю :lool: Раз такие переходы на личности, то всё же мои аргументы по существу.


                                          В очередной раз вы сами себе что-то выдумали.

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


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

                                          Цитата
                                          eao197, знаете, а я ведь давно ваш блог читаю. Даже ваши аргументы по поводу D нравятся, часто на них ссылался. А сейчас смотрю - да вы обычный... чудак ;)


                                          А вы попробуйте со мной по существу поговорить. Я вам перечислил вещи, которые мне не нравятся в libcppa. Это не значит, что libcppa отстой, а SO рулез. Просто вот такое отношение к некоторым вещам. Могу, если интересно, развивать эти темы. Могу объяснить, почему в SO что-то сделано так, а не иначе. Могу рассказать, почему я бы не стал делать, как в libcppa. Это просто требует времени и соответствующих вопросов. Но когда разговор заходит на уровне "различия между каменным топором или стальным", то да, какой смысл мне с очередным... чудаком общаться не как очередному... чудаку?

                                          Добавлено
                                          Цитата Radagast @
                                          простите за нубский вопрос, но я так и не понял, SO работает на green threads или на обычных OS threads? если на зеленых, то как планировщик организовывает вытесняющую многозадачность между акторами?

                                          На нитях OS. Зеленые потоки мы не используем.

                                          Добавлено
                                          Цитата MyNameIsIgor @
                                          Обещанный код пинг-понга на boost.fibers. С комментария соответствующего кода на Go для оценки адовости :)

                                          Спасибо, интересно.
                                            Цитата MyNameIsIgor @
                                            table.push(ball);

                                            Поскольку я никогда не использовал Boost.Fiber и unbounded_queue, то объясните, пожалуйста, что/кто гарантирует, что после помещения ball в очередь table этот ball будет вытащен именно другим файбером, а не тем же самым, который поместил только что ball в очередь?
                                              Цитата eao197 @
                                              Решить что? Счетчик попыток -- это состояние агента. Его нужно хранить в самом агенте.

                                              It depends.
                                              Цитата eao197 @
                                              Поскольку в SO нет сопоставления с образцом, он использует typeid(msg_step)

                                              Вообще-то, это несвязанные вещи. libcppa использует свою информацию о типе из-за необходимости сериализации, которая в свою очередь необходима для удалённого взаимодействия. Кстати, а у вас как с этим обстоят дела?
                                              Цитата eao197 @
                                              Ну вот libcppa создает обертку вокруг тупла неявно. В SO это делается путем наследования от базового типа.

                                              Так и спрашиваю: с чего бы? Почему мне надо от чего-то наследоваться, чтобы кинуть int?
                                              Цитата eao197 @
                                              Фиг знает. Я так понимаю, что наследование там не спроста сделано. Видимо, кроме наследования нужно еще что-то менять в класса. И не известно, как от этого зависят клиенты или наследники.

                                              Там реализация, которую не надо всякий раз писать руками. В мануале неплохой пример со стеком с разными состояниями, что позволяет оставлять сообщения в ящике до перехода стека в другое состояние. Как это будет на SO?
                                              Цитата eao197 @
                                              Я уже все написал. Раз вы так хорошо знаете C++, как об этом думаете, то знаете, что большой класс ошибок в C++ не ловится вовремя вообще, либо же, в лучшем случае, ведет к краху всего приложения. В отличии от Erlang-а. Соответственно, в Erlang-е можно писать процесс не сильно заморачиваясь на многие вещи. А в C++ нельзя. Поэтому акторы в C++ требуют более пристального внимания. А когда оно есть, то польза от мониторинга агентов оказывается меньше, чем в Erlang-e.

                                              Если же обработчик события выбрасывает обычного наследника std::exception, то SO дает возможность пользователю определить, что делать. Поступить по-умолчанию (т.е. грохнуть приложение), остановить RunTime SO, дерегистрировать только кооперацию с этим агентом, или вообще проигнорировать.

                                              Так в SO как в libcppa, в чём же ваше претензии? :-?
                                              Цитата eao197 @
                                              Ну, если quard-ы облегчают вам жизнь и вы пишете программы уровня draw_kirby, тогда да, серьезное облегчение.

                                              Опять по существу ответить нечего? :) Я говорю о возможностях, которые не влияют на остальную функциональность, потому те, кому это нравится, могут использовать.
                                              Цитата eao197 @
                                              Смысл прост, очень похож на тот, который в приведенном kovrin-ым примере на Go: пинги шлются не более N раз, понг отсылается только в ответ на полученный ping, следующий ping (если это возможно) отсылается только после получения pong-а.

                                              Код, на который я дал ссылку, так и делает, за исключением того, что количество пинг-понгов там зашито. Ну, аналог кода korvin'а я привёл.
                                              Цитата eao197 @
                                              Я уже достаточно пожил на свете, чтобы не страдать от того, что чего-то не знаю.

                                              Но ещё недостаточно, чтобы научиться вести техническую дискуссию :)
                                              Цитата eao197 @
                                              А вы попробуйте со мной по существу поговорить. Я вам перечислил вещи, которые мне не нравятся в libcppa

                                              Я с вами именно по существу и разговариваю. Все мои высказывания касались ваших претензий и не являлись нападками на вас.
                                              Цитата eao197 @
                                              Но когда разговор заходит на уровне "различия между каменным топором или стальным", то да, какой смысл мне с очередным... чудаком общаться не как очередному... чудаку?

                                              Вы сами задали такой тон своим отношением
                                              Цитата eao197 @
                                              не идет ни в какое сравнение
                                                Цитата eao197 @
                                                Поскольку я никогда не использовал Boost.Fiber и unbounded_queue, то объясните, пожалуйста, что/кто гарантирует, что после помещения ball в очередь table этот ball будет вытащен именно другим файбером, а не тем же самым, который поместил только что ball в очередь?

                                                Да, я суровый косячник :D Надо будет написать Оливеру, чтобы запилил полноценные каналы, пока ещё не поздно, а не оставлял это на пользователей.
                                                ExpandedWrap disabled
                                                  using namespace boost::fibers;
                                                   
                                                  struct Ball {       //type Ball struct {
                                                      int hints;      //  hits int
                                                  };                  //}
                                                   
                                                  void player(str::string title, unbounded_queue<Ball>& table_in, unbounded_queue<Ball>& table_out,           //func player(title string, table chan *Ball, lose chan string) {
                                                              unbounded_queue<std::string>& lose) {                                                           // ...
                                                      for(Ball ball; table_in.pop(ball) == queue_op_status::success;) {                                       //  for ball := range table {
                                                          if(ball.hints > 0) {                                                                                //      if ball.hits > 0 {
                                                              std::cout << title << ' ' << ball.hints << std::endl;                                           //          fmt.Println(title, ball.hits)
                                                              ball.hints--;                                                                                   //          ball.hits--
                                                              table_out.push(ball);                                                                           //          table <- ball
                                                          } else {                                                                                            //      } else {
                                                              lose.push(title);                                                                               //          lose <- title
                                                              breal;                                                                                          //          break
                                                          }                                                                                                   //      }
                                                      }                                                                                                       //  }
                                                  }                                                                                                           //}
                                                   
                                                  int main() {                                                                                                //func main() {
                                                      unbounded_queue<Ball> table_ping, table_pong;                                                           //  table := make(chan *Ball)
                                                      unbounded_queue<std::string> lose;                                                                      //  lose  := make(chan string)
                                                      fiber ping { [&table_ping, &table_pong, &lose] { player("ping", table_ping, table_pong, lose); } };     //  go player("ping", table, lose)
                                                      fiber pong { [&table_ping, &table_pong, &lose] { player("pong", table_pong, table_ping, lose); } };     //  go player("pong", table, lose)
                                                   
                                                      table_ping.push(Ball{10});                                                                              //  table <- &Ball{10}
                                                      std::string title;                                                                                      //  ...
                                                      lose.pop(title);                                                                                        //  ...
                                                      std::cout << title << " lost" << std::endl;                                                             //  fmt.Println(<-lose, "lost")
                                                                                                                                                              //  close(table)
                                                      ping.join();                                                                                            //  ...
                                                      pong.join();                                                                                            //  ...
                                                  }                                                                                                           //  }


                                                Добавлено
                                                Значит, к вопросам о поддержке в SO удалённого взаимодействия и обработки разных сообщений в зависимости от состояний актора добавляется третий: а как с кроссплатформенностью? Как я понял, есть зависимость от такого монстра, как ACE. На Android/iOS соберётся?
                                                  Цитата MyNameIsIgor @
                                                  Цитата eao197 @
                                                  Решить что? Счетчик попыток -- это состояние агента. Его нужно хранить в самом агенте.

                                                  It depends.

                                                  Это если в общем говорить, тогда, действительно, где-то нужно хранить, где-то нужно передавать. В примере, приведенном bsivko изначально требовалось сделать хранение в агенте для того, чтобы показать, как в ad-hoc-агентах сохранять состояние через захват переменной по ссылке.

                                                  Цитата MyNameIsIgor @
                                                  Цитата eao197 @
                                                  Поскольку в SO нет сопоставления с образцом, он использует typeid(msg_step)

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

                                                  Мы в SO-4 использовали что-то похоже, на то, что предлагает libcppa для удаленного взаимодействия. Там так же нужно было отдельно декларировать поля сообщения и сам SO-4 формировал код по сериализации/десериализации структур. Более того, была утилита командной строки, которая позволяла задавать значение полей сообщения в stdin и засылала их внутрь SO-4 приложения.

                                                  Но со временем мы от этого ушли в сторону более мощной системы сериализации. А так же и поменяли подход к построению распределенных приложений на основе SO. Сейчас этими вещами занимается mbapi_4 (для сериализации используется ObjESSty -- что-то вроде Protobuf-а). Но, поскольку mbapi_4 -- это всего лишь т.н. layer, коих на SO можно навесить несколько, то вместо mbapi_4 можно сделать обмен сообщениями посредством AMQP и Protobuf-а.
                                                  Цитата MyNameIsIgor @
                                                  Цитата eao197 @
                                                  Ну вот libcppa создает обертку вокруг тупла неявно. В SO это делается путем наследования от базового типа.

                                                  Так и спрашиваю: с чего бы? Почему мне надо от чего-то наследоваться, чтобы кинуть int?

                                                  Потому, что мы по другому подходили к организации взаимодействия агентов. Агент A должен отослать агенту B какое-то осмысленное сообщение, например, "влючить лампочку" или "остановить двигатель". Соответственно, сообщение должно быть описано типом. Какая уже структура будет у типа -- это уже детали, может там один int, может два. А, поскольку мы уже заставляем пользователя вводить тип сообщения, то с точки зрения ООП естественным образом напрашивается его наследование от чего-нибудь.
                                                  Цитата MyNameIsIgor @
                                                  Цитата eao197 @
                                                  Фиг знает. Я так понимаю, что наследование там не спроста сделано. Видимо, кроме наследования нужно еще что-то менять в класса. И не известно, как от этого зависят клиенты или наследники.

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

                                                  Я пока не совсем понял, что там с состояниями у акторов libcppa. Поэтому не могу сейчас ответить. Если укажете конкретный пример, который бы вам было бы интересно увидеть переписанным на SO, я постараюсь это сделать.
                                                  Цитата MyNameIsIgor @
                                                  Так в SO как в libcppa, в чём же ваше претензии? :-?

                                                  Мне не нравится то, что в C++ 1-в-1 перенесли механизм из Erlang-а, польза от которого в C++ очень сомнительна. Это то, про что Страуструп говорит, как о попытке использования не подходящих к языку приемов. Как в свое время пытались делать библиотеки контейнеров для C++, требуя, чтобы все элементы контейнера были унаследованы от какого-нибудь общего Object-а.
                                                  Цитата MyNameIsIgor @
                                                  Цитата eao197 @
                                                  Я уже достаточно пожил на свете, чтобы не страдать от того, что чего-то не знаю.

                                                  Но ещё недостаточно, чтобы научиться вести техническую дискуссию :)

                                                  Техническая еще только начинается.
                                                  Цитата MyNameIsIgor @
                                                  Вы сами задали такой тон своим отношением
                                                  Цитата eao197 @
                                                  не идет ни в какое сравнение

                                                  Это не отношение. Это констатация того, что в libcppa сделали то, что в SO вообще никогда не пытались сделать. Поэтому, если пользователю от системы актеров нужно именно сопоставление с образцом, то возможности SObjectizer здесь бесполезно начинать сравнивать. Что вовсе не означает, что SObjectizer отстает от libcppa как каменный топор от стального. Скорее это просто попытка сравнить отбойный молоток с дрелью. Вроде как дырки оба инструмента позволяют делать...
                                                    Всё, я спать, D_KEY продолжит, он всё равно не спит...
                                                      Цитата MyNameIsIgor @
                                                      а как с кроссплатформенностью? Как я понял, есть зависимость от такого монстра, как ACE. На Android/iOS соберётся?

                                                      Сейчас да, сильно зависим от ACE. Может быть, в версии 5.4 постараемся от ACE уйти, хотя бы в самом ядре SO-5.

                                                      Про Android/iOS не знаю, никогда не связывался с этими платформами. По-идее, сам SO зависит только от GCC. А вот как с ACE -- хз, надо посмотреть.
                                                      Уверен, что если бы у меня под рукой был соответствующий инструментарий, то заработало бы и там.
                                                        Цитата MyNameIsIgor @
                                                        Всё, я спать, D_KEY продолжит, он всё равно не спит...

                                                        >:(
                                                          Цитата MyNameIsIgor @
                                                          Да, я суровый косячник

                                                          Еще одна штука. После чтения результата из очереди lose нужно закрыть обе очереди table*.
                                                          Иначе один из файберов заснет навечно на извлечении очередного сообщения. И весь пример уснет на одном из вызовом join.
                                                            Цитата eao197 @
                                                            то с точки зрения ООП естественным образом напрашивается его наследование от чего-нибудь

                                                            Нет, не напрашивается.

                                                            Цитата eao197 @
                                                            Еще одна штука. После чтения результата из очереди lose нужно закрыть обе очереди table*.
                                                            Иначе один из файберов заснет навечно на извлечении очередного сообщения. И весь пример уснет на одном из вызовом join.

                                                            Возможно в этом нет необходимости. По крайней мере в Go (и в Racket) — нет, все горутины прибьются автоматически при завершении программы. В данном случае это устраивает, close я добавил скорее просто для «аккуратности».
                                                              Цитата korvin @
                                                              Цитата eao197 @ Вчера, 02:03
                                                              то с точки зрения ООП естественным образом напрашивается его наследование от чего-нибудь

                                                              Нет, не напрашивается.


                                                              Судя по количеству разного ООП (например, Simula, Smalltalk, C++, Object Pascal, Java, Ruby, Self, JavaScript) мнения так же могут быть совершенно разными. Я высказал свое.
                                                              В предыдущей версии SObjectizer-а, SO-4, в качестве типа сообщения мог быть любой класс/структура, наследование было не обязательно. По факту, никакой выгоды от этого не было, только лишние заботы для разработчиков SO-4. Поэтому в SO-5 мы пошли вот по такому пути. Никаких реальных проблем на практике с этим нет.

                                                              Но с точки зрения какой-то абстрактной теоритической чистоты, возможно, в наследовании от общей базы есть что-то нехорошее.
                                                                Цитата eao197 @
                                                                Это констатация того, что в libcppa сделали то, что в SO вообще никогда не пытались сделать.

                                                                Блин, очевидные вещи всегда сложнее всего заметить о описать.

                                                                Вот еще какая штука. В Erlang-е нет никаких других механизмов структурирования информации, кроме туплов. Т.е. есть лишь туплы для структурирования и list-ы и (вроде как с недавних пор) map-ы для агрегирования. Все.

                                                                Но в туплах отдельные элементы не имеют своих имен, поэтому для доступа к элементу тупла нужен какой-то механизм. В плюсовых реализациях туплов -- это, например, методы get<INDEX>. А в языках, которые нормально затачивались под работу с туплами, как в Erlang, используется pattern matching. Отсюда же вытекает и формат receive в Erlang-е: если процессу отослали какую-то структуру данных, то это будет или тупл, или list/map. А, поскольку к данным в тупле нужно как-то добраться, то отсюда и паттерн-матчинг как селектор сообщения. (Аналогичным образом и работа с list/map-ами через паттерн-матчинг, ведь язык функциональный, циклов вроде for в нем нет, поэтому обход коллекций записывается как рекурсия с разбором контейнера на head и tail через паттерн-матчинг).

                                                                Однако, туплы автоматически означают структурную эквивалентность. Т.е. если у меня есть {0,1} и {3,5}, то я не могу судить -- относятся ли эти значения к экземплярам разных типов или нет. Может быть первый обозначает IP-адрес и порт, а второй секунды и микросекунды?

                                                                Для решения этой проблемы в Erlang-е ввели дискриминанты под названием атомы. Что стало позволять записывать туплы с указанием "типовой принадлежности": {address, 0, 1} и {timeval, 3, 5}.

                                                                Однако, в императивных языках, вышедших из Aglol/Simula, нет необходимости в таком отдельном дискриминанте таковым там является само имя типа. Т.е. то, что в Erlang-е из-за наличия в языке struct записывается как {address, 0, 1}, в C++ записывается как address(0, 1).

                                                                Соответственно, значение паттерн-матчинга в C++ ниже, чем в Erlang. Ведь в Erlang-е для разбора значения {address, 0, 1} нам нужно писать образец с присваиванием значений локальным константам:
                                                                ExpandedWrap disabled
                                                                  process_address({address, Host, Port}) ->
                                                                    что-то там с использованием Host и Port

                                                                А в С++ мы просто обращаемся к полям структуры:
                                                                ExpandedWrap disabled
                                                                  process_address(const address & a ) {
                                                                    // что-то там с использованием a.host и a.port.
                                                                  }

                                                                Добавим сюда еще и то, что Erlang -- это динамически типизированный язык. Это означает, что код на Erlang-е получается компактнее, обозримее и, в некоторых случаях, он сразу становится "обобщенным". Т.е. может работать с разными типами аргументов. Например, если какой-то фрагмент Erlang-овской программы использует туплы вида {address, Host, Port}, то ему может оказаться без разницы, что из себя представляет Host -- uint32, string или ipv6. Это ведет к двум важным последствиям в Erlang-е: сокращается объем кода и код оказывается толерантным к изменениям типов элементов тупла. Т.е. сначала process_address успешно работал с представлением Host в виде unit32 и string, а затем спокойно пережил еще и добавление ipv6.

                                                                В статически-типизированном C++ этот фокус не работает. Писать в любом случае приходится больше (спецификация типов аргументов). Толерантность к изменению типов элементов тупла нужно обеспечивать за счет использования шаблонов, а в этом так же есть свои минусы. Да и просто вариант
                                                                ExpandedWrap disabled
                                                                  struct address {
                                                                    какой-то-тип host;
                                                                    short port;
                                                                  }

                                                                в котором на месте "какой-то-тип" может быть как unit32, так и std::string, так и ipv6, в C++ уже потребует каких-то фокусов (вроде задействования какого-то из variant-ов) с соответствующими последствиями (например, накладными расходами в run-time).

                                                                Поэтому мне и показалось странным копирование подхода из Erlang-а в C++ную библиотеку. Родные и удобные для Erlang-а вещи смотрятся для меня как чужеродные в C++. Например, мне не понятно, чем вот это:
                                                                ExpandedWrap disabled
                                                                  on(atom("add"), arg_match) >> [](int a, int b) { /*...*/ },
                                                                  on(atom("multiply"), arg_match) >> [](int a, int b) { /*...*/ },

                                                                лучше, чем вот это:
                                                                ExpandedWrap disabled
                                                                  struct add { int a, int b };
                                                                  struct multiply { int a, int b };
                                                                   
                                                                  on( arg_match ) >> []( const add & w ) { /* ... */ },
                                                                  on( arg_match ) >> []( const multiply & w ) { /* ... */ }

                                                                Ведь здесь мы получаем защиту статической типизации. Никто не сможет просто так отослать сообщение multiply, передав в качестве аргументов две строки. Или написав по ошибке atom("multiplicate") вместо atom("multiply").
                                                                Сообщение отредактировано: eao197 -
                                                                  Цитата eao197 @
                                                                  Но со временем мы от этого ушли в сторону более мощной системы сериализации. А так же и поменяли подход к построению распределенных приложений на основе SO. Сейчас этими вещами занимается mbapi_4 (для сериализации используется ObjESSty -- что-то вроде Protobuf-а). Но, поскольку mbapi_4 -- это всего лишь т.н. layer, коих на SO можно навесить несколько, то вместо mbapi_4 можно сделать обмен сообщениями посредством AMQP и Protobuf-а.

                                                                  Protobuf и свой сериализатор.
                                                                  Цитата eao197 @
                                                                  Потому, что мы по другому подходили к организации взаимодействия агентов. Агент A должен отослать агенту B какое-то осмысленное сообщение, например, "влючить лампочку" или "остановить двигатель". Соответственно, сообщение должно быть описано типом.

                                                                  Ok, я хочу enum ;)
                                                                  Цитата eao197 @
                                                                  А, поскольку мы уже заставляем пользователя вводить тип сообщения, то с точки зрения ООП естественным образом напрашивается его наследование от чего-нибудь.

                                                                  В вашем примере нет ООП (или вы его не показали). Потому что для пользователя нет никакого профита от наследования - по вашим словам, это лишь артефакт реализации.
                                                                  Цитата eao197 @
                                                                  Я пока не совсем понял, что там с состояниями у акторов libcppa. Поэтому не могу сейчас ответить. Если укажете конкретный пример, который бы вам было бы интересно увидеть переписанным на SO, я постараюсь это сделать.

                                                                  Ну, я имел в виду fixed_stack. Или обедающих философов. Там обработка сообщений зависит от состояния актора, причём код структурирован по состояниям. Вот аналог этого и хотелось бы увидеть.
                                                                  По поводу оставления сообщений в ящике, наверное, я что-то напутал. Сейчас читаю, что не сопоставленные сообщения отбрасываются. Странно, надо будет уточнить. Кстати, как с этим в SO?
                                                                  Цитата eao197 @
                                                                  Мне не нравится то, что в C++ 1-в-1 перенесли механизм из Erlang-а, польза от которого в C++ очень сомнительна. Это то, про что Страуструп говорит, как о попытке использования не подходящих к языку приемов.

                                                                  Здесь нарушена причинно-следственная связь. Т.е. не доказано, что это именно тот случай, о котором говорит Бьярн. Читающему предлагается поверить вам на слово, а между тем я не вижу в данном случае "неподходящих к языку приёмов".
                                                                  Кстати, о Страуструпе. ЕМНИП, на вопрос, а почему нет требования наследовать исключения от std::exception, он отвечает "а зачем?".
                                                                  Цитата eao197 @
                                                                  Как в свое время пытались делать библиотеки контейнеров для C++, требуя, чтобы все элементы контейнера были унаследованы от какого-нибудь общего Object-а

                                                                  Там как раз были виноваты любители ООП :D Они хотели положить в контейнеры именно полиморфные типы. В их представлении не было жизни за пределами ООП. Да и большая часть таких библиотек появилась ещё до шаблонов.
                                                                  А вообще интрузивные контейнеры полезны - да хотя бы документацию boost.intrusive почитайте. Например, благодаря их особенностям, lock-free структуры данных легче делать именно интрузивными.
                                                                  Так что это не является чем-то неправильным, это лишь иной подход с плюсами и минусами.
                                                                  Цитата eao197 @
                                                                  Скорее это просто попытка сравнить отбойный молоток с дрелью. Вроде как дырки оба инструмента позволяют делать...

                                                                  Я не вижу здесь разных инструментов - с помощью libcppa можно писать в том же стиле, что и с SO. Так что это дрель рядом с перфоратором с режимом дрели :crazy:

                                                                  Добавлено
                                                                  Цитата eao197 @
                                                                  Добавим сюда еще и то, что Erlang -- это динамически типизированный язык

                                                                  Цитата eao197 @
                                                                  В статически-типизированном C++ этот фокус не работает

                                                                  Время типизации здесь ни при чём. Дело в синтаксисе - явная/неявная. Хиндли-Милнер сделает код статически типизированного языка не менее компактным.
                                                                  Цитата eao197 @
                                                                  Поэтому мне и показалось странным копирование подхода из Erlang-а в C++ную библиотеку. Родные и удобные для Erlang-а вещи смотрятся для меня как чужеродные в C++. Например, мне не понятно, чем вот это:
                                                                  ...
                                                                  лучше, чем вот это:

                                                                  Почему "лучше"? Это другая возможность. libcppa не исключает ни одну из них.

                                                                  Добавлено
                                                                  Ну, и да, в Erlang всё же есть структуры... но они преобразуются в тегированные кортежи, да.

                                                                  Добавлено
                                                                  Цитата korvin @
                                                                  Возможно в этом нет необходимости.

                                                                  Не, здесь есть необходимость :D
                                                                    Цитата eao197 @
                                                                    Но с точки зрения какой-то абстрактной теоритической чистоты, возможно, в наследовании от общей базы есть что-то нехорошее.

                                                                    Дело не в хорошести/нехорошести, а в надобности/ненадобности. Из одного только факта использования ООП никаким образом не вытекает необходимость наследования. Но это все так, к слову.
                                                                      Цитата MyNameIsIgor @
                                                                      Цитата eao197 @
                                                                      Потому, что мы по другому подходили к организации взаимодействия агентов. Агент A должен отослать агенту B какое-то осмысленное сообщение, например, "влючить лампочку" или "остановить двигатель". Соответственно, сообщение должно быть описано типом.

                                                                      Ok, я хочу enum ;)

                                                                      Я понимаю, что вы можете хотеть работать с туплами вида <lamp_on, power_level> или <engine_off, mode, timeout>.
                                                                      Но не понимаю, зачем это делать на практике, если можно работать со структурами struct lamp_on{int power_level;} или struct engine_off{management_mode mode; duration timeout;}.

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

                                                                      Цитата MyNameIsIgor @
                                                                      Цитата eao197 @
                                                                      А, поскольку мы уже заставляем пользователя вводить тип сообщения, то с точки зрения ООП естественным образом напрашивается его наследование от чего-нибудь.

                                                                      В вашем примере нет ООП (или вы его не показали). Потому что для пользователя нет никакого профита от наследования - по вашим словам, это лишь артефакт реализации.

                                                                      А какой профит пользователям Qt наследоваться от QObject-а?

                                                                      Цитата MyNameIsIgor @
                                                                      Цитата eao197 @
                                                                      Я пока не совсем понял, что там с состояниями у акторов libcppa. Поэтому не могу сейчас ответить. Если укажете конкретный пример, который бы вам было бы интересно увидеть переписанным на SO, я постараюсь это сделать.

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

                                                                      Ну, fixed_stack выглядел бы вот так:
                                                                      ExpandedWrap disabled
                                                                        class fixed_stack : public so_5::rt::agent_t
                                                                        {
                                                                          const so_5::rt::mbox_ref_t m_mbox;
                                                                          so_5::rt::state_t st_empty;
                                                                          so_5::rt::state_t st_filled;
                                                                          so_5::rt::state_t st_full;
                                                                         
                                                                          const size_t m_max_size;
                                                                          std::vector< int > m_stack;
                                                                         
                                                                        public :
                                                                          fixed_stack( so_5::rt::environment_t & env,
                                                                            const so_5::rt::mbox_ref_t & mbox,
                                                                            size_t max_size )
                                                                            : so_5::rt::agent_t( env )
                                                                            , m_mbox( mbox )
                                                                            , st_empty( so_self_ptr(), "empty" )
                                                                            , st_filled( so_self_ptr(), "filled" )
                                                                            , st_full( so_self_ptr(), "full" )
                                                                            , m_max_size( max_size )
                                                                            {}
                                                                         
                                                                          struct msg_push : public so_5::rt::message_t
                                                                          {
                                                                            int m_val;
                                                                          };
                                                                          struct msg_pop : public so_5::rt::signal_t {};
                                                                         
                                                                          virtual void
                                                                          so_define_agent()
                                                                          {
                                                                            so_change_state( st_empty );
                                                                         
                                                                            so_subscribe( m_mbox ).in( st_empty ).in( st_filled ).event(
                                                                              [this]( const msg_push & w ) {
                                                                                m_stack.push_back( w.m_val );
                                                                                if( m_stack.size() == m_max_size )
                                                                                  so_change_state( st_full );
                                                                              } );
                                                                         
                                                                            so_subscribe( m_mbox ).in( st_filled ).in( st_full ).event( so_5::signal< msg_pop >,
                                                                              [this]() {
                                                                                auto r = m_stack.back();
                                                                                m_stack.pop_back();
                                                                                so_change_state( m_stack.empty() ? st_empty : st_filled );
                                                                                return r;
                                                                              } );
                                                                         
                                                                            so_subscribe( m_mbox ).in( st_empty ).event( so_5::signal< msg_pop >,
                                                                              []() {
                                                                                throw std::runtime_error( "empty_stack" );
                                                                              } );
                                                                          }
                                                                        };


                                                                      Цитата MyNameIsIgor @
                                                                      По поводу оставления сообщений в ящике, наверное, я что-то напутал. Сейчас читаю, что не сопоставленные сообщения отбрасываются. Странно, надо будет уточнить. Кстати, как с этим в SO?

                                                                      Не обработанные сообщения выбрасываются. Selective receive нет и, полагаю, не будет.

                                                                      Цитата MyNameIsIgor @
                                                                      Цитата eao197 @
                                                                      Мне не нравится то, что в C++ 1-в-1 перенесли механизм из Erlang-а, польза от которого в C++ очень сомнительна. Это то, про что Страуструп говорит, как о попытке использования не подходящих к языку приемов.

                                                                      Здесь нарушена причинно-следственная связь. Т.е. не доказано, что это именно тот случай, о котором говорит Бьярн. Читающему предлагается поверить вам на слово, а между тем я не вижу в данном случае "неподходящих к языку приёмов".

                                                                      А разве такие вещи могут быть доказаны? Здесь больше дело вкуса. Если кому-то нравится полагаться на строковые константы длиной до 10 символов и ручной разбор туплов на составляющие -- ну значит для него это подходящий прием. Если кому-то, как и мне, это не нравится, то для меня не подходящий.

                                                                      Цитата MyNameIsIgor @
                                                                      Цитата eao197 @
                                                                      Добавим сюда еще и то, что Erlang -- это динамически типизированный язык

                                                                      Цитата eao197 @
                                                                      В статически-типизированном C++ этот фокус не работает

                                                                      Время типизации здесь ни при чём. Дело в синтаксисе - явная/неявная. Хиндли-Милнер сделает код статически типизированного языка не менее компактным.

                                                                      Мы же говорим о переносе принципов работы Erlang-а в C++, а не в OCaml или Haskell. Поэтому более чем при чем.

                                                                      Цитата MyNameIsIgor @
                                                                      Почему "лучше"? Это другая возможность. libcppa не исключает ни одну из них.

                                                                      Ок, поинт я понял. Значит можно сказать, что SObjectizer помещает пользователя в более жесткие рамки.

                                                                      Цитата MyNameIsIgor @
                                                                      Добавлено
                                                                      Ну, и да, в Erlang всё же есть структуры... но они преобразуются в тегированные кортежи, да.

                                                                      Ссылочку можно?

                                                                      Цитата MyNameIsIgor @
                                                                      Добавлено
                                                                      Цитата korvin @
                                                                      Возможно в этом нет необходимости.

                                                                      Не, здесь есть необходимость :D

                                                                      В итоге, если устранить все ошибки и записать код примера на C++ полностью, то по объему он уйдет не сильно далеко от SO-варианта. Что до сложности, то любой инструмент нуждается в изучении. После определенного порога он перестает быть сложным.
                                                                        Кстати, eao197, код без кучи переносов строк выглядит приятнее. А, korvin?
                                                                          Цитата eao197 @
                                                                          Я понимаю, что вы можете хотеть работать с туплами вида <lamp_on, power_level> или <engine_off, mode, timeout>.
                                                                          Но не понимаю, зачем это делать на практике, если можно работать со структурами struct lamp_on{int power_level;} или struct engine_off{management_mode mode; duration timeout;}.

                                                                          Я вам привёл весьма жизненный пример - я хочу послать сообщения типа enum, благо теперь есть enum class. Как мне это сделать в SO? Это риторический вопрос ;)
                                                                          Я не понимаю, зачем мне писать
                                                                          ExpandedWrap disabled
                                                                            struct msg_1 : message_t {};
                                                                            struct msg_2 : message_t {};
                                                                            ...
                                                                            struct msg_n : message_t {};

                                                                          вместо
                                                                          ExpandedWrap disabled
                                                                            enum class msg
                                                                            {
                                                                              msg_1,
                                                                              msg_2,
                                                                              ...
                                                                              msg_n
                                                                            };

                                                                          Цитата eao197 @
                                                                          А какой профит пользователям Qt наследоваться от QObject-а?

                                                                          А это тоже артефакт реализации. Но там хоть много чего можно переопределять типа обработки событий.
                                                                          Цитата eao197 @
                                                                          А разве такие вещи могут быть доказаны? Здесь больше дело вкуса. Если кому-то нравится полагаться на строковые константы длиной до 10 символов и ручной разбор туплов на составляющие -- ну значит для него это подходящий прием. Если кому-то, как и мне, это не нравится, то для меня не подходящий.

                                                                          Замечательно. libcppa позволяет оба подхода. Почему же не конкурент?
                                                                          Цитата eao197 @
                                                                          Мы же говорим о переносе принципов работы Erlang-а в C++, а не в OCaml или Haskell. Поэтому более чем при чем.

                                                                          ... Ещё раз: код на C++ менее компактный не из-за статической, а из-за явной типизации.
                                                                          Цитата eao197 @
                                                                          Ссылочку можно?

                                                                          Эмм.. Ну, [Чезарини, Томпсон "Программирование в Erlang"]. Есть пара строк в вики.
                                                                          Цитата eao197 @
                                                                          В итоге, если устранить все ошибки и записать код примера на C++ полностью, то по объему он уйдет не сильно далеко от SO-варианта.

                                                                          Во-первых, дело не в объёме, а в том, что korvin назвал "адовостью" :) Да, читаемость - вещь субъективная, но тут я с ним согласен: примеры на SO нечитаемы.
                                                                          Во-вторых, смысл boost.fibers в другом - в возможности писать синхронный код вместо лапшеколбэков.

                                                                          Добавлено
                                                                          Ах, да, ещё забыл. У вас группировка состояний по одному обработчику
                                                                          ExpandedWrap disabled
                                                                            so_subscribe( m_mbox ).in( st_empty ).in( st_filled ).event

                                                                          Это неинтересно, ибо редко обработчик один для разных состояний. Интереснее как в случае философов - группировка обработчиков по одному состоянию.
                                                                          Сообщение отредактировано: MyNameIsIgor -
                                                                            ExpandedWrap disabled
                                                                              enum class msg
                                                                              {
                                                                                msg_1,
                                                                                msg_2,
                                                                                ...
                                                                                msg_n
                                                                              };
                                                                               
                                                                              template <msg V> struct msg2type {}: message_t;
                                                                            Ужас, да?
                                                                              Цитата MyNameIsIgor @
                                                                              Я не понимаю, зачем мне писать
                                                                              ExpandedWrap disabled
                                                                                struct msg_1 : message_t {};
                                                                                struct msg_2 : message_t {};
                                                                                ...
                                                                                struct msg_n : message_t {};

                                                                              вместо
                                                                              ExpandedWrap disabled
                                                                                enum class msg
                                                                                {
                                                                                  msg_1,
                                                                                  msg_2,
                                                                                  ...
                                                                                  msg_n
                                                                                };

                                                                              Потому, что в подавляющем большинстве случаев с сообщением связаны еще и какие-то данные. Т.о., при реальной работе вам кроме enum class msg с вариантами msg_1,...,msg_n предстоит вести дополнительные наборы структур или туплов.
                                                                              Цитата MyNameIsIgor @
                                                                              Цитата eao197 @
                                                                              А какой профит пользователям Qt наследоваться от QObject-а?

                                                                              А это тоже артефакт реализации.

                                                                              Ну вот и у нас аналогично. Всех особенностей реализации не спрячешь. У нас вот здесь пользователь видит некоторые ограничения. Что позволяет чуть более эффективно работать с сообщениями, чем это было в SO-4, где таких ограничений не было.
                                                                              Цитата MyNameIsIgor @
                                                                              Замечательно. libcppa позволяет оба подхода. Почему же не конкурент?

                                                                              Знаете, я когда-то задал вопрос Мартину Одерски о том, что он думает о конкурентах Scala (вроде Nemerle, F#, Nice и пр.). Он тогда высказался, что не считает эти языки конкурентами, скорее они все помогают друг другу развиваться и набирать популярность.

                                                                              Вот так и здесь. Мне не суть важно, насколько libcppa и SObjectizer конкурируют друг с другом. Намного важнее то, оставляют ли они C++ разработчиков в рамках C++ или же люди все-таки уходят в Erlang, Scala или еще куда-нибудь. Берут какую-нибудь Akka, а потом узкие места пытаются переписать на C или начинают бороться с GC. Тогда как можно было получить более качественный результат в C++.

                                                                              Цитата MyNameIsIgor @
                                                                              Цитата eao197 @
                                                                              Мы же говорим о переносе принципов работы Erlang-а в C++, а не в OCaml или Haskell. Поэтому более чем при чем.

                                                                              ... Ещё раз: код на C++ менее компактный не из-за статической, а из-за явной типизации.

                                                                              Ок, понял. Похоже, суть разногласий здесь в том, что под "статической типизацией" я сразу подразумевал и статическую типизацию и явную декларацию типов.

                                                                              Цитата MyNameIsIgor @
                                                                              Цитата eao197 @
                                                                              В итоге, если устранить все ошибки и записать код примера на C++ полностью, то по объему он уйдет не сильно далеко от SO-варианта.

                                                                              Во-первых, дело не в объёме, а в том, что korvin назвал "адовостью" :) Да, читаемость - вещь субъективная, но тут я с ним согласен: примеры на SO нечитаемы.
                                                                              Во-вторых, смысл boost.fibers в другом - в возможности писать синхронный код вместо лапшеколбэков.

                                                                              Суть в том, что SO никогда, т.е. вообще никогда, не задумывался для написания синхронного кода. Добавленная в 5.3 фича -- это эксперимент, на результат которого нужно будет еще посмотреть.
                                                                              ---
                                                                                Цитата Qraizer @
                                                                                Кстати, eao197, код без кучи переносов строк выглядит приятнее.

                                                                                А как бы вы пример отформатировали?
                                                                                  Цитата MyNameIsIgor @
                                                                                  Это неинтересно, ибо редко обработчик один для разных состояний. Интереснее как в случае философов - группировка обработчиков по одному состоянию.

                                                                                  Никто не заставляет писать один обработчик на насколько состояний, можно делать кучу отдельных subscribe. Но, если можно объединить, то можно объединить.

                                                                                  Про философов посмотрю. Нужно вкурить особенности тамошней реализации.
                                                                                    Цитата eao197 @
                                                                                    Потому, что в подавляющем большинстве случаев с сообщением связаны еще и какие-то данные. Т.о., при реальной работе вам кроме enum class msg с вариантами msg_1,...,msg_n предстоит вести дополнительные наборы структур или туплов.

                                                                                    Ну, а можно это буду решать я как пользователь?
                                                                                    Цитата eao197 @
                                                                                    Ну вот и у нас аналогично. Всех особенностей реализации не спрячешь.

                                                                                    Сложностей, которые принёс бы отказ от QObject, несравнимо больше сложностей, которые появятся от отказа наследования для типа сообщения. Да я вообще никаких особых сложностей от произвольного типа не вижу. Да и у вас это уже было. А отказываться только из-за неудобства разработчиков... ну, библиотеки пишутся для удобства пользователей, а не создателей.
                                                                                    Цитата eao197 @
                                                                                    Мне не суть важно, насколько libcppa и SObjectizer конкурируют друг с другом. Намного важнее то, оставляют ли они C++ разработчиков в рамках C++ или же люди все-таки уходят в Erlang, Scala или еще куда-нибудь. Берут какую-нибудь Akka, а потом узкие места пытаются переписать на C или начинают бороться с GC. Тогда как можно было получить более качественный результат в C++.

                                                                                    А, простите, вы уже где-то показали, что ваш результат качественнее, кроме "я так считаю"? :) Какие, кстати, критерия качества?
                                                                                    Цитата eao197 @
                                                                                    Про философов посмотрю. Нужно вкурить особенности тамошней реализации.

                                                                                    Ну, меня интересует не программа с точно такой же семантикой, а просто аналог конструкций
                                                                                    ExpandedWrap disabled
                                                                                      // a philosopher that receives {eat} stops thinking and becomes hungry
                                                                                              thinking = (
                                                                                                  on(atom("eat")) >> [=] {
                                                                                                      become(hungry);
                                                                                                      send(left, atom("take"), this);
                                                                                                      send(right, atom("take"), this);
                                                                                                  }
                                                                                              );
                                                                                              // wait for the first answer of a chopstick
                                                                                              hungry = (
                                                                                                  on(atom("taken"), left) >> [=] {
                                                                                                      become(waiting_for(right));
                                                                                                  },
                                                                                                  on(atom("taken"), right) >> [=] {
                                                                                                      become(waiting_for(left));
                                                                                                  },
                                                                                                  on<atom("busy"), actor>() >> [=] {
                                                                                                      become(denied);
                                                                                                  }
                                                                                              );
                                                                                              // philosopher was not able to obtain the first chopstick
                                                                                              denied = (
                                                                                                  on(atom("taken"), arg_match) >> [=](const actor& ptr) {
                                                                                                      send(ptr, atom("put"), this);
                                                                                                      send(this, atom("eat"));
                                                                                                      become(thinking);
                                                                                                  },
                                                                                                  on<atom("busy"), actor>() >> [=] {
                                                                                                      send(this, atom("eat"));
                                                                                                      become(thinking);
                                                                                                  }
                                                                                              );
                                                                                              // philosopher obtained both chopstick and eats (for five seconds)
                                                                                              eating = (
                                                                                                  on(atom("think")) >> [=] {
                                                                                                      send(left, atom("put"), this);
                                                                                                      send(right, atom("put"), this);
                                                                                                      delayed_send(this, seconds(5), atom("eat"));
                                                                                                      aout(this) << name
                                                                                                                 << " puts down his chopsticks and starts to think\n";
                                                                                                      become(thinking);
                                                                                                  }
                                                                                              );

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

                                                                                    Добавлено
                                                                                    Цитата Qraizer @
                                                                                    Ужас, да?

                                                                                    Ужас или нет, но... зачем?
                                                                                      Цитата MyNameIsIgor @
                                                                                      Цитата eao197 @
                                                                                      Потому, что в подавляющем большинстве случаев с сообщением связаны еще и какие-то данные. Т.о., при реальной работе вам кроме enum class msg с вариантами msg_1,...,msg_n предстоит вести дополнительные наборы структур или туплов.

                                                                                      Ну, а можно это буду решать я как пользователь?


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

                                                                                      Цитата MyNameIsIgor @
                                                                                      Цитата eao197 @
                                                                                      Ну вот и у нас аналогично. Всех особенностей реализации не спрячешь.

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

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

                                                                                      Ну а по поводу "я не вижу", так пока не сделаешь сам и не попытаешься это разогнать, а потом посопровождать, много чего не видишь :(

                                                                                      Цитата MyNameIsIgor @
                                                                                      Цитата eao197 @
                                                                                      Мне не суть важно, насколько libcppa и SObjectizer конкурируют друг с другом. Намного важнее то, оставляют ли они C++ разработчиков в рамках C++ или же люди все-таки уходят в Erlang, Scala или еще куда-нибудь. Берут какую-нибудь Akka, а потом узкие места пытаются переписать на C или начинают бороться с GC. Тогда как можно было получить более качественный результат в C++.

                                                                                      А, простите, вы уже где-то показали, что ваш результат качественнее, кроме "я так считаю"? :)

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

                                                                                      Цитата MyNameIsIgor @
                                                                                      Цитата eao197 @
                                                                                      Про философов посмотрю. Нужно вкурить особенности тамошней реализации.

                                                                                      Ну, меня интересует не программа с точно такой же семантикой, а просто аналог конструкций
                                                                                      ExpandedWrap disabled
                                                                                        // a philosopher that receives {eat} stops thinking and becomes hungry
                                                                                                thinking = (
                                                                                                    on(atom("eat")) >> [=] {
                                                                                                        become(hungry);
                                                                                                        send(left, atom("take"), this);
                                                                                                        send(right, atom("take"), this);
                                                                                                    }
                                                                                                );
                                                                                                // wait for the first answer of a chopstick
                                                                                                hungry = (
                                                                                                    on(atom("taken"), left) >> [=] {
                                                                                                        become(waiting_for(right));
                                                                                                    },
                                                                                                    on(atom("taken"), right) >> [=] {
                                                                                                        become(waiting_for(left));
                                                                                                    },
                                                                                                    on<atom("busy"), actor>() >> [=] {
                                                                                                        become(denied);
                                                                                                    }
                                                                                                );
                                                                                                // philosopher was not able to obtain the first chopstick
                                                                                                denied = (
                                                                                                    on(atom("taken"), arg_match) >> [=](const actor& ptr) {
                                                                                                        send(ptr, atom("put"), this);
                                                                                                        send(this, atom("eat"));
                                                                                                        become(thinking);
                                                                                                    },
                                                                                                    on<atom("busy"), actor>() >> [=] {
                                                                                                        send(this, atom("eat"));
                                                                                                        become(thinking);
                                                                                                    }
                                                                                                );
                                                                                                // philosopher obtained both chopstick and eats (for five seconds)
                                                                                                eating = (
                                                                                                    on(atom("think")) >> [=] {
                                                                                                        send(left, atom("put"), this);
                                                                                                        send(right, atom("put"), this);
                                                                                                        delayed_send(this, seconds(5), atom("eat"));
                                                                                                        aout(this) << name
                                                                                                                   << " puts down his chopsticks and starts to think\n";
                                                                                                        become(thinking);
                                                                                                    }
                                                                                                );

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

                                                                                      Я не совсем понимаю, что именно вы хотите увидеть. Если одни и те же сообщения по разному нужно обрабатывать в разных состояниях, то делается это так:
                                                                                      ExpandedWrap disabled
                                                                                        so_subscribe( mbox ).in( st_hungry ).event([](const taken&) {...} );
                                                                                        so_subscribe( mbox ).in( st_hungry ).event([](const busy&) {...} );
                                                                                        so_subscribe( mbox ).in( st_denied ).event([](const taken&) {...} );
                                                                                        so_subscribe( mbox ).in( st_denied ).event([](const busy&) {...} );
                                                                                        ...
                                                                                        Цитата eao197 @
                                                                                        Не можно, а нужно. Вы, как пользователь, сформируете свои критерии выбора конкретного инструмента

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

                                                                                        Так расскажите о сложностях отказа от наследования.
                                                                                        Цитата eao197 @
                                                                                        Какой внезапный поворот заговора. Здесь, вообще-то, речь не шла о конкретно моем результате

                                                                                        Почему же? Разговор о вашей библиотеке.
                                                                                        Цитата eao197 @
                                                                                        Если одни и те же сообщения по разному нужно обрабатывать в разных состояниях, то делается это так

                                                                                        Ясно, группировка с помощью форматирования кода :yes-sad:
                                                                                          Цитата MyNameIsIgor @
                                                                                          Цитата eao197 @
                                                                                          Не можно, а нужно. Вы, как пользователь, сформируете свои критерии выбора конкретного инструмента

                                                                                          Хорошо, тогда я ставлю минус.

                                                                                          Так об этом сразу было сказано: в плане сопоставления с образцом при разборе данных сообщения SObjectizer не идет ни в какое сравнение с libcppa.
                                                                                          Другое дело, что за все время работы с SObjectizer надобности в этом не было. Посему для вас минус, для меня это вообще не критерий.
                                                                                          Цитата MyNameIsIgor @
                                                                                          Цитата eao197 @
                                                                                          Ну а по поводу "я не вижу", так пока не сделаешь сам и не попытаешься это разогнать, а потом посопровождать, много чего не видишь

                                                                                          Так расскажите о сложностях отказа от наследования.

                                                                                          Может вы сначала попробуете описать преимущества этого?
                                                                                          Поскольку вот мы сначала работали без наследования. Из-за этого приходилось создавать дополнительные объекты со счетчиками ссылок. Не было возможностей просто так переадресовать тот же самый экземпляр сообщения в новый send или серию новых send-ов. И т.д. по мелочам. Отказались от всего этого, жизнь стала лучше :)
                                                                                          Цитата MyNameIsIgor @
                                                                                          Цитата eao197 @
                                                                                          Какой внезапный поворот заговора. Здесь, вообще-то, речь не шла о конкретно моем результате

                                                                                          Почему же? Разговор о вашей библиотеке.

                                                                                          Похоже, здесь опять какое-то недопонимание.
                                                                                          Попробую вот так объяснить. С начала 2000-х идет большой отток разработчиков из C++ в другие ниши (в основном в Java, частично в C#). В свое время это было оправдано, т.к. C++ развивался очень медленно. Да и память с гигагерцами никто не считал. Однако, время прошло, писать на C++ сейчас намного проще и безопаснее, а за счет некоторых возможностей языка (rvalue references, например) код получается еще быстрее и надежнее. Плюс на расход памяти и на мощность компьютеров вновь обращают внимание. Если лет 8-мь назад можно было встретить радостные упоминания, что RoR приложение отмасштабировано на 1000 серверов, то сейчас уже чаще заходит речь о другом: зачем платить за 1000 серверов с RoR приложением там, где можно обойтись 200 с Lift-приложением. Т.е. для возвращения достаточного интереса к использованию C++ вместо Java/C# сейчас больше условий, чем 10 лет назад. И, если этому поспособствуют библиотеки вроде libcppa, jss или SObjectizer, то это хорошо. Даже если 99% процентов C++ников будут пользоваться libcppa, а на долю jss и SO придется по 0.5%.

                                                                                          Что до SO, то на своей прошлой работе SO-проекты были самыми нагруженными, стабильными, протестированными и документированными. Некоторая доля заслуги в этом есть и SO, как простого и надежного инструмента.
                                                                                          Цитата MyNameIsIgor @
                                                                                          Цитата eao197 @
                                                                                          Если одни и те же сообщения по разному нужно обрабатывать в разных состояниях, то делается это так

                                                                                          Ясно, группировка с помощью форматирования кода :yes-sad:

                                                                                          Э... Это не принципиальное ограничение обусловленное какими-то архитектурными особенностями. Если кому-то потребуется, то можно будет сделать и такой вариант:
                                                                                          ExpandedWrap disabled
                                                                                            so_state( st_hungry ).mbox( mbox ).event( ... ).event( ... ).event( ... )...

                                                                                          Просто метод so_subscribe заточен под те кейсы, который были распространены у нас. Но он возвращает простенький прокси-объект, накапливающий информацию, а затем осуществляющий обращение к специальному методу агента для создания подписок. Аналогичным образом можно сделать и другой простенький прокси-объект, возвращаемый методом so_state().
                                                                                            Цитата MyNameIsIgor @
                                                                                            Цитата korvin @
                                                                                            Это всё наверное дико круто, но хотелось бы, чтоб оно выглядело менее адово.

                                                                                            Например. Но, я думаю, ты согласишься, что это всё не дотягивает до нормальных акторов без сопоставления с образцом.
                                                                                            IMHO, libcppa более вменяемая в этом плане. bsivko, что скажете о конкуренте?

                                                                                            Тут много чего уже сказали, но в общем с случае да, абстракции и инструменты работы над ними разные, и не все акторы/агенты одинаково полезны [в конкретных обстоятельствах].

                                                                                            Цитата MyNameIsIgor @
                                                                                            Цитата eao197 @
                                                                                            Не можно, а нужно. Вы, как пользователь, сформируете свои критерии выбора конкретного инструмента

                                                                                            Хорошо, тогда я ставлю минус.

                                                                                            MyNameIsIgor, какие вы используете (если используете) реализации модели акторов в боевых системах, в частности, на С++?

                                                                                            Цитата MyNameIsIgor @
                                                                                            В вашем примере нет ООП (или вы его не показали). Потому что для пользователя нет никакого профита от наследования - по вашим словам, это лишь артефакт реализации.

                                                                                            Пользователю прямого профита нет, но разработчик может при необходимости добавить что-то обобщающее. Как это сделано в QObject. И как бы это противоричиво с YAGNI не звучало.

                                                                                            А часть проблем разного типа под капотом SO могут решиться с помощью привязки к нативному или не очень smart_ptr/ptr. Также с помощью только него можно создавать акторы/агенты, выполняющие обобщенные действия (например принимать одиночные собщения, подождать, отправить пачку дальше). Но общий предок позволяет сделать ещё больше.
                                                                                            Сообщение отредактировано: bsivko -
                                                                                              Цитата eao197 @
                                                                                              А как бы вы пример отформатировали?
                                                                                              Та вот как в последнем примере нормально. В принципе мне и примеры в первом посту вполне приемлемы с определённой точки зрения, но то я, я в буст-лямбдах на буст-функциях одно время зависал конкретно, а то korvin, ему сам Плюсовый синтаксис как таковой не очень родной. Вот и спросил.
                                                                                              Цитата MyNameIsIgor @
                                                                                              Ужас или нет, но... зачем?
                                                                                              Ну а почему нет? Мне как заядлому метапрограммеру писать подобное абсолютно не в лом. И это легко и сахарно решает вдруг (?) возникшую из-за особенностей архитектуры либы маленькую проблемку.

                                                                                              Ваш диалог был бы более конструктивным, если б шёл не вокруг сферических философий, а вокруг конкретики. Пусть и синтетической. Пока вы бросаетесь из одной тему в другую в пределах одного поста и т. же о. строите ответы, от диспута будет мало проку.
                                                                                                Цитата Qraizer @
                                                                                                Ваш диалог был бы более конструктивным, если б шёл не вокруг сферических философий, а вокруг конкретики. Пусть и синтетической. Пока вы бросаетесь из одной тему в другую в пределах одного поста и т. же о. строите ответы, от диспута будет мало проку.


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

                                                                                                Если будут вопросы о чем-то еще, постараюсь максимально полно ответить.
                                                                                                  Цитата eao197 @
                                                                                                  Так об этом сразу было сказано: в плане сопоставления с образцом при разборе данных сообщения SObjectizer не идет ни в какое сравнение с libcppa.

                                                                                                  :wacko: Какое сопоставление с образцом? Я поставил минус за необходимость наследования.
                                                                                                  Цитата eao197 @
                                                                                                  Может вы сначала попробуете описать преимущества этого?

                                                                                                  Я уже сказал - хочу не париться с передачей enum. Только не надо рассказывать, что мне это лишнее.
                                                                                                  Цитата eao197 @
                                                                                                  Поскольку вот мы сначала работали без наследования. Из-за этого приходилось создавать дополнительные объекты со счетчиками ссылок. Не было возможностей просто так переадресовать тот же самый экземпляр сообщения в новый send или серию новых send-ов. И т.д. по мелочам. Отказались от всего этого, жизнь стала лучше

                                                                                                  Чем нельзя внутри реализации заворачивать сообщения в
                                                                                                  ExpandedWrap disabled
                                                                                                    template<class T>
                                                                                                    struct msg : message_t
                                                                                                    {
                                                                                                      T value;
                                                                                                    };

                                                                                                  ?
                                                                                                  Цитата eao197 @
                                                                                                  Похоже, здесь опять какое-то недопонимание.

                                                                                                  Цитата, на которую я изначально отвечал
                                                                                                  Цитата eao197 @
                                                                                                  Мне не суть важно, насколько libcppa и SObjectizer конкурируют друг с другом. Намного важнее то, оставляют ли они C++ разработчиков в рамках C++ или же люди все-таки уходят в Erlang, Scala или еще куда-нибудь. Берут какую-нибудь Akka, а потом узкие места пытаются переписать на C или начинают бороться с GC. Тогда как можно было получить более качественный результат в C++.

                                                                                                  В моём понимании, вы утверждаете, что libcppa "уводит" людей от C++, и в этом качестве идёт противопоставление с SO, который, по вашим представлениям, более C++-каноничен. Ещё вы утверждаете, что такой "уход" даёт менее качественный результат. Если я понял правильно, то повторяю вопрос: по каким критериям вы оценили свой результат (SO) как более качественный?
                                                                                                  Цитата eao197 @
                                                                                                  Попробую вот так объяснить. С начала 2000-х идет большой отток разработчиков из C++ в другие ниши (в основном в Java, частично в C#). В свое время это было оправдано, т.к. C++ развивался очень медленно. Да и память с гигагерцами никто не считал. Однако, время прошло, писать на C++ сейчас намного проще и безопаснее, а за счет некоторых возможностей языка (rvalue references, например) код получается еще быстрее и надежнее. Плюс на расход памяти и на мощность компьютеров вновь обращают внимание. Если лет 8-мь назад можно было встретить радостные упоминания, что RoR приложение отмасштабировано на 1000 серверов, то сейчас уже чаще заходит речь о другом: зачем платить за 1000 серверов с RoR приложением там, где можно обойтись 200 с Lift-приложением. Т.е. для возвращения достаточного интереса к использованию C++ вместо Java/C# сейчас больше условий, чем 10 лет назад. И, если этому поспособствуют библиотеки вроде libcppa, jss или SObjectizer, то это хорошо. Даже если 99% процентов C++ников будут пользоваться libcppa, а на долю jss и SO придется по 0.5%.

                                                                                                  На форуме есть целый раздел Holy wars, там обсуждают подобные вещи. С написанным я не согласен, да.
                                                                                                  Цитата eao197 @
                                                                                                  Это не принципиальное ограничение обусловленное какими-то архитектурными особенностями. Если кому-то потребуется, то можно будет сделать и такой вариант

                                                                                                  Я бы настоятельно рекомендовал его сделать.
                                                                                                  Цитата bsivko @
                                                                                                  MyNameIsIgor, какие вы используете (если используете) реализации модели акторов в боевых системах, в частности, на С++?

                                                                                                  Никаких.
                                                                                                  Цитата bsivko @
                                                                                                  Пользователю прямого профита нет, но разработчик может при необходимости добавить что-то обобщающее. Как это сделано в QObject.

                                                                                                  В Qt пользователь может переопределять поведение в наследнике. В SO есть варианты использования, при которых пользователю необходимо переопределить поведение типов сообщений?

                                                                                                  Добавлено
                                                                                                  Цитата Qraizer @
                                                                                                  Ну а почему нет? Мне как заядлому метапрограммеру писать подобное абсолютно не в лом

                                                                                                  Мне много что не в лом. Да и вообще, предлагается библиотека или список того, что не в лом?
                                                                                                  Цитата eao197 @
                                                                                                  Ну я здесь в режиме ведомого

                                                                                                  Так ведите :-? Хотя бы в стиле "а ещё мы умеем вот так".
                                                                                                  Сообщение отредактировано: MyNameIsIgor -
                                                                                                    Цитата MyNameIsIgor @
                                                                                                    Цитата eao197 @
                                                                                                    Так об этом сразу было сказано: в плане сопоставления с образцом при разборе данных сообщения SObjectizer не идет ни в какое сравнение с libcppa.

                                                                                                    :wacko: Какое сопоставление с образцом? Я поставил минус за необходимость наследования.

                                                                                                    Значит в процессе разговора я не понял, за что именно минус.

                                                                                                    Цитата MyNameIsIgor @
                                                                                                    Цитата eao197 @
                                                                                                    Может вы сначала попробуете описать преимущества этого?

                                                                                                    Я уже сказал - хочу не париться с передачей enum. Только не надо рассказывать, что мне это лишнее.

                                                                                                    Ну, с учетом того, что в бою вы акторов в C++ не используете, не буду.

                                                                                                    Цитата MyNameIsIgor @
                                                                                                    Цитата eao197 @
                                                                                                    Поскольку вот мы сначала работали без наследования. Из-за этого приходилось создавать дополнительные объекты со счетчиками ссылок. Не было возможностей просто так переадресовать тот же самый экземпляр сообщения в новый send или серию новых send-ов. И т.д. по мелочам. Отказались от всего этого, жизнь стала лучше

                                                                                                    Чем нельзя внутри реализации заворачивать сообщения в
                                                                                                    ExpandedWrap disabled
                                                                                                      template<class T>
                                                                                                      struct msg : message_t
                                                                                                      {
                                                                                                        T value;
                                                                                                      };

                                                                                                    ?

                                                                                                    А пользователь что будет отсылать? Экземпляр объекта T? Как он попадет внутрь msg? Через copy, а еще лучше, move-конструктор? Тогда, если T -- это не элементарный тип, пользователю нужно будет писать этот конструктор для своего Т.
                                                                                                    Далее, когда агент получает экземпляр T и хочет именно его передать в серию новых send-ов, как это сделать? В libcppa для этого, как я понял, можно специальным методом получить ссылку на текущее обрабатываемое агентом сообщение. Но это создаст сложности, если мы захотим разрешить агенту работать одновременно на нескольких контекстах, на каждом из которых будет обрабатываться свое собственное сообщение.

                                                                                                    Т.е. все это решаемо, но с наследованием от общего предка все получается проще и понятнее.

                                                                                                    Далее, всегда есть вероятность, что с сообщением нужно будет ассоциировать какое-то новое поведение. Например, признак того, может ли это сообщение безопасно игнорироваться при переполнении очереди получателя. В случае с общим базовым типом может быть добавлен виртуальный метод, который будет переопределен в наследнике. Ну и т.д.
                                                                                                    Цитата MyNameIsIgor @
                                                                                                    Цитата eao197 @
                                                                                                    Мне не суть важно, насколько libcppa и SObjectizer конкурируют друг с другом. Намного важнее то, оставляют ли они C++ разработчиков в рамках C++ или же люди все-таки уходят в Erlang, Scala или еще куда-нибудь. Берут какую-нибудь Akka, а потом узкие места пытаются переписать на C или начинают бороться с GC. Тогда как можно было получить более качественный результат в C++.

                                                                                                    В моём понимании, вы утверждаете, что libcppa "уводит" людей от C++, и в это качестве идёт противопоставление с SO, который, по вашим представления, более C++-каноничен. Ещё вы утверждаете, что такой "уход" даёт менее качественный результат. Если я понял правильно, то повторяю вопрос: по каким критериям вы оценили свой результат (SO) как более качественный?

                                                                                                    Нет, вы не правильно понимаете. Я надеюсь, что библиотеки вроде libcppa, jss и SObjectizer будут задерживать разработчиков в C++.

                                                                                                    Кроме того, я думаю, что написание требовательных к производительности приложений на Java/Scala/C# в некоторых областях ставит перед разработчиками проблемы, которые легче решаются в C++. В частности, контроль за расходом памяти и отсутствием издержек GC, а так же более простой контроль за ресурсами посредством идеомы RAII (особенно это актуально для Java). В таких случаях использование C++ делает результат качественнее из-за уменьшения требований к памяти, более высокой скорости работы, более надежному поведению и лучшему контролю за ресурсами. Впрочем, поскольку вы считаете, что это тема для Holy War, то здесь ее развивать смысла нет.

                                                                                                    Цитата MyNameIsIgor @
                                                                                                    Цитата eao197 @
                                                                                                    Это не принципиальное ограничение обусловленное какими-то архитектурными особенностями. Если кому-то потребуется, то можно будет сделать и такой вариант

                                                                                                    Я бы настоятельно рекомендовал его сделать.

                                                                                                    Ок, спасибо, постараемся учесть в будущих версиях.
                                                                                                    Цитата MyNameIsIgor @
                                                                                                    Цитата bsivko @
                                                                                                    MyNameIsIgor, какие вы используете (если используете) реализации модели акторов в боевых системах, в частности, на С++?

                                                                                                    Никаких.

                                                                                                    Правильно я понимаю, что boost.fibers вы в продакшене так же не используете?

                                                                                                    Добавлено
                                                                                                    Цитата MyNameIsIgor @
                                                                                                    Так ведите


                                                                                                    Э... Как бы в паре "ведущий"-"ведомый" партию ведет ведущий, а не ведомый.
                                                                                                      Цитата MyNameIsIgor @
                                                                                                      В Qt пользователь может переопределять поведение в наследнике.

                                                                                                      Если вы формулируете именно таким образом, то это противоречит LSP.

                                                                                                      Цитата MyNameIsIgor @
                                                                                                      В SO есть варианты использования, при которых пользователю необходимо переопределить поведение типов сообщений?

                                                                                                      Если имеется ввиду все то множество методов в QObject, то оно вместе со всеми деревьями и прочими потрохами в настоящее время в SO отсутствует. В этом плане SO происходит только доставка.
                                                                                                      Если хочется прикрутить к сообщению какие-то свои методы, виртуальные и не совсем (изменяющие поведение в наследнике), то пожалуйста.
                                                                                                      Сообщение отредактировано: bsivko -
                                                                                                        Цитата Qraizer @
                                                                                                        код без кучи переносов строк выглядит приятнее. А, korvin?

                                                                                                        Обычно да, но длинные составные имена при таком количестве параметров... Да и :: со snake case плохо сочетается, ИМХО, т.к. выглядит "жирнее" и тем самым намекает на более сильную связь символов =/
                                                                                                          Цитата eao197 @
                                                                                                          В libcppa для этого, как я понял, можно специальным методом получить ссылку на текущее обрабатываемое агентом сообщение. Но это создаст сложности, если мы захотим разрешить агенту работать одновременно на нескольких контекстах, на каждом из которых будет обрабатываться свое собственное сообщение.

                                                                                                          А это создаст либо сложности сложности, либо оверхед и в вашем случае:
                                                                                                          1. Пессимистичная синхронизация - когда мы предполагаем, что обработчики одного и того же сообщения его всегда изменяют, требует от нас мьютекса для обработки в разных потоках - оверхед
                                                                                                          2. Ручное задание окружения - мы применяем мьютекс только для тех обработчиков, которые это указали, т.е. изменяют сообщение - сложности
                                                                                                          Цитата eao197 @
                                                                                                          Далее, всегда есть вероятность, что с сообщением нужно будет ассоциировать какое-то новое поведение. Например, признак того, может ли это сообщение безопасно игнорироваться при переполнении очереди получателя. В случае с общим базовым типом может быть добавлен виртуальный метод, который будет переопределен в наследнике. Ну и т.д.

                                                                                                          Сомнительный вариант...
                                                                                                          Цитата eao197 @
                                                                                                          Правильно я понимаю, что boost.fibers вы в продакшене так же не используете?

                                                                                                          Нет, не использую.
                                                                                                          Цитата eao197 @
                                                                                                          Как бы в паре "ведущий"-"ведомый" партию ведет ведущий, а не ведомый.

                                                                                                          У нас не танцы. А вы можете не только отвечать на вопросы.
                                                                                                          Цитата bsivko @
                                                                                                          Если вы формулируете именно таким образом, то это противоречит LSP.

                                                                                                          С чего бы? Переопределять поведение можно и без нарушения конртакта QObject.
                                                                                                            Цитата MyNameIsIgor @
                                                                                                            Цитата eao197 @
                                                                                                            В libcppa для этого, как я понял, можно специальным методом получить ссылку на текущее обрабатываемое агентом сообщение. Но это создаст сложности, если мы захотим разрешить агенту работать одновременно на нескольких контекстах, на каждом из которых будет обрабатываться свое собственное сообщение.

                                                                                                            А это создаст либо сложности сложности, либо оверхед и в вашем случае:
                                                                                                            1. Пессимистичная синхронизация - когда мы предполагаем, что обработчики одного и того же сообщения его всегда изменяют, требует от нас мьютекса для обработки в разных потоках - оверхед
                                                                                                            2. Ручное задание окружения - мы применяем мьютекс только для тех обработчиков, которые это указали, т.е. изменяют сообщение - сложности

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

                                                                                                            Так что, похоже, мы о разных ситуациях говорим.

                                                                                                            Цитата MyNameIsIgor @
                                                                                                            Цитата eao197 @
                                                                                                            Далее, всегда есть вероятность, что с сообщением нужно будет ассоциировать какое-то новое поведение. Например, признак того, может ли это сообщение безопасно игнорироваться при переполнении очереди получателя. В случае с общим базовым типом может быть добавлен виртуальный метод, который будет переопределен в наследнике. Ну и т.д.

                                                                                                            Сомнительный вариант...

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

                                                                                                            Цитата MyNameIsIgor @
                                                                                                            Цитата eao197 @
                                                                                                            Как бы в паре "ведущий"-"ведомый" партию ведет ведущий, а не ведомый.

                                                                                                            У нас не танцы. А вы можете не только отвечать на вопросы.

                                                                                                            Так мы же в разных ситуациях. Я о SO знаю много. Для меня сложно даже представить, что в SO можно не знать.
                                                                                                            Поэтому режим, когда меня спрашивают, а я отвечаю, выглядит вполне логичным.
                                                                                                              Цитата MyNameIsIgor @
                                                                                                              С чего бы? Переопределять поведение можно и без нарушения конртакта QObject.

                                                                                                              Можно. А можно и нарушением. Но узнаете об этом только тогда, когда произойдет что-то страшное.

                                                                                                              Наверное я что-то пропустил, но Qt разработан со сторогим соблюдением DbC? Где можно взглянуть на точные, верифицируемые, и формализованные условия класса QObject?
                                                                                                                Цитата eao197 @
                                                                                                                Речь не о том

                                                                                                                Хз. Вот ваши слова
                                                                                                                Цитата eao197 @
                                                                                                                Далее, когда агент получает экземпляр T и хочет именно его передать в серию новых send-ов, как это сделать?

                                                                                                                Жалеть передать именно его, а не его копию, можно лишь если мы хотим доступ к одному объекту из разных мест. Это требует синхронизации - на уровне библиотеки или обработчика. Если доступ из разных мест не нужен, то необходимости передавать именно этот же объект нету.
                                                                                                                Цитата eao197 @
                                                                                                                Для определенных классов сообщений (например, поток данных с часто опрашиваемых датчиков) вполне себе применимый: если из-за переполненной очереди мы не можем обработать текущий замер, то его можно проигнорировать, т.к. через секунду-другую все равно будет идти обновленное значение.

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

                                                                                                                Добавлено
                                                                                                                Цитата bsivko @
                                                                                                                Можно. А можно и нарушением. Но узнаете об этом только тогда, когда произойдет что-то страшное.

                                                                                                                Ну, давайте запретим любое переопределение методов :lol: Чтобы идея eao197 о виртуальном методе приоритета сообщения накрылась медным тазом.
                                                                                                                Только какое это всё имеет отношение к необходимости наследовать сообщения от общего предка, мне не понятно.
                                                                                                                Цитата bsivko @
                                                                                                                Наверное я что-то пропустил

                                                                                                                Бывает...
                                                                                                                Цитата bsivko @
                                                                                                                но Qt разработан со сторогим соблюдением DbC

                                                                                                                Проектирование по контракту - не наука, а набор медитативных практик. Полученных из опыта. Потому "строгих" критериев не будет.
                                                                                                                Цитата bsivko @
                                                                                                                Где можно взглянуть на точные, верифицируемые, и формализованные условия класса QObject?

                                                                                                                Пока программирование не перейдёт хотя бы на зависимые типы, обо всем этом вы можете забыть и просто прочитать документацию. Помогает ;)
                                                                                                                  Цитата MyNameIsIgor @
                                                                                                                  Цитата eao197 @
                                                                                                                  Далее, когда агент получает экземпляр T и хочет именно его передать в серию новых send-ов, как это сделать?

                                                                                                                  Жалеть передать именно его, а не его копию, можно лишь если мы хотим доступ к одному объекту из разных мест. Это требует синхронизации - на уровне библиотеки или обработчика. Если доступ из разных мест не нужен, то необходимости передавать именно этот же объект нету.

                                                                                                                  И в libcppa, и в SObjectizer один и тот же экземпляр сообщения передается всем получателям одновременно. Это просто значительным образом снижает издержки (особенно, когда речь идет не о int-ах или atom-ах). И задача корректного обращения с этим экземпляром решается с участием пользователя.
                                                                                                                  В libcppa это производится за счет тактики copy-on-write (однако пользователь должен явно обозначать тип доступа к данным), в SObjectizer изменение значения экземпляра сообщения -- это undefined behavior: если пользователь захотел, пусть делает это на свой страх и риск. Поэтому все обработчики в SObjectizer получают сообщение-инцидент по константной ссылке.
                                                                                                                  Передать именно тот самый объект-сообщение бывает необходимо, если сообщение "тяжелое", например, содержит текст, который нужно зашифровать и подписать электронной подписью. Если такое сообщение проходит через несколько стадий обработки (а каждая стадия -- это свой агент), то копирование даже десятка Кб при пересылке сообщения -- уже накладно.

                                                                                                                  Цитата MyNameIsIgor @
                                                                                                                  Цитата eao197 @
                                                                                                                  Для определенных классов сообщений (например, поток данных с часто опрашиваемых датчиков) вполне себе применимый: если из-за переполненной очереди мы не можем обработать текущий замер, то его можно проигнорировать, т.к. через секунду-другую все равно будет идти обновленное значение.

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

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

                                                                                                                  Я же говорю, проблема нетривиальная, требует совокупности подходов. Где-то нужно отдать приоритет мнению агента. Где-то можно положиться на характер данных в сообщении.
                                                                                                                    Цитата eao197 @
                                                                                                                    Передать именно тот самый объект-сообщение бывает необходимо, если сообщение "тяжелое"

                                                                                                                    Не катит - можно бросить [умный] указатель. Да и сам текст мы будем хранить в куче, потому перемещение в данном случае рулит.
                                                                                                                    Цитата eao197 @
                                                                                                                    Я же говорю, проблема нетривиальная, требует совокупности подходов. Где-то нужно отдать приоритет мнению агента. Где-то можно положиться на характер данных в сообщении.

                                                                                                                    Даже если и так, требование наследование не является необходимым.
                                                                                                                      Цитата MyNameIsIgor @
                                                                                                                      Пока программирование не перейдёт хотя бы на зависимые типы, обо всем этом вы можете забыть и просто прочитать документацию. Помогает ;)


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

                                                                                                                      А зависимые типы в продакшене вы уже используете?
                                                                                                                        Цитата eao197 @
                                                                                                                        Это не изменение поведения, это как раз ожидаемое поведение наследника -- сделать то, что от него просят, но каким-то частным способом

                                                                                                                        :facepalm: Ну, давайте, покажите общепринятое определения понятия "изменение поведения"...
                                                                                                                        Цитата eao197 @
                                                                                                                        А зависимые типы в продакшене вы уже используете?

                                                                                                                        Т.е. программирование ещё на них не перешло, но я уже использую :crazy:
                                                                                                                          Цитата MyNameIsIgor @
                                                                                                                          Цитата eao197 @
                                                                                                                          Передать именно тот самый объект-сообщение бывает необходимо, если сообщение "тяжелое"

                                                                                                                          Не катит - можно бросить [умный] указатель. Да и сам текст мы будем хранить в куче, потому перемещение в данном случае рулит.

                                                                                                                          Ну так message_t и есть тот самый умный указатель. Он и бросается, и перебрасывается при необходимости.

                                                                                                                          Цитата MyNameIsIgor @
                                                                                                                          Цитата eao197 @
                                                                                                                          Я же говорю, проблема нетривиальная, требует совокупности подходов. Где-то нужно отдать приоритет мнению агента. Где-то можно положиться на характер данных в сообщении.

                                                                                                                          Даже если и так, требование наследование не является необходимым.

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

                                                                                                                          Необходимым это не было. Но жизнь облегчило.
                                                                                                                            Цитата eao197 @
                                                                                                                            Ну так message_t и есть тот самый умный указатель. Он и бросается, и перебрасывается при необходимости.

                                                                                                                            И привносит оверхед счётчика.
                                                                                                                            Цитата eao197 @
                                                                                                                            Заходим на очередной круг

                                                                                                                            А как иначе?
                                                                                                                              Цитата MyNameIsIgor @
                                                                                                                              Ну, давайте запретим любое переопределение методов

                                                                                                                              Вы сейчас применяете дамский аргумент. Прошу вас заниматься софистикой в другом месте.

                                                                                                                              Цитата MyNameIsIgor @
                                                                                                                              Проектирование по контракту - не наука, а набор медитативных практик. Полученных из опыта. Потому "строгих" критериев не будет.

                                                                                                                              Прочитайте пожалуйста хотя бы определение.

                                                                                                                              Формализованность и верифицируемость - это необходимые условия для DbC.

                                                                                                                              Поэтому, я настойчиво рекомендую вам в дальнейшем не пользоваться понятиями, смысл которых вы не знаете. Даже если в ваш лексикон что-то перепало с барского стола DbC. Все эти слова сотрясают воздух, но не собеседника.
                                                                                                                                Цитата MyNameIsIgor @
                                                                                                                                Т.е. программирование ещё на них не перешло, но я уже использую

                                                                                                                                Ну кто же знает. Некоторые люди себе на жизнь Erlang-ом и Haskell-ем зарабатывали когда об этих языках широкая общественность еще и не знала.
                                                                                                                                Может и вы на какой-нибудь Adga2 или еще чем-нибудь уже во всю коммерческие проекты делаете.

                                                                                                                                Просто забавно получается. Ни libcppa, ни boost.fibers, ни зависимые типы вы реально не используете, но говорите, что на них можно. Это несколько настораживает ;)

                                                                                                                                Добавлено
                                                                                                                                Цитата MyNameIsIgor @
                                                                                                                                И привносит оверхед счётчика.


                                                                                                                                Конечно. Поскольку в C++ GC нет, то приходится работать со счетчиками ссылок. В том же libcppa это так же используется. Просто там пользователь об этом счетчике не сном, ни духом. SO про счетчик пользователь так же не сильно думает, но у нас он выставлен наружу через message_t.
                                                                                                                                  Цитата eao197 @
                                                                                                                                  Мы уже работали с сообщениями, где не нужно было наследоваться. По итогам решили ввести общий базовый тип

                                                                                                                                  А можно узнать, какие были аргументы за, какие против и какие из аргументов, в итоге, перевесили и почему?
                                                                                                                                  Ну так, чтоб каких-то производственных тайн не раскрывать :)
                                                                                                                                    У-тю-тю-тю, ещё один якобы умный :lool:
                                                                                                                                    Цитата bsivko @
                                                                                                                                    Прочитайте пожалуйста хотя бы определение.

                                                                                                                                    Формализованность и верифицируемость - это необходимые условия для DbC.

                                                                                                                                    Покажите цитату, где сказано, что они являются необходимыми условиями. А потом расскажите, как вы формально верифицируете программу на Eiffel.
                                                                                                                                    Цитата bsivko @
                                                                                                                                    Поэтому, я настойчиво рекомендую

                                                                                                                                    Если когда-нибудь ваше мнение станет мне интересно, я дам вам знать. До тех пор попусту не возбуждайтесь.
                                                                                                                                    Цитата eao197 @
                                                                                                                                    Просто забавно получается. Ни libcppa, ни boost.fibers, ни зависимые типы вы реально не используете, но говорите, что на них можно. Это несколько настораживает

                                                                                                                                    Штирлиц насторожился © :D Если вас что-то не устраивает в разговоре, это исключительно ваши проблемы, я вас не держу.
                                                                                                                                    Цитата eao197 @
                                                                                                                                    Конечно

                                                                                                                                    Конечно это минус в том случае, если копирование/перемещение сообщения дешевле счётчика.
                                                                                                                                      Цитата D_KEY @
                                                                                                                                      А можно узнать, какие были аргументы за, какие против и какие из аргументов, в итоге, перевесили и почему?

                                                                                                                                      Дело довольно давнее, с моим склерозом всего уже и не вспомнить.
                                                                                                                                      Точно помню, что в 2002, когда создавался SO-4, я специально закладывал возможность, чтобы любую структуру можно было отослать в виде сообщения. Но, т.к. рядом с ней нужно было иметь еще и некоторую метаинформацию, в частности, счетчик ссылок, то рядом с созданным пользователем объектом-сообщением еще и создавался мелкий объект-дескриптор. Это серьезные накладные расходы, т.к. любой дополнительный new/delete в многопоточном приложении -- это ощутимо, даже если связать с объектом-дескриптором отдельный эффективных аллокатор. Кроме того, выяснилось, что за все время использования SO-4 (а это уже 12 лет) ни разу не была использована возможность отослать в виде сообщения какую-то чужую структуру. Всегда это были специально подготовленные в качестве сообщения структуры данных.

                                                                                                                                      Поэтому, занимаясь SO-5, хотелось объединить и объект-сообщение, и нужную для него метаинформацию в одном блоке памяти. Общий базовый тип здесь выглядел наиболее простым и логичным вариантом. Кроме того, общий базовый класс позволил задействовать dynamic_cast для обеспечения большей безопасности операций. Ну и были идеи по добавлению в общего предка виртуальных методов для разных целей -- от валидации объекта сообщения (в SO-4 была такая фича, перед обработкой сообщения запускался его валидатор), до реакции на какие-то события (вроде переполнения очереди или игнорирования сообщения из-за того, что агент не смог его обработать). Но пока это все осталось в фантазиях. Хотя сама возможность сделать что-то подобное греет :)

                                                                                                                                      Не могу сказать, как на это дело повлияло то, что SO-5 разрабатывался в 2010, официально C++11 не был принят, и далеко не все компиляторы имели поддержку таких вещей, как rvalue references и move-semantic. Наверное так же повлияло, т.к. мы делали инструмент, который нужно было запускать в дело максимально быстро, а не ждать, когда появятся компиляторы с достаточным уровнем поддержки C++11.
                                                                                                                                        Я еще не смотрел вашу библиотеку, но разве при наличии даже требования к наследованию, сложно расширить интерфейс для обработки произвольных типов, которые бы уже внутри заворачивались в объект с нужными требованиями?
                                                                                                                                          Цитата D_KEY @
                                                                                                                                          Я еще не смотрел вашу библиотеку, но разве при наличии даже требования к наследованию, сложно расширить интерфейс для обработки произвольных типов, которые бы уже внутри заворачивались в объект с нужными требованиями?

                                                                                                                                          Не уверен, что понимаю, о чем именно идет речь. Полагаю, об одном из следующих вариантов:
                                                                                                                                          Есть внутренний тип message_t с нужным набором методов. Для конкретного пользовательского типа неявно строится наследник-обертка:
                                                                                                                                          ExpandedWrap disabled
                                                                                                                                            template< class USER_MESSAGE >
                                                                                                                                            struct concrete_msg_t : public message_t {
                                                                                                                                              USER_MESSAGE m_data;
                                                                                                                                              ... // Куча виртульных методов.
                                                                                                                                            };

                                                                                                                                          Далее, для получения concrete_msg_t<T> с дополнительными свойствами, например, с реакцией на переполнение очереди, поступаем одним из следующих способов. Способ 1:
                                                                                                                                          ExpandedWrap disabled
                                                                                                                                            // Пользователь в своем типе определяет метод queue_overload_reaction():
                                                                                                                                            class my_message {
                                                                                                                                              ...
                                                                                                                                              reaction queue_overload_reaction() const { ... }
                                                                                                                                            };
                                                                                                                                            // Наличие этого метода автоматически определяется при обращении к deliver_message:
                                                                                                                                            mbox->deliver_message( my_message(...) );

                                                                                                                                          Способ 2:
                                                                                                                                          ExpandedWrap disabled
                                                                                                                                            // При обращении к deliver_message передаются дополнительные свойства:
                                                                                                                                            mbox->deliver_message( my_message(...) ).with_queue_overload_reaction(...);

                                                                                                                                          Правильно я вас понял?

                                                                                                                                          Если правильно, то можно и так. Только вот мне ближе, когда все это делается в общем базовом классе, от которого пользователь наследуется. Может это и субъективное мнение, но вот не понимаю, что в таком подходе плохого.
                                                                                                                                            Цитата MyNameIsIgor @
                                                                                                                                            Покажите цитату, где сказано, что они являются необходимыми условиями. А потом расскажите, как вы формально верифицируете программу на Eiffel.

                                                                                                                                            Т.е. цитаты из вики вам недостаточно?

                                                                                                                                            Нужно ли вам объяснять, являются ли assert'ы формальными и/или верифицируемыми?

                                                                                                                                            На Eiffel никогда не верифицировал программ. И, вообще-то, DbC != Eiffel. И даже, утверждение (точнее, предикат) Eiffel => DbC не является истинным (стрелка тут импликация).

                                                                                                                                            И это все выходит за рамки текущей темы. Контрактов нет ни в Qt, ни в SO, и они редко где используются простыми программистами С++.

                                                                                                                                            Цитата MyNameIsIgor @
                                                                                                                                            Если когда-нибудь ваше мнение станет мне интересно, я дам вам знать. До тех пор попусту не возбуждайтесь.

                                                                                                                                            Когда вы ещё раз ляпнете что-нибудь про контракт, я вам дам знать.
                                                                                                                                            Сообщение отредактировано: bsivko -
                                                                                                                                              Цитата MyNameIsIgor @
                                                                                                                                              Штирлиц насторожился © :D Если вас что-то не устраивает в разговоре, это исключительно ваши проблемы, я вас не держу.

                                                                                                                                              Да как же я уйду, где ж еще получится пообсуждать практические проблемы с теоретиком :tong:

                                                                                                                                              Не обижайтесь, пожалуйста, это шутка.
                                                                                                                                                Цитата bsivko @
                                                                                                                                                Т.е. цитаты из вики вам недостаточно?

                                                                                                                                                Во-первых, вика - это не абсолютная истина, а информация для ознакомления. Во-вторых, там нет ничего про необходимость формальной спецификации.
                                                                                                                                                Цитата bsivko @
                                                                                                                                                Нужно ли вам объяснять, являются ли assert'ы формальными и/или верифицируемыми?

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

                                                                                                                                                Цитата eao197 @
                                                                                                                                                Да как же я уйду

                                                                                                                                                Вы правда хотите, чтобы я сказал?
                                                                                                                                                  Цитата MyNameIsIgor @
                                                                                                                                                  Мне много что не в лом. Да и вообще, предлагается библиотека или список того, что не в лом?
                                                                                                                                                  Ну так кому-то вон не в лом и на Билдере писать в объектной модели Дельфей. Всё относительно, а уж такая право мелочь, как мета-переходник от значения к типу, не достойна в качестве минуса привлекать пристальное внимание, коли большая часть остального в либе устраивает.

                                                                                                                                                  Добавлено
                                                                                                                                                  Цитата eao197 @
                                                                                                                                                  Т.е. все это решаемо, но с наследованием от общего предка все получается проще и понятнее.
                                                                                                                                                  Кстати вот. А не смотрели в сторону стратегий поведения? Они могут относительно дёшево избавить от общего предка, заменив полиморфизм на статический.
                                                                                                                                                    Цитата Qraizer @
                                                                                                                                                    Всё относительно, а уж такая право мелочь, как мета-переходник от значения к типу, не достойна в качестве минуса привлекать пристальное внимание, коли большая часть остального в либе устраивает

                                                                                                                                                    Да я же не против, что у всего есть плюсы и минусы. Просто зацепились за эту тему, другие роль ведомого подкинуть не позволяет :)
                                                                                                                                                      Цитата Qraizer @
                                                                                                                                                      Цитата eao197 @ Сегодня, 16:08
                                                                                                                                                      Т.е. все это решаемо, но с наследованием от общего предка все получается проще и понятнее.
                                                                                                                                                      Кстати вот. А не смотрели в сторону стратегий поведения? Они могут относительно дёшево избавить от общего предка, заменив полиморфизм на статический.

                                                                                                                                                      Не уверен, что понимаю о чем идет речь. При диспетчеризации сообщений именно что нужен обычный полиморфизм -- есть очередь объектов типа message_t, все это находится где-то глубоко внутри отдельной dll/so-шки, пользовательский код компилируется отдельно и потом уже линкуется с библиотекой SO-5. Как бы мы в пользовательском коде не игрались с шаблонами, стратегиями и статическим полиморфизмом, все равно это нужно будет как-то свести к поведению типа message_t.
                                                                                                                                                        Не, понятно, что гетерогенные контейнеры на статике собирать категорически неудобно. Хоть и можно. Но я и не знаю внутренней кухни SO, я просто отталкиваюсь от вашего же заявления, что единый базовый класс был необязателен.
                                                                                                                                                        Конкретно в том, что я имел в виду, подразумевалось, что различные те или иные кастомные характеристики можно было бы возложить на компайл-тайм стратегии вместо ран-тайм полиморфизма. В конце концов я представляю агентов как сущности с характеристиками, заданными при их проектировании, и им совершенно незачем менять их у себя в ран-тайм.
                                                                                                                                                          Цитата Qraizer @
                                                                                                                                                          В конце концов я представляю агентов как сущности с характеристиками, заданными при их проектировании, и им совершенно незачем менять их у себя в ран-тайм.


                                                                                                                                                          Да, собственно говоря, так оно и есть.
                                                                                                                                                            Цитата MyNameIsIgor @
                                                                                                                                                            Ну, меня интересует не программа с точно такой же семантикой, а просто аналог конструкций
                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                  // a philosopher that receives {eat} stops thinking and becomes hungry
                                                                                                                                                                          thinking = (
                                                                                                                                                                              on(atom("eat")) >> [=] {
                                                                                                                                                                                  become(hungry);
                                                                                                                                                                                  send(left, atom("take"), this);
                                                                                                                                                                                  send(right, atom("take"), this);
                                                                                                                                                                              }
                                                                                                                                                                          );
                                                                                                                                                                          // wait for the first answer of a chopstick
                                                                                                                                                                          hungry = (
                                                                                                                                                                              on(atom("taken"), left) >> [=] {
                                                                                                                                                                                  become(waiting_for(right));
                                                                                                                                                                              },
                                                                                                                                                                              on(atom("taken"), right) >> [=] {
                                                                                                                                                                                  become(waiting_for(left));
                                                                                                                                                                              },
                                                                                                                                                                              on<atom("busy"), actor>() >> [=] {
                                                                                                                                                                                  become(denied);
                                                                                                                                                                              }
                                                                                                                                                                          );
                                                                                                                                                                          // philosopher was not able to obtain the first chopstick
                                                                                                                                                                          denied = (
                                                                                                                                                                              on(atom("taken"), arg_match) >> [=](const actor& ptr) {
                                                                                                                                                                                  send(ptr, atom("put"), this);
                                                                                                                                                                                  send(this, atom("eat"));
                                                                                                                                                                                  become(thinking);
                                                                                                                                                                              },
                                                                                                                                                                              on<atom("busy"), actor>() >> [=] {
                                                                                                                                                                                  send(this, atom("eat"));
                                                                                                                                                                                  become(thinking);
                                                                                                                                                                              }
                                                                                                                                                                          );
                                                                                                                                                                          // philosopher obtained both chopstick and eats (for five seconds)
                                                                                                                                                                          eating = (
                                                                                                                                                                              on(atom("think")) >> [=] {
                                                                                                                                                                                  send(left, atom("put"), this);
                                                                                                                                                                                  send(right, atom("put"), this);
                                                                                                                                                                                  delayed_send(this, seconds(5), atom("eat"));
                                                                                                                                                                                  aout(this) << name
                                                                                                                                                                                             << " puts down his chopsticks and starts to think\n";
                                                                                                                                                                                  become(thinking);
                                                                                                                                                                              }
                                                                                                                                                                          );

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

                                                                                                                                                            А вот интересно, если знаете, конечно, как в libcppa при наследовании от какого-то уже имеющегося класса агента модифицировать определение состояния? Вот, например, определил родительский класс в состоянии denied обработчики атомов denied и busy. А потомок хочет заменить обработчик атома busy и добавить обработчик еще одного атома tryagain. Можно это в libcppa сделать?
                                                                                                                                                              Цитата eao197 @
                                                                                                                                                              А вот интересно, если знаете, конечно, как в libcppa при наследовании от какого-то уже имеющегося класса агента модифицировать определение состояния? Вот, например, определил родительский класс в состоянии denied обработчики атомов denied и busy. А потомок хочет заменить обработчик атома busy и добавить обработчик еще одного атома tryagain. Можно это в libcppa сделать?

                                                                                                                                                              Без понятия. Ну, кроме создания своего состояния в потомке и присвоения его состоянию в предке, но это не декомпозиция по обработчикам, да.
                                                                                                                                                                Цитата MyNameIsIgor @
                                                                                                                                                                Без понятия. Ну, кроме создания своего состояния в потомке и присвоения его состоянию в предке, но это не декомпозиция по обработчикам, да.

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

                                                                                                                                                                SObjectizer в этом плане дает больше возможностей разработчику. Подписку на сообщения в конкретном состоянии можно изменить -- отменить старую или добавить новую.
                                                                                                                                                                  Цитата eao197 @
                                                                                                                                                                  SObjectizer в этом плане дает больше возможностей разработчику. Подписку на сообщения в конкретном состоянии можно изменить -- отменить старую или добавить новую.

                                                                                                                                                                  Настораживает. Грозит непонятными проблемами и сильной связностью.
                                                                                                                                                                    Цитата MyNameIsIgor @
                                                                                                                                                                    Настораживает. Грозит непонятными проблемами и сильной связностью.

                                                                                                                                                                    Наследование -- это и так очень сильная связанность.
                                                                                                                                                                    А реакцию на сообщение можно рассматривать как виртуальный метод. В принципе, в Smalltalk и Ruby это почти так и есть -- вызов метода как отсылка сообщения, обработчик которого может быть переопределен в производном классе.
                                                                                                                                                                    Соответственно, замена обработчика в производном классе -- вполне нормальна вещь. Как и расширение списка состояний и/или списка обработчиков в конкретном состоянии.
                                                                                                                                                                      Цитата eao197 @
                                                                                                                                                                      В принципе, в Smalltalk и Ruby это почти так и есть -- вызов метода как отсылка сообщения, обработчик которого может быть переопределен в производном классе.

                                                                                                                                                                      Я в курсе, и подход C++/C# с чётким декларированием точек расширения лучше.
                                                                                                                                                                      Цитата eao197 @
                                                                                                                                                                      Соответственно, замена обработчика в производном классе -- вполне нормальна вещь.

                                                                                                                                                                      Ну, если писать их, всё держа в уме, что могу подменить любой обработчик, то, наверное, нормальная.
                                                                                                                                                                        Цитата MyNameIsIgor @
                                                                                                                                                                        Во-первых, вика - это не абсолютная истина, а информация для ознакомления.

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

                                                                                                                                                                        Цитата MyNameIsIgor @
                                                                                                                                                                        Потому что ни assert'ы, ни котракты (в смысле языковых возможностей) не являются формальной верификацией.

                                                                                                                                                                        Где у меня вообще упоминается формальная верификация??

                                                                                                                                                                        Вам был дан элементарный вопрос на знание базовых понятий - формальный и верифицируемый.

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

                                                                                                                                                                        Цитата MyNameIsIgor @
                                                                                                                                                                        Или попробую объяснить по-другому: контракты и утверждения выполняют ту же работу, которую можно выполнить с помощью модульного тестирования.

                                                                                                                                                                        DbC не имеет никакого отношения к тестированию. Потому что DbC = Design by Contract, это примеяется на ранних стадиях проектирования и затем затрагивает все остальное. А во что выльется в дальнейшем - в fail hard, автоматическую формальную ферификацию, defense programming, ... - это уже совсем другая история.
                                                                                                                                                                          Цитата bsivko @
                                                                                                                                                                          Потому что если бы вы прочитали хотя бы одну книгу Мейера, то таких вопросов у вас бы не возникло.
                                                                                                                                                                          ...
                                                                                                                                                                          Вам был дан элементарный вопрос на знание базовых понятий - формальный и верифицируемый.
                                                                                                                                                                          ...
                                                                                                                                                                          Утверждения и предикаты в контрактном программировании как раз должны быть формализованными и верифицируемыми, чтобы такие как вы существительные с прилагательными не путали.

                                                                                                                                                                          Мне кажется, что вы путаете математическое описание АТД и его реализацию в виде класса.

                                                                                                                                                                          Цитата
                                                                                                                                                                          Переход от АТД к классам включает существенное изменение стилистики: введение изменений и императивных аргументов.

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

                                                                                                                                                                          ExpandedWrap disabled
                                                                                                                                                                            put: STACK [G] x  G -> STACK [G]


                                                                                                                                                                          задающей операцию, которая возвращает новый стек, а не изменяет существующий.

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

                                                                                                                                                                          Такое изменение стиля отражает императивные настроения, преобладающие при разработке ПО. (В качестве синонима слова "императивный" иногда используется термин "операционный"). При этом потребуется изменять аксиомы АТД. Аксиомы стеков A1 и A4, которые имели вид

                                                                                                                                                                          ExpandedWrap disabled
                                                                                                                                                                            (A1) item (put (s, x)) = x
                                                                                                                                                                            (A4) not empty (put (s, x))


                                                                                                                                                                          превратятся в императивной форме в предложение, называемое постусловием программы (routine postcondition), вводимое ключевым словом ensure (обеспечивает):
                                                                                                                                                                          ExpandedWrap disabled
                                                                                                                                                                            put (x: G) is
                                                                                                                                                                                  -- Втолкнуть x на вершину стека
                                                                                                                                                                               require
                                                                                                                                                                                  ... Предусловие (если таковое имеется) ...
                                                                                                                                                                               do
                                                                                                                                                                                  ... Соответствующая реализация (если известна) ...
                                                                                                                                                                               ensure
                                                                                                                                                                                  item = x
                                                                                                                                                                                  not empty
                                                                                                                                                                               end



                                                                                                                                                                          Так же можете посмотреть главу книги "Основы объектно-ориентированного программирования" про проектирование по контракту, ту часть, где описано связывание АТД и классов, где рассказано про утверждения, про их отличия от формальной спецификации аксиом и предусловий АТД и пр.
                                                                                                                                                                          Сообщение отредактировано: D_KEY -
                                                                                                                                                                            Цитата MyNameIsIgor @
                                                                                                                                                                            Просто зацепились за эту тему, другие роль ведомого подкинуть не позволяет

                                                                                                                                                                            Вот, после поверхностного знакомства с libcppa вырисовалось
                                                                                                                                                                              Цитата eao197
                                                                                                                                                                              libcppa заточен на то, что в приложении будет работать всего один экземпляр рантайма libcppa

                                                                                                                                                                              Вот, кстати, откуда это?
                                                                                                                                                                              Сообщение отредактировано: MyNameIsIgor -
                                                                                                                                                                                Цитата MyNameIsIgor @
                                                                                                                                                                                Вот, кстати, откуда это?


                                                                                                                                                                                Сначала из исходников. Полез посмотреть, как shutdown тамошний устроен.
                                                                                                                                                                                Потом следы в PDF-ке нашлись, там расписано, как они self реализуют.
                                                                                                                                                                                  Цитата eao197 @
                                                                                                                                                                                  Сначала из исходников. Полез посмотреть, как shutdown тамошний устроен.
                                                                                                                                                                                  Потом следы в PDF-ке нашлись, там расписано, как они self реализуют.

                                                                                                                                                                                  В исходниках не видел. Но по pdf мне не очевидно, что при двух рантаймах случится что-то страшное.
                                                                                                                                                                                    Возвращаясь в выборке сообщений из ящика. Имеет ли смысл не удалять сообщения, если для них не найден обработчик? Это позволило бы, например, пустому стэку ответить на pop после того, как в него что-то поместят.
                                                                                                                                                                                      Цитата MyNameIsIgor @
                                                                                                                                                                                      Возвращаясь в выборке сообщений из ящика. Имеет ли смысл не удалять сообщения, если для них не найден обработчик? Это позволило бы, например, пустому стэку ответить на pop после того, как в него что-то поместят.


                                                                                                                                                                                      Ну а какой смысл отправителю pop-а ждать в этом случае? И сколько он будет ждать?
                                                                                                                                                                                      Кроме того, допустим идет большой поток pop-ов к пустому стеку, они не выбрасываются, а скапливаются в очереди. Очередь растет, по сути, происходит утечка ресурсов.
                                                                                                                                                                                        извините за нубский вопрос, но я всё равно не понимаю, зачем нужны эти акторы без зеленых потоков? при том, что у меня есть небольшой опыт в Эрланге, т.е. я вроде бы должен понимать, что это за акторы.
                                                                                                                                                                                        мне кажется, что б.ч. того что в этой теме описывается, уже есть (как минимум) в Qt
                                                                                                                                                                                        хочется publish/subscribe - signals+slots
                                                                                                                                                                                        доставка одному конкретному адресату - invokeMethod
                                                                                                                                                                                        из одного потока в другой - QueuedConnection
                                                                                                                                                                                        для любителей острых ощущений в поиске дедлоков даже есть BlockingQueuedConnection, который позволяет дождаться ответа из другого потока
                                                                                                                                                                                        передавать в сообщении можно абсолютно любые типы, не нужно никакого общего наследника, просто qRegisterMetaType + Q_DECLARE_METATYPE
                                                                                                                                                                                        диспетчеризация по обработчикам из коробки, т.е. Qt сама вызовет нужный метод

                                                                                                                                                                                        остается только 2 момента:
                                                                                                                                                                                        1. невозможно запросить длину очереди сообщений (хотя маленький патч в Qt имхо может это решить)
                                                                                                                                                                                        и в целом, асинхронные сигналы не рекомендуют использовать для интенсивных producer/consumer. Обычная очередь в мютексом будет быстрее и проще контролировать
                                                                                                                                                                                        2. аналог линков Эрланга - при желании можно чуть пошаманить с try/catch вокруг всего event loop'a Qt, вроде никакого rocket science тоже не будет.
                                                                                                                                                                                          Цитата Radagast @
                                                                                                                                                                                          извините за нубский вопрос, но я всё равно не понимаю, зачем нужны эти акторы без зеленых потоков? при том, что у меня есть небольшой опыт в Эрланге, т.е. я вроде бы должен понимать, что это за акторы.
                                                                                                                                                                                          мне кажется, что б.ч. того что в этой теме описывается, уже есть (как минимум) в Qt

                                                                                                                                                                                          Ваш вопрос можно разделить на две части:

                                                                                                                                                                                          * зачем нужны акторы, если большая часть их функциональности может быть обеспечена тем, что еще есть в разных фреймворках (в частности, в Qt);
                                                                                                                                                                                          * зачем нужны акторы не на зеленых потоках.

                                                                                                                                                                                          По первой части ответ довольно прост. Если вы разбиваете свою задачу на отдельные кусочки посредством того же Qt, вам нужно вручную управлять потоками, их запуском и остановом, привязыванием к ним тех или иных QObject-ов. А так же выбирать форму взаимодействия между ними -- где-то signal/slot, где-то invokeMethod, где-то еще что-то. А потом заменять одно на другое в процессе сопровождения. Т.е. в итоге вы все равно сделаете большую часть того, что уже лежит под капотом в SObjectizer или libcppa, но своими руками и сами затем будете это сопровождать.

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

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

                                                                                                                                                                                            Цитата
                                                                                                                                                                                            нужно вручную управлять потоками, их запуском и остановом, привязыванием к ним тех или иных QObject-ов

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

                                                                                                                                                                                            спасибо, я всё понял
                                                                                                                                                                                              Цитата Radagast @
                                                                                                                                                                                              спасибо, я всё понял

                                                                                                                                                                                              Ну, чтобы не быть голословным. Недавно делал реализацию простого теста производительности "Хамелеоны".
                                                                                                                                                                                              Вот описание
                                                                                                                                                                                              Вот код реализации на SObjectizer.
                                                                                                                                                                                              Вот код аналога на Qt5 (этот код писал не я).

                                                                                                                                                                                              В реализации на Qt можно увидеть, что приходится давать явные команды на завершение работы рабочих нитей, а потом ожидать завершение их работы. В таком простом случае, где все создается и завершается в main-е, не страшно. Но в более сложных случаях, когда рабочие нити нужно создавать по необходимости, а потом завершать когда они становятся не нужны, это требует уже большей работы.

                                                                                                                                                                                              Ну и еще в Qt-шном варианте мне не очень нравится смесь из emit-ов и postEvent-ов.
                                                                                                                                                                                                Цитата eao197 @
                                                                                                                                                                                                Вот код реализации на SObjectizer.

                                                                                                                                                                                                Как-то многовато. http://play.golang.org/p/IjLcwII2Jl
                                                                                                                                                                                                  Цитата korvin @
                                                                                                                                                                                                  Как-то многовато. http://play.golang.org/p/IjLcwII2Jl


                                                                                                                                                                                                  Не удивлюсь, если на Erlang-е будет еще короче. Что это доказывает?

                                                                                                                                                                                                  Добавлено
                                                                                                                                                                                                  Цитата korvin @
                                                                                                                                                                                                  Как-то многовато. http://play.golang.org/p/IjLcwII2Jl

                                                                                                                                                                                                  Мне кажется, что вы не обеспечиваете одновременного старта всех хамелеонов. Т.е. два первых хамелеона могут завершить всю работу еще до того, как стартует третий и четвертый хамелеоны.
                                                                                                                                                                                                    Цитата eao197 @
                                                                                                                                                                                                    Ну, чтобы не быть голословным. Недавно делал реализацию простого теста производительности "Хамелеоны".
                                                                                                                                                                                                    Вот описание

                                                                                                                                                                                                    Ну, прямо скажем, не rocket science. :) На больную голову вполне решаемая задачка.
                                                                                                                                                                                                    ExpandedWrap disabled
                                                                                                                                                                                                      #include <QCoreApplication>
                                                                                                                                                                                                      #include <QThread>
                                                                                                                                                                                                      #include <QMutex>
                                                                                                                                                                                                      #include <QWaitCondition>
                                                                                                                                                                                                       
                                                                                                                                                                                                      #include <iostream>
                                                                                                                                                                                                       
                                                                                                                                                                                                      enum Color
                                                                                                                                                                                                      {
                                                                                                                                                                                                          Blue,
                                                                                                                                                                                                          Red,
                                                                                                                                                                                                          Yellow,
                                                                                                                                                                                                          Faded
                                                                                                                                                                                                      };
                                                                                                                                                                                                       
                                                                                                                                                                                                      enum Action
                                                                                                                                                                                                      {
                                                                                                                                                                                                          WaitForPeer,
                                                                                                                                                                                                          WasRandevous,
                                                                                                                                                                                                          ShouldPassBy,
                                                                                                                                                                                                          MustDie
                                                                                                                                                                                                      };
                                                                                                                                                                                                       
                                                                                                                                                                                                      class Chamelion;
                                                                                                                                                                                                       
                                                                                                                                                                                                      class RandevousPoint
                                                                                                                                                                                                      {
                                                                                                                                                                                                      public:
                                                                                                                                                                                                          RandevousPoint(int maxRandevous)
                                                                                                                                                                                                              : m_firstChamelion(nullptr)
                                                                                                                                                                                                              , m_maxRandevous(maxRandevous)
                                                                                                                                                                                                              , m_currentRandevous(0)
                                                                                                                                                                                                          {
                                                                                                                                                                                                              ;
                                                                                                                                                                                                          }
                                                                                                                                                                                                          
                                                                                                                                                                                                          ~RandevousPoint()
                                                                                                                                                                                                          {
                                                                                                                                                                                                              ;
                                                                                                                                                                                                          }
                                                                                                                                                                                                          
                                                                                                                                                                                                          Action ImHere(Chamelion &ch);
                                                                                                                                                                                                          
                                                                                                                                                                                                          void WaitForStart()
                                                                                                                                                                                                          {
                                                                                                                                                                                                              ;
                                                                                                                                                                                                          }
                                                                                                                                                                                                      private:
                                                                                                                                                                                                          QMutex m_guard;
                                                                                                                                                                                                          Chamelion *m_firstChamelion;
                                                                                                                                                                                                          int m_maxRandevous;
                                                                                                                                                                                                          int m_currentRandevous;    
                                                                                                                                                                                                      };
                                                                                                                                                                                                       
                                                                                                                                                                                                      class Chamelion : public QThread
                                                                                                                                                                                                      {
                                                                                                                                                                                                      public:
                                                                                                                                                                                                          Chamelion(const std::string &name, Color color, RandevousPoint &point)
                                                                                                                                                                                                              : m_metChamelions(0)
                                                                                                                                                                                                              , m_name(name)
                                                                                                                                                                                                              , m_currentColor(color)
                                                                                                                                                                                                              , m_point(point)
                                                                                                                                                                                                          {
                                                                                                                                                                                                              ;
                                                                                                                                                                                                          }
                                                                                                                                                                                                       
                                                                                                                                                                                                          ~Chamelion()
                                                                                                                                                                                                          {
                                                                                                                                                                                                          }
                                                                                                                                                                                                          
                                                                                                                                                                                                          void SwapColors(Chamelion &other)
                                                                                                                                                                                                          {
                                                                                                                                                                                                              m_guard.lock();
                                                                                                                                                                                                              std::swap(other.m_currentColor, m_currentColor);
                                                                                                                                                                                                              m_colorChangedFlag = true;
                                                                                                                                                                                                              m_colorChanged.wakeAll();
                                                                                                                                                                                                              m_guard.unlock();
                                                                                                                                                                                                          }
                                                                                                                                                                                                       
                                                                                                                                                                                                          void SetColor(Color color)
                                                                                                                                                                                                          {
                                                                                                                                                                                                              m_guard.lock();
                                                                                                                                                                                                              m_currentColor = color;
                                                                                                                                                                                                              m_colorChangedFlag = true;
                                                                                                                                                                                                              m_colorChanged.wakeAll();
                                                                                                                                                                                                              m_guard.unlock();
                                                                                                                                                                                                          }
                                                                                                                                                                                                          
                                                                                                                                                                                                          int GetMetHamelions()
                                                                                                                                                                                                          {
                                                                                                                                                                                                              return m_metChamelions;
                                                                                                                                                                                                          }
                                                                                                                                                                                                          
                                                                                                                                                                                                      private:    
                                                                                                                                                                                                          void run()
                                                                                                                                                                                                          {
                                                                                                                                                                                                              m_point.WaitForStart();
                                                                                                                                                                                                              
                                                                                                                                                                                                              bool shouldBreak = false;
                                                                                                                                                                                                              
                                                                                                                                                                                                              while (!shouldBreak)
                                                                                                                                                                                                              {
                                                                                                                                                                                                                  auto colorChanged = m_colorChangedFlag;
                                                                                                                                                                                                                  switch (m_point.ImHere(*this))
                                                                                                                                                                                                                  {
                                                                                                                                                                                                                  case Action::WaitForPeer:
                                                                                                                                                                                                                      m_guard.lock();
                                                                                                                                                                                                                      if (colorChanged == m_colorChangedFlag)
                                                                                                                                                                                                                          m_colorChanged.wait(&m_guard);
                                                                                                                                                                                                                      
                                                                                                                                                                                                                      m_colorChangedFlag = false;
                                                                                                                                                                                                                      m_guard.unlock();
                                                                                                                                                                                                                      m_metChamelions ++;
                                                                                                                                                                                                                      break;
                                                                                                                                                                                                                  case Action::WasRandevous:
                                                                                                                                                                                                                      m_metChamelions ++;
                                                                                                                                                                                                                      break;
                                                                                                                                                                                                                  case Action::ShouldPassBy:
                                                                                                                                                                                                                      break;
                                                                                                                                                                                                                  case Action::MustDie:
                                                                                                                                                                                                                      shouldBreak = true;
                                                                                                                                                                                                                      break;
                                                                                                                                                                                                                  }
                                                                                                                                                                                                                  
                                                                                                                                                                                                                  if (!shouldBreak)
                                                                                                                                                                                                                      ; // msleep(10);
                                                                                                                                                                                                              }
                                                                                                                                                                                                              // std::cout << m_name << ": Meeted chamelions = " << m_metChamelions << std::endl;
                                                                                                                                                                                                              std::cout << "F" << std::endl;
                                                                                                                                                                                                          }
                                                                                                                                                                                                          
                                                                                                                                                                                                      private:
                                                                                                                                                                                                          int m_metChamelions;        
                                                                                                                                                                                                          std::string m_name;    
                                                                                                                                                                                                          Color m_currentColor;
                                                                                                                                                                                                          RandevousPoint &m_point;
                                                                                                                                                                                                          QMutex m_guard;
                                                                                                                                                                                                          QWaitCondition m_colorChanged;
                                                                                                                                                                                                          bool m_colorChangedFlag;
                                                                                                                                                                                                      };
                                                                                                                                                                                                       
                                                                                                                                                                                                      Action RandevousPoint::ImHere(Chamelion &ch)
                                                                                                                                                                                                      {
                                                                                                                                                                                                          QMutexLocker l(&m_guard);
                                                                                                                                                                                                          
                                                                                                                                                                                                          if (m_currentRandevous >= m_maxRandevous)
                                                                                                                                                                                                          {
                                                                                                                                                                                                              ch.SetColor(Color::Faded);
                                                                                                                                                                                                              return Action::MustDie;
                                                                                                                                                                                                          }
                                                                                                                                                                                                          
                                                                                                                                                                                                          if (m_firstChamelion == nullptr)
                                                                                                                                                                                                          {
                                                                                                                                                                                                              m_firstChamelion = &ch;
                                                                                                                                                                                                              return Action::WaitForPeer;        
                                                                                                                                                                                                          }
                                                                                                                                                                                                          
                                                                                                                                                                                                          m_firstChamelion->SwapColors(ch);
                                                                                                                                                                                                          m_currentRandevous ++;
                                                                                                                                                                                                          m_firstChamelion = nullptr;
                                                                                                                                                                                                          return Action::WasRandevous;
                                                                                                                                                                                                      }
                                                                                                                                                                                                       
                                                                                                                                                                                                      int main(int argc, char *argv[])
                                                                                                                                                                                                      {
                                                                                                                                                                                                          QCoreApplication a(argc, argv);
                                                                                                                                                                                                          
                                                                                                                                                                                                          RandevousPoint point(10000);
                                                                                                                                                                                                          {
                                                                                                                                                                                                              Chamelion ch1("Chamelion #1", Color::Blue, point);
                                                                                                                                                                                                              Chamelion ch2("Chamelion #2", Color::Yellow, point);
                                                                                                                                                                                                              Chamelion ch3("Chamelion #3", Color::Red, point);
                                                                                                                                                                                                              Chamelion ch4("Chamelion #4", Color::Blue, point);
                                                                                                                                                                                                              
                                                                                                                                                                                                              ch1.start();
                                                                                                                                                                                                              ch2.start();
                                                                                                                                                                                                              ch3.start();
                                                                                                                                                                                                              ch4.start();
                                                                                                                                                                                                              
                                                                                                                                                                                                              ch1.wait();
                                                                                                                                                                                                              ch2.wait();
                                                                                                                                                                                                              ch3.wait();
                                                                                                                                                                                                              ch4.wait();
                                                                                                                                                                                                              
                                                                                                                                                                                                              std::cout << "# of randevous: " << ch1.GetMetHamelions() + ch2.GetMetHamelions() + ch3.GetMetHamelions() + ch4.GetMetHamelions() << std::endl;
                                                                                                                                                                                                          }
                                                                                                                                                                                                              
                                                                                                                                                                                                          return 0;
                                                                                                                                                                                                      }

                                                                                                                                                                                                    UPD: Пофиксил небольшую гоночку - цвета у хамелеонов не уникальные. :)
                                                                                                                                                                                                    Сообщение отредактировано: Flex Ferrum -
                                                                                                                                                                                                      Цитата Flex Ferrum @
                                                                                                                                                                                                      Ну, прямо скажем, не rocket science. :) На больную голову вполне решаемая задачка.

                                                                                                                                                                                                      Конечно не rocket science, поэтому такие задачки в качестве демок и выбираются, чтобы можно было быстро решить.
                                                                                                                                                                                                      Кстати говоря, у вас SetColor имеет слишком сложную реализацию. Да и вообще вряд ли он нужен. Когда ImHere возвращает MustDie, хамелеон сам может поменять свой цвет на Faded на контексте своей нити, тогда никаких блокировок не нужно. Ну и код возврата ShouldPassBy, как я понял, не нужен.
                                                                                                                                                                                                        Цитата eao197 @
                                                                                                                                                                                                        Цитата Flex Ferrum @
                                                                                                                                                                                                        Ну, прямо скажем, не rocket science. :) На больную голову вполне решаемая задачка.

                                                                                                                                                                                                        Конечно не rocket science, поэтому такие задачки в качестве демок и выбираются, чтобы можно было быстро решить.
                                                                                                                                                                                                        Кстати говоря, у вас SetColor имеет слишком сложную реализацию. Да и вообще вряд ли он нужен. Когда ImHere возвращает MustDie, хамелеон сам может поменять свой цвет на Faded на контексте своей нити, тогда никаких блокировок не нужно. Ну и код возврата ShouldPassBy, как я понял, не нужен.

                                                                                                                                                                                                        На счёт ShouldPassBy - согласен. Просто была мысль сделать ожидание на мьютексе в ImHere с таймаутом. Тогда бы пригодилось. На счёт SetColor - в некотором смысле на автомате получилось. С одной стороны, нужды в нём действительно нет. С другой - сделано для консистентности, чтобы не размазывать логику перекрашивания хамелиона по коду точки встречи и реализации потока хамелиона. А поскольку в SetColor модифицируется защищенная мьютексом переменная, то отсюда и такая "сложность". :)

                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                        Тем более, что перекрашивания в Faded всегда будет происходить в контексте потока хамелиона.

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

                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                        И зачем для сборки проекта ACE? Вы сами реакторы/проекторы не реализуете?
                                                                                                                                                                                                          Цитата Flex Ferrum @
                                                                                                                                                                                                          Возник вот какой вопрос: а в вашей библиотеке посылать несколько раз один и тот же экземпляр сообщения можно? Как раз для таких случаев было бы полезно - разновидностей сообщений мало (порядка 12-ти), а операций с ними - очень много.

                                                                                                                                                                                                          Да, можно.

                                                                                                                                                                                                          Примеры и как это делается есть тут: http://sourceforge.net/p/sobjectizer/featu...equests/3/#085c

                                                                                                                                                                                                          С любого сообщения можно сделать make_reference (получить smart ptr), и использовать как shared_ptr. Тех тех пор, пока хотя бы один такой указатель жив, сообщение можно пересылать без копирования.
                                                                                                                                                                                                            Цитата Flex Ferrum @
                                                                                                                                                                                                            И зачем для сборки проекта ACE? Вы сами реакторы/проекторы не реализуете?

                                                                                                                                                                                                            Мы где-то в 2004 или 2005 выбрали ACE в качестве базовой библиотеки для кросс-платформенности. С тех пор ее и используем, благо опыт есть и ежели чего, в ее потрохах разобраться гораздо проще, чем в Boost-е. Хотя, если бы в то время была Qt под LGPL лицензией, может быть остановились бы на Qt.

                                                                                                                                                                                                            Сейчас в ядре SObjectizer-а из ACE используются:
                                                                                                                                                                                                            * нити/мутексы/condition_variables;
                                                                                                                                                                                                            * atomic-и;
                                                                                                                                                                                                            * ACE Logging для печатей сообщений об ошибках;
                                                                                                                                                                                                            * таймеры.

                                                                                                                                                                                                            Заменить нити/мутексы/atomic-и уже сейчас можно на средства из С++11.
                                                                                                                                                                                                            А вот уже с ACE Logging-ом сложнее.

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

                                                                                                                                                                                                            Есть еще три библиотеки, построенные над ядром:
                                                                                                                                                                                                            * so_log, которая расширяет возможности ACE Logging и упрощает логирование информации для агентов;
                                                                                                                                                                                                            * so_5_transport, в котором задействуются ACE_Socket-ы и ACE_Reactor-ы;
                                                                                                                                                                                                            * so_sysconf, в котором из ACE берется функциональность для работы с DLL и so-файлами.

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

                                                                                                                                                                                                            В принципе, лично я бы хотел, чтобы со временем ядро SObjectizer-а зависело только от стандартных библиотек C++. А такие штуки, как ACE или Qt, или Boost использовались уже в дополнительных библиотеках. Но это требует времени и работы.

                                                                                                                                                                                                            Добавлено
                                                                                                                                                                                                            Цитата Flex Ferrum @
                                                                                                                                                                                                            Посмотрел вашу реализацию в заметке на Blogspot - конечно, оверкилл для этой задачи.

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

                                                                                                                                                                                                            С другой стороны, решение показательно тем, что пользователь нигде не видит нитей или mutex-ов.
                                                                                                                                                                                                              eao197 по поводу ACE - ясно (хотя сотни тысяч таймеров - хмммм). Относительно примера - лучше всё-таки выбирать что-нибудь более подходящее. Т. е. из серии продьюсеров-консьюмеров. И это, старайтесь в текстах примеров избегать захвата (в контекст лямбд) чего-либо по ссылкам. Предполагается, что код лямбда будет работать за пределами захваченного контекста, и захват чего-либо по ссылкам в таком случае - это очень хороший способ наступить на грабли.
                                                                                                                                                                                                              bsivko, угу, ясно. Интересно, насколько ускорится код eao197, если перестать постоянно дёргать хип таким вот образом?
                                                                                                                                                                                                                Цитата Flex Ferrum @
                                                                                                                                                                                                                eao197 по поводу ACE - ясно (хотя сотни тысяч таймеров - хмммм). Относительно примера - лучше всё-таки выбирать что-нибудь более подходящее. Т. е. из серии продьюсеров-консьюмеров. И это, старайтесь в текстах примеров избегать захвата (в контекст лямбд) чего-либо по ссылкам. Предполагается, что код лямбда будет работать за пределами захваченного контекста, и захват чего-либо по ссылкам в таком случае - это очень хороший способ наступить на грабли.

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

                                                                                                                                                                                                                По поводу примера. Что первое в голову пришло, то и сделали. Если есть какие-то хорошие примеры для таких вещей, то я был бы рад их услышать.

                                                                                                                                                                                                                Про захват переменных для лямбд -- все оправдано. Если говорить про пример с ping_pong-ом, из первого поста, то там pings_left захватывается по ссылке специально для того, чтобы показать, как в ad-hoc-агенте (объект которого скрыт от пользователя) можно иметь состояние, сохраняющееся между вызовами событий этого агента. Ссылку на env нужно сохранять потому, что so_environment_t -- это интерфейс с абстрактными методами, по значению его экземпляр не скопируешь, можно иметь только ссылку на него. А вот mbox-ы в агентах pinger и ponger захватываются как раз по значению и именно для того, чтобы не иметь проблем с повисшими указателями.
                                                                                                                                                                                                                  eao197, я не сомневаюсь, что в примере это оправдано. Но, как говориться, error prone. Менее опытный разработчик очень хорошо может залететь.
                                                                                                                                                                                                                    Цитата Flex Ferrum @
                                                                                                                                                                                                                    eao197, я не сомневаюсь, что в примере это оправдано. Но, как говориться, error prone. Менее опытный разработчик очень хорошо может залететь.


                                                                                                                                                                                                                    Да как по мне, так с лямбдами вообще нужно быть поосторожнее. Даже имея за плечами большой опыт разработки сложно разбираться в том, что делает код с лямбдами, когда что работает, когда что теряет актуальность, когда нужно обеспечить длительное время жизни и т.д.
                                                                                                                                                                                                                      eao197, на вашем месте в качестве основы реализации ad-hoc агентов я бы рассмотрел шаблонный класс, типизируемый контекстом, который передает этот контекст (и env) первыми параметрами в лямбды. Сигнатура лямбды усложнится, но вероятность допустить ошибку значительно уменьшится, что важнее.
                                                                                                                                                                                                                        Цитата Flex Ferrum @
                                                                                                                                                                                                                        eao197, на вашем месте в качестве основы реализации ad-hoc агентов я бы рассмотрел шаблонный класс, типизируемый контекстом, который передает этот контекст (и env) первыми параметрами в лямбды. Сигнатура лямбды усложнится, но вероятность допустить ошибку значительно уменьшится, что важнее.

                                                                                                                                                                                                                        Надо посмотреть, что из этого вообще выйдет. Как по мне, так ad-hoc нужны для мелких вспомогательных stateless агентов, которым контекст вообще не нужен.

                                                                                                                                                                                                                        Если же я ошибаюсь, то в будущем можно будет и более сложные варианты рассмотреть.
                                                                                                                                                                                                                          Цитата eao197 @
                                                                                                                                                                                                                          Мне кажется, что вы не обеспечиваете одновременного старта всех хамелеонов. Т.е. два первых хамелеона могут завершить всю работу еще до того, как стартует третий и четвертый хамелеоны.

                                                                                                                                                                                                                          Когда кажется, креститься надо. Все там одновременно насколько это возможно.
                                                                                                                                                                                                                            Цитата korvin @
                                                                                                                                                                                                                            Когда кажется, креститься надо. Все там одновременно насколько это возможно.

                                                                                                                                                                                                                            Это доказательство из разряда "Мамой клянусь!" :)

                                                                                                                                                                                                                            Впрочем, я посмотрел свой старый код, который я когда-то делал на mutex-ах. Там не было задачи обеспечивать синхронный запуск всех четырех рабочих очередей. Так что это я уже что-то от себя выдумал. Под впечатлением от Qt-шной реализации Игоря Мирончика.
                                                                                                                                                                                                                              Цитата Flex Ferrum @
                                                                                                                                                                                                                              bsivko, угу, ясно. Интересно, насколько ускорится код eao197, если перестать постоянно дёргать хип таким вот образом?

                                                                                                                                                                                                                              Не так, чтобы много. На 500k встреч время уменьшилось с 1.9s до 1.7s. Код теста здесь.

                                                                                                                                                                                                                              В данном тесте основные потери времени идут на том, что в очереди каждой рабочей нити хамелеонов оказывается всего одна заявка. Поэтому когда она извлекается, рабочая нить засыпает на condition variable в ожидании следующей заявки. Это дорого.
                                                                                                                                                                                                                              Если бы в данном конкретном примере рабочие нити ждали не на condition variable, а на spin lock-ах, то время работы было бы заметно меньше. Но это была бы заточка под конкретный тест. А в общем случае запускать ожидание рабочей нити на spin lock-е -- это неразумно.

                                                                                                                                                                                                                              Может быть, со временем мы придем к какому-то более хитрому, адаптивному механизму. Например, сначала несколько попыток ожидания на spin lock-е, затем переход к condition variable. Нужно будет смотреть. Но хотелось бы отталкиваться не от простых синтетических тестов.

                                                                                                                                                                                                                              А вообще за подсказку спасибо. Я как раз начинал ломать голову над тем, как позволить пользователю использовать предварительно аллоцированные экземпляры сообщений. Оказалось, что все заготовки для этого в SObjectizer уже есть. Я их просто не замечал.
                                                                                                                                                                                                                                Цитата eao197 @
                                                                                                                                                                                                                                Это доказательство из разряда "Мамой клянусь!"

                                                                                                                                                                                                                                Это доказательство практикой. Тебе вывод времени добавить?
                                                                                                                                                                                                                                Сообщение отредактировано: korvin -
                                                                                                                                                                                                                                  Цитата korvin @
                                                                                                                                                                                                                                  Это доказательство практикой. Тебе вывод времени добавить?

                                                                                                                                                                                                                                  Практика доказывает наличие проблем, а не их отсутствие.
                                                                                                                                                                                                                                  Что должен показать вывод времени?

                                                                                                                                                                                                                                  Я исхожу из того, что запуск гороутин идет подряд:
                                                                                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                                                                                    go newChameleon(meets, colorBlue,   meetplace)
                                                                                                                                                                                                                                    go newChameleon(meets, colorRed,    meetplace)
                                                                                                                                                                                                                                    go newChameleon(meets, colorYellow, meetplace)
                                                                                                                                                                                                                                    go newChameleon(meets, colorBlue,   meetplace)

                                                                                                                                                                                                                                  И каждый хамелеон начинал работать не дожидаясь каких-то сигналов:
                                                                                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                                                                                    func newChameleon(meets chan int, c color, meetplace chan meeter) {
                                                                                                                                                                                                                                        done := make(chan bool)
                                                                                                                                                                                                                                        self := &chameleon{c, 0}
                                                                                                                                                                                                                                        for {
                                                                                                                                                                                                                                            meetplace <- meeter{self, done}

                                                                                                                                                                                                                                  Это означает, что если в самом Go нет какой-то магии вокруг канала chan meeter, то первая запущенная гороутина сразу же пишет в канал. Туда же сразу же пишет вторая, третья и т.д.

                                                                                                                                                                                                                                  Только вот многопоточная/многопроцессная работа она такая вот. Специфична тем, что текущий поток/процесс может быть приостановлен в любой момент (есть многозадачность реально вытесняющая). Это значит, что между второй и третьей конструкцией go newChameleon() поток с функцией main может быть приостановлен на некоторое время. Этого времени может хватить двум первым хамелеонам для того, чтобы выбрать весь лимит встреч. А может и не хватить. Что чаще всего и происходит на практике, т.к. если система не перегружена выше крыши, нити/процессы прерываются не небольшие интервалы времени. Тем не менее, с теоритической точки зрения, вполне может быть так, что весь тест проделают только два или три стартовавших первыми хамелеонов.

                                                                                                                                                                                                                                  В этом смысле реализация Игоря Мирончика на Qt более честная, т.к. она сначала запускает все 4 рабочих нити, а потом единомоментно дает им шанс побороться за место. Очевидно, что здесь все зависит от состояния планировщика ОС и этот сценарий вовсе не исключает того же самого (весь тест отработает всего два или три хамелеона), но, по крайней мере стартовые позиции у хамелеонов более-менее одинаковые. В отличии от простого поочередного запуска хамелеонов, которые сразу начинают работать.
                                                                                                                                                                                                                                    Цитата eao197 @
                                                                                                                                                                                                                                    В этом смысле реализация Игоря Мирончика на Qt более честная, т.к. она сначала запускает все 4 рабочих нити, а потом единомоментно дает им шанс побороться за место. Очевидно, что здесь все зависит от состояния планировщика ОС и этот сценарий вовсе не исключает того же самого (весь тест отработает всего два или три хамелеона), но, по крайней мере стартовые позиции у хамелеонов более-менее одинаковые

                                                                                                                                                                                                                                    Да всё одно и то же на самом деле.
                                                                                                                                                                                                                                      Цитата eao197 @
                                                                                                                                                                                                                                      Практика доказывает наличие проблем, а не их отсутствие.

                                                                                                                                                                                                                                      И какие проблемы ты видишь в моем примере?

                                                                                                                                                                                                                                      Цитата eao197 @
                                                                                                                                                                                                                                      Это означает, что если в самом Go нет какой-то магии вокруг канала chan meeter, то первая запущенная гороутина сразу же пишет в канал. Туда же сразу же пишет вторая, третья и т.д.

                                                                                                                                                                                                                                      Каналы --- точки синхронизации, все четыре горутины пытаются писать в канал и блокируются до тех пор, пока их сообщение не будет прочтено. В принципе можно отправку запустить в отдельной горутине, т.к. важная для корректности блокировка идет на следующей строке.
                                                                                                                                                                                                                                        Цитата korvin @
                                                                                                                                                                                                                                        И какие проблемы ты видишь в моем примере?

                                                                                                                                                                                                                                        Я их уже описал.

                                                                                                                                                                                                                                        Цитата korvin @
                                                                                                                                                                                                                                        Каналы --- точки синхронизации, все четыре горутины пытаются писать в канал и блокируются до тех пор, пока их сообщение не будет прочтено.

                                                                                                                                                                                                                                        Гороутина meetingplace уже запущена к тому моменту, когда стартует первый хамелеон. Так что обработка запросов хамелеонов идет сразу же, как только первый из них появляется.
                                                                                                                                                                                                                                        Если бы гороутина meetingplace стартовала после хамелеонов -- это бы лишило мои замечания смысла.
                                                                                                                                                                                                                                          Цитата eao197 @
                                                                                                                                                                                                                                          Это значит, что между второй и третьей конструкцией go newChameleon() поток с функцией main может быть приостановлен на некоторое время. Этого времени может хватить двум первым хамелеонам для того, чтобы выбрать весь лимит встреч.

                                                                                                                                                                                                                                          А еще кто-то может выдернуть шнур питания, да.

                                                                                                                                                                                                                                          Добавлено
                                                                                                                                                                                                                                          Цитата eao197 @
                                                                                                                                                                                                                                          Если бы гороутина meetingplace стартовала после хамелеонов -- это бы лишило мои замечания смысла.

                                                                                                                                                                                                                                          Это бы ничего не изменило, в твоей ситуации горутина meetingplace может просто быть приостановлена на неопределенное время и ничего не будет работать.

                                                                                                                                                                                                                                          Добавлено
                                                                                                                                                                                                                                          Но да ладно, просили, получите.
                                                                                                                                                                                                                                            Состоялся релиз SObjectizer 5.4.0

                                                                                                                                                                                                                                            Версия 5.4.0 содержит несколько изменений и улучшений, среди которых можно выделить следующие:
                                                                                                                                                                                                                                            • новый тип mbox-а: multi-producer/single-consumer (MPSC). Позволяет организовать эффективное peer-to-peer взаимодействие агентов (ранее такое взаимодействие было частным случаем использования модели publish/subscribe). Накладные расходы на общение двух агентов через MPSC заметно ниже, чем при работе через старые multi-producer/multi-consumer mbox-ы;
                                                                                                                                                                                                                                            • для обработчиков событий можно указывать признак thread safety. По умолчанию все обработчики событий рассматриваются как not_thread_safe и для одного агента обработчики его событий запускаются строго последовательно. Если же событие помечено как thread_safe, но новый диспетчер adv_thread_pool может параллельно запустить несколько thread_safe-обработчиков для одного агента на разных нитях;
                                                                                                                                                                                                                                            • новый диспетчер thread_pool, который использует пул рабочих потоков и распределяет обработчики событий между этими потоками (здесь чуть подробнее о принципах работы этого диспетчера);
                                                                                                                                                                                                                                            • новый диспетчер adv_thread_pool, который так же использует пул рабочих потоков и распределяет обработчики событий с учетом флага thread safety (здесь чуть подробнее об этой возможности);
                                                                                                                                                                                                                                            • режим autoshutdown -- SObjectizer Environment завершает свою работу после дерегистрации последней кооперации;
                                                                                                                                                                                                                                            • теперь диспетчеров можно добавлять и после запуска SObjectizer Environment (ранее это нужно было делать только до старта Environment-а);
                                                                                                                                                                                                                                            • серьезная реорганизация внутренней кухни, увеличение производительности и улучшение масштабируемости.
                                                                                                                                                                                                                                            Более подобно список изменений в версии 5.4.0 на русском языке описывается здесь.

                                                                                                                                                                                                                                            Версия распространяется в виде сборки so-201408-00, в которую кроме SObjectzer 5.4.0 входит еще несколько SObjectizer-библиотек, предназначенных для разработки больших, распределенных приложений на основе SObjectizer, а именно:
                                                                                                                                                                                                                                            • so_log, служащая оберткой над ACE Logging и упрощающая логирование для агентов;
                                                                                                                                                                                                                                            • so_sysconf, позволяющая собирать большое приложение из маленьких кусочков, оформленных в виде dll/so-библиотек;
                                                                                                                                                                                                                                            • so_5_transport, оформляющая работу с TCP/IP соединениями в виде транспортных SObjectizer-агентов;
                                                                                                                                                                                                                                            • mbapi, являющаяся высокоуровневой библиотекой для обмена сообщениями между агентами или между компонентами распределенного приложения.
                                                                                                                                                                                                                                            Примечание. Компилятор Microsoft Visual C++ 11 (т.е. MSVS2012) больше не поддерживается. Для компиляции под Windows теперь нужно использовать Visual C++ 12 (т.е. MSVS2013).

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

                                                                                                                                                                                                                                            Wiki-раздел SObjectizer-а на SourceForge содержит более подробную информацию как об особенностях версии 5.4.0, так и о самом SObjectizer и его основах.

                                                                                                                                                                                                                                            Также может быть интересна статья о SObjectizer на Openquality.
                                                                                                                                                                                                                                            Сообщение отредактировано: bsivko -
                                                                                                                                                                                                                                              SObjectizer обновился до версии 5.5.0

                                                                                                                                                                                                                                              Главное отличие v.5.5.0 от предыдущих версий -- это отсутствие зависимости от ACE Framework. Т.е. теперь ACE в коде ядра SObjectizer не используется вообще, для SObjectizer достаточно наличия стандартной библиотеки C++11. Это означает, что SObjectizer уменьшился в размере, нужно меньше времени на сборку SObjectizer-проектов, упрощается поддержка различных компиляторов и платформ. В частности, эта версия SObjectizer тестировалась посредством MSVS2013 (Windows), GCC 4.8/4.9 (Windows, Linux), Clang 3.5.0 (Linux).

                                                                                                                                                                                                                                              Из более мелких изменений можно отметить прямую поддержку std::chrono при работе с отложенными/периодическими сообщениями, а так же небольшое изменение названий некоторых классов/функций (с сохранением старых имен для обеспечения совместимости). Более подробная информация о нововведениях в v.5.5.0 доступна в соответствующем разделе Wiki проекта. Так же увеличилось количество страниц с описаниями базовых вещей SObjectizer.

                                                                                                                                                                                                                                              Версия 5.5.0 может быть загружена из раздела Files или получена из Subversion-репозитория.

                                                                                                                                                                                                                                              Примечание. Этот релиз содержит только ядро SObjectizer (т.е. проект so_5). Никакие другие подпроекты (вроде so_log или so_sysconf) в релиз не включены. Возможно, сборка SObjectizer Assembly со всеми подпроектами будет сформирована и опубликована позже (если она действительно кому-то потребуется).

                                                                                                                                                                                                                                              PS. Анонс делается просто для того, чтобы уведомить, что такой проект есть, живет, развивается. Доступен под BSD-лицензий, т.е. даром, в том числе и для коммерческих проектов. Это не просьба сделать code review. И не попытка кому-то что-то "продать".

                                                                                                                                                                                                                                              PPS. Специально для желающих постебаться над синтаксисом и посравнивать программирование на C++ с Perl-ом. Вот классический пример Hello, World. В традиционном, ООП-шном варианте, с созданием класса агента и переопределением виртуальных методов (хотя есть и более модерновый вариант, с использованием С++ных лямбда-функций):

                                                                                                                                                                                                                                              ExpandedWrap disabled
                                                                                                                                                                                                                                                #include <iostream>
                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                // Main SObjectizer header files.
                                                                                                                                                                                                                                                #include <so_5/all.hpp>
                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                // Definition of an agent for SObjectizer.
                                                                                                                                                                                                                                                class a_hello_t : public so_5::rt::agent_t
                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                    public:
                                                                                                                                                                                                                                                        a_hello_t( so_5::rt::environment_t & env )
                                                                                                                                                                                                                                                            : so_5::rt::agent_t( env )
                                                                                                                                                                                                                                                        {}
                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                        // A reaction to start of work in SObjectizer.
                                                                                                                                                                                                                                                        virtual void
                                                                                                                                                                                                                                                        so_evt_start() override
                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                            std::cout << "Hello, world! This is SObjectizer v.5."
                                                                                                                                                                                                                                                                << std::endl;
                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                            // Shutting down SObjectizer.
                                                                                                                                                                                                                                                            so_environment().stop();
                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                        // A reaction to finish of work in SObjectizer.
                                                                                                                                                                                                                                                        virtual void
                                                                                                                                                                                                                                                        so_evt_finish() override
                                                                                                                                                                                                                                                        {
                                                                                                                                                                                                                                                            std::cout << "Bye! This was SObjectizer v.5."
                                                                                                                                                                                                                                                                << std::endl;
                                                                                                                                                                                                                                                        }
                                                                                                                                                                                                                                                };
                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                int
                                                                                                                                                                                                                                                main( int, char ** )
                                                                                                                                                                                                                                                {
                                                                                                                                                                                                                                                    try
                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                        // Starting SObjectizer.
                                                                                                                                                                                                                                                        so_5::launch(
                                                                                                                                                                                                                                                            // A function for SO Environment initialization.
                                                                                                                                                                                                                                                            []( so_5::rt::environment_t & env )
                                                                                                                                                                                                                                                            {
                                                                                                                                                                                                                                                                // Creating and registering single agent as a cooperation.
                                                                                                                                                                                                                                                                env.register_agent_as_coop( "coop", new a_hello_t( env ) );
                                                                                                                                                                                                                                                            } );
                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                    catch( const std::exception & ex )
                                                                                                                                                                                                                                                    {
                                                                                                                                                                                                                                                        std::cerr << "Error: " << ex.what() << std::endl;
                                                                                                                                                                                                                                                        return 1;
                                                                                                                                                                                                                                                    }
                                                                                                                                                                                                                                                 
                                                                                                                                                                                                                                                    return 0;
                                                                                                                                                                                                                                                }


                                                                                                                                                                                                                                              PPPS. Специально для желающих узнать, чем SObjectizer лучше libcppa/CAF. В двух словах -- это две совершенно разные разработки, ставящие перед собой разные цели и достигающие их разными способами. Подробнее здесь и здесь.
                                                                                                                                                                                                                                              Сообщение отредактировано: eao197 -
                                                                                                                                                                                                                                                Версия 5.5.1

                                                                                                                                                                                                                                                Небольшое обновление. Ничего особо примечательного, маленький эволюционный шажок в сторону упрощения использования и сокращения объема писанины. Подробнее здесь (там же и все ссылки на исходники/дистрибутивы).
                                                                                                                                                                                                                                                  Если кому-то интересно, то вот еще один пример. Одно из возможных решений проблемы Producer-Consumer с защитой Consumer-а от перегрузки.
                                                                                                                                                                                                                                                    SObjectizer обновился до версии 5.5.2. Изменений в самом SO5 нет, но добавилась экспериментальная поддержка CMake для сборки библиотеки so.5.5.2.(so,dll) и примеров (сборка тестов пока не поддерживается).

                                                                                                                                                                                                                                                    Огромная благодарность ув.тов.Alex Syrnikov за реализацию поддержки CMake.
                                                                                                                                                                                                                                                      eao197, так CMake же "уродский инструмент" :D
                                                                                                                                                                                                                                                        Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                        eao197, так CMake же "уродский инструмент" :D

                                                                                                                                                                                                                                                        Ну так не мне же этим пользоваться и поддерживать ;)
                                                                                                                                                                                                                                                          Цитата eao197 @
                                                                                                                                                                                                                                                          Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                          eao197, так CMake же "уродский инструмент" :D

                                                                                                                                                                                                                                                          Ну так не мне же этим пользоваться и поддерживать ;)

                                                                                                                                                                                                                                                          Ну, да, SCons и Rake хороши, но у них есть минус - IDE в обозримом будущем не смогут обрабатывать такие проекты. В этом смысле свой язык CMake гораздо лучше и потому что может сгенерировать проект для любой IDE, и потому что будет CLion :)
                                                                                                                                                                                                                                                          Сообщение отредактировано: MyNameIsIgor -
                                                                                                                                                                                                                                                            Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                            Цитата eao197 @
                                                                                                                                                                                                                                                            Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                            eao197, так CMake же "уродский инструмент" :D

                                                                                                                                                                                                                                                            Ну так не мне же этим пользоваться и поддерживать ;)

                                                                                                                                                                                                                                                            Ну, да, SCons и Rake удобны, но у них есть минус - IDE в обозримом будущем не смогут обрабатывать такие проекты. В этом смысле свой язык CMake гораздо лучше и потому что может сгенерировать проект для любой IDE, и потому что будет CLion :)

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

                                                                                                                                                                                                                                                            Мое же личное отношение к таким вещам вообще ни о чем, побухтеть в блоге -- запросто. А навязывать что-то кому-то или запрещать -- не в коем случае.
                                                                                                                                                                                                                                                              eao197, видел в блоге интересное сравнение с сопрограммами. Пока особо не смотрел, но думаю, что тут можно было б обсудить :)
                                                                                                                                                                                                                                                                Цитата D_KEY @
                                                                                                                                                                                                                                                                eao197, видел в блоге интересное сравнение с сопрограммами. Пока особо не смотрел, но думаю, что тут можно было б обсудить :)

                                                                                                                                                                                                                                                                Всегда пожалуйста. Я с удовольствием.

                                                                                                                                                                                                                                                                Кста. Там в комментариях автор оригинальной статьи с Хабра отметился, мы с ним вроде как интересными взглядами на вещи обменялись. Так что если будете смотреть внимательнее, то и комментарии можно глянуть.
                                                                                                                                                                                                                                                                  Подготовлена еще одна статья, знакомящая читателя с ключевыми особенностями SObjectizer-а на простом примере. Серьезного знания C++ и/или SObjectizer не требуется, материал расчитан на широкий круг читателей: "Разбор примера простой реализации дедлайнов для сообщений"
                                                                                                                                                                                                                                                                    SObjectizer обновился до версии 5.5.2.1. Это баг-фикс релиз, кроме исправления ошибки с отменой подписок агента других отличий с версией 5.5.2 нет.
                                                                                                                                                                                                                                                                      SObjectizer обновился до версии 5.5.3.
                                                                                                                                                                                                                                                                      Версию 5.5.3 можно взять либо из секции Files на SF, либо из Svn-репозитория.
                                                                                                                                                                                                                                                                      Если говорить кратко, что в версии 5.5.3:
                                                                                                                                                                                                                                                                      • чуть-чуть упрощено создание дочерних коопераций;
                                                                                                                                                                                                                                                                      • добавлена возможность работы с direct_mbox-ами ad-hoc-агентов (т.е. агентов, которые определяются «по месту», без создания отдельного C++ класса);
                                                                                                                                                                                                                                                                      • добавлена возможность выбора типа хранилища для подписок агентов;
                                                                                                                                                                                                                                                                      • добавлены новые примеры.
                                                                                                                                                                                                                                                                      Если интересны подробности, то сюда.
                                                                                                                                                                                                                                                                      Для тех, кто больше любит смотреть слайды есть пара презенташек (для того, чтобы получить более полное представление об инструменте, лучше смотреть вторую, которая подлинее).
                                                                                                                                                                                                                                                                        Тут затрагивался вопрос супервизоров для агентов/акторов. Поэтому читателям темы может быть интересно вот это: О сбоящих агентах или почему в версии 5.5.4 не будет изменена схема реакции на исключения. Там описаны мысли о реакции на сбои агентов/акторов. Вообще. Но в больше степени в привязке к нативному коду. И с объяснением того, как это сделано в SObjectizer. И почему сделано так :)
                                                                                                                                                                                                                                                                          В so-5.5 обнаружена ошибка, которая была исправлена в версии 5.5.3.1. Чуть подробнее здесь.
                                                                                                                                                                                                                                                                            Подготовлено еще одно подробное описание одного из примеров использования SObjectizer. В данном случае показывается, как может выглядеть работа с многопоточностью и использованием простой модели Publish-Subscribe:

                                                                                                                                                                                                                                                                            Многопоточность и Pub-Sub с помощью SObjectizer.
                                                                                                                                                                                                                                                                              SObjectizer — это небольшой фреймворк для упрощения разработки многопоточных приложений на C++. SObjectizer позволяет создавать объекты-агенты, которые взаимодействуют друг с другом только посредством асинхронных сообщений. Сам SObjectizer берет на себя задачи диспетчеризации сообщений и предоставление агентам рабочего контекста для обработки получаемых сообщений.

                                                                                                                                                                                                                                                                              Проект живет на SourceForge, распространяется под трехпунктной BSD-лицензией.

                                                                                                                                                                                                                                                                              Версию 5.5.4 можно взять либо из секции Files на SF, либо из Svn-репозитория.

                                                                                                                                                                                                                                                                              Если говорить кратко, то в версии 5.5.4 появилось следующее:
                                                                                                                                                                                                                                                                              • вспомогательные шаблонные методы make_agent и make_agent_with_binder (аналоги make_shared и make_unique из C++11/14), упрощающие создание экземпляров агентов;
                                                                                                                                                                                                                                                                              • приватные диспетчеры. Приватный диспетчер можно использовать только по прямой ссылке, которую получает только тот, кто создает такой диспетчер. Так же приватные диспетчеры автоматически уничтожаются, когда ими больше никто не пользуется;
                                                                                                                                                                                                                                                                              • лимиты для сообщений, т.е. возможность ограничить количество сообщений конкретного типа в очереди заявок для агента, что позволяет реализовывать простую защиту агентов от перегрузок штатными средствами SObjectizer-а;
                                                                                                                                                                                                                                                                              • новый тип context_t и дополнительный конструктор для базового типа agent_t, за счет чего упрощается создание агентов, использующих лимиты для сообщений, особенно при наследовании;
                                                                                                                                                                                                                                                                              • простейший вариант сбора и распространения мониторинговой информации о том, что происходит внутри SObjectizer Run-Time. В первую очередь этот вариант предназначен для предоставления возможности сохранения мониторинговой информации посредством таких инструментов, как statsd+graphite, Zabbix, Nagios и т.д.;
                                                                                                                                                                                                                                                                              • несколько новых примеров.

                                                                                                                                                                                                                                                                              Если интересны подробности, то сюда.

                                                                                                                                                                                                                                                                              Отдельная благодарность Алексею Сырникову, как за помощь в подготовке этого релиза, так и за работы по созданию зеркала SObjectizer на GitHub-е.
                                                                                                                                                                                                                                                                                Может быть читателям темы будет интересно: вот здесь небольшая задачка, которая уже более-менее похоже на то, что приходилось делать на SObjectizer и для чего он предназначается. Там уже есть решение на Rust и C++/SObjectizer. Может быть со временем еще кто-то со своими решениями подтянется.

                                                                                                                                                                                                                                                                                PS. На SObjectizer не точь-в-точь такие задачи решались, несколько пообъемнее, обычно. К тому же, в подавляющем большинстве случаев это были не вычислительные задачи, вроде подбора хеша или решения СЛАУ. Но смысл похожий — раздача заданий по агентам-исполнителям, реакция на результаты или какие-то проблемы и т.д., и т.п.
                                                                                                                                                                                                                                                                                  Цитата eao197 @
                                                                                                                                                                                                                                                                                  На SObjectizer не точь-в-точь такие задачи решались

                                                                                                                                                                                                                                                                                  Вот это вот
                                                                                                                                                                                                                                                                                  Цитата
                                                                                                                                                                                                                                                                                  Программа представляет собой многопоточное приложение, с архитектурой: мастер + один или несколько воркеров.
                                                                                                                                                                                                                                                                                  Количество воркеров определяется на старте программы, и, обычно, равно количеству вычислительных ядер в машине.
                                                                                                                                                                                                                                                                                  Мастер вычитывает задания из stdin построчно и раздаёт их свободным воркерам. Пустые строки могут игнорироваться сразу и не восприниматься как задания. Чтение должно либо чередоваться с обработкой, либо вестись параллельно. Нельзя однократно прочитать содержимое stdin от начала до конца и лишь затем приступить к обработке прочитанного (т.к. программа должна иметь возможность работать в составе, например, конвейера в течении длительного периода и обрабатывать миллионы/сотни миллионов/миллиарды строк с stdin).
                                                                                                                                                                                                                                                                                  Задание -- это md5-сумма пароля и диапазон возможных значений пароля. И нижняя, и верхняя граница интервала входит в поиск (т.е. диапазон вида [lower,upper]).
                                                                                                                                                                                                                                                                                  Символы пароля и интервалов могут быть либо цифрами, либо строчными латинскими буквами.
                                                                                                                                                                                                                                                                                  Пример строки с заданием: fec91335051486b245d74cdb6042d4c0 0ayie zayie
                                                                                                                                                                                                                                                                                  Воркер получает задание, пытается подобрать значение из указанного в таске диапазона, которое даст такой же md5-хеш. Такое значение может быть, а может и не быть. О результате воркер сообщает мастеру, который печатает отчёт на stdout.
                                                                                                                                                                                                                                                                                  Получение результата мастером означает, что воркер освободился и может получить следующий таск (если таковые еще есть).
                                                                                                                                                                                                                                                                                  Диапазоны могут быть заданы некорректно.
                                                                                                                                                                                                                                                                                  zzz 000 -- нарушение правила lower меньше upper.
                                                                                                                                                                                                                                                                                  0000 zz -- в upper меньше символов, чем в lower.
                                                                                                                                                                                                                                                                                  aaaa aaAz -- символ A не входит в разрешенный алфавит
                                                                                                                                                                                                                                                                                  Помимо некорректных диапазонов, ошибка может возникать при парсинге строки, и некорректном формате md5-суммы.
                                                                                                                                                                                                                                                                                  Столкнувшись с ошибкой, воркер должен "упасть" (завершить работу).
                                                                                                                                                                                                                                                                                  Эту ситуацию должен отловить мастер и запустить вместо упавшего воркера нового. Проблемное задание при этом выбрасывается, но на stderr должен быть отчёт от мастера.
                                                                                                                                                                                                                                                                                  Если воркер завершил обработку задачи без ошибок, то этот воркер должен быть переиспользован для одного из следующих заданий (если таковые будут). Т.е. допускается создание воркеров по мере необходимости, но не допускается создание/пересоздание воркеров для каждого нового задания.
                                                                                                                                                                                                                                                                                  Завершение работы программы происходит при достижении конца stdin и завершении обработки всех начатых заданий.

                                                                                                                                                                                                                                                                                  не задача. Это пояснения для младшего программиста как надо сделать.
                                                                                                                                                                                                                                                                                  Сообщение отредактировано: MyNameIsIgor -
                                                                                                                                                                                                                                                                                    Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                    Это пояснения для младшего программиста как надо сделать.

                                                                                                                                                                                                                                                                                    Как оказалось, даже такого подробного объяснения не хватает, чтобы сделали именно то, что требуется.
                                                                                                                                                                                                                                                                                      В обсуждениях релизов SO-5 зачастую говорят о том, что сделано все сложно, коряво, непонятно, неправильно и т.д. Допустим, есть возможность все сделать с чистого листа, с нуля, сразу правильно и понятно. Как это должно выглядеть?

                                                                                                                                                                                                                                                                                      Если у кого-то есть мысли/идеи или просто хочется ляпнуть, то вот специальная тема. Или же вот тут. Или же можно прямо здесь, чтобы далеко не ходить.
                                                                                                                                                                                                                                                                                        Как-то в обсуждении SO-5 всплыла тема приоритетов сообщений. Мол, приоритеты нужны, без них плохо. В находящейся сейчас в разработке версии 5.5.5 есть возможность добавить поддержку оных. Что к чему, описано на SF.net и на GitHub-е. Если найдутся заинтересовавшиеся, то обсудить можно будет либо там, либо непосредственно здесь.
                                                                                                                                                                                                                                                                                          Выпущена версия 5.5.5.

                                                                                                                                                                                                                                                                                          Ее можно взять либо из секции Files на SF, либо из Svn-репозитория, либо из зеркала на GitHub.

                                                                                                                                                                                                                                                                                          Если говорить кратко, то в версии 5.5.5 появилось следующее:
                                                                                                                                                                                                                                                                                          • вспомогательные шаблонные методы introduce_coop и introduce_child_coop, упрощающие создание и регистрацию коопераций;
                                                                                                                                                                                                                                                                                          • возможность использования туплов в качестве типов сообщений;
                                                                                                                                                                                                                                                                                          • фильтры для сообщений, которые позволяют анализировать содержимое сообщений и отбрасывать те из них, которые не интересны агенту получателю;
                                                                                                                                                                                                                                                                                          • несколько новых примеров.
                                                                                                                                                                                                                                                                                          Так же подготовлены две новые части серии презентаций “Dive into SObjectizer-5.5”, более подробно рассказывающие о состояниях агентов и кооперациях агентов (все имеющиеся презентации собраны здесь).

                                                                                                                                                                                                                                                                                          Если интересны подробности, то сюда.

                                                                                                                                                                                                                                                                                          Отдельная благодарность Алексею Сырникову, как за помощь в подготовке этого релиза, так и за поддержку зеркала SObjectizer на GitHub-е.
                                                                                                                                                                                                                                                                                          Сообщение отредактировано: eao197 -
                                                                                                                                                                                                                                                                                            Цитата bsivko @
                                                                                                                                                                                                                                                                                            Сама же тема предназначена для любых вопросов, пожеланий и уточнений, которые всячески приветствуются.


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

                                                                                                                                                                                                                                                                                              Открытых проектов на SO-5, насколько я знаю, сейчас нет.

                                                                                                                                                                                                                                                                                              SO-5 продолжает активно использоваться в "Интервэйл", где он и появился впервые, но там все разработки закрытые, насколько мне известно.

                                                                                                                                                                                                                                                                                              Добавлено
                                                                                                                                                                                                                                                                                              Цитата JoeUser @
                                                                                                                                                                                                                                                                                              Можно глянуть на какой-нибудь проект, использующий сабж, но более практичный чем "пинг-понг" или "хелоуворлд"? :-?

                                                                                                                                                                                                                                                                                              Некоторое время назад я специально поднимал вопрос о демо-проекте, который был бы интересен не только разработчикам SO-5. Но что-то никаких интересных идей никто не озвучил, а так как в самом SO-5 было еще много работы, то эта тема не взлетела.

                                                                                                                                                                                                                                                                                              Однако, данное предложение все еще открыто, т.ч. если есть какие-то идеи, то можно их рассмотреть и сделать какой-то приближенный к реальности демо-проект.
                                                                                                                                                                                                                                                                                                Цитата eao197 @
                                                                                                                                                                                                                                                                                                Однако, данное предложение все еще открыто


                                                                                                                                                                                                                                                                                                Навскидку два предложения:

                                                                                                                                                                                                                                                                                                1) Распределенная версия 7z

                                                                                                                                                                                                                                                                                                Возможно на ее основе - система резервного копирования. Если я не ошибаюсь, использование алгоритма LZMA2 позволяет распараллеливать процесс. Есть еще идея - использовать LZMA (т.к. он может позволять большую степень сжатия нежели LZMA2), но процесс строить несколько по другому - многоходовкой. В первом проходе строятся "локальные" словари, во втором проходе строится/вычисляется объединенный словарь, в третьем проходе собственно процесс сжатия на основе объединенного словаря.

                                                                                                                                                                                                                                                                                                Возможны эксперименты и с другими типами алгоритмов сжатия, типа PPMD, ZPAQ

                                                                                                                                                                                                                                                                                                2) Процесс видеокодирования

                                                                                                                                                                                                                                                                                                Тут, увы, я пасс - не знаю особенностей и возможностей распараллеливания - интересует кодек x264. Возможно, нет - без понятия. Хотя в опциях двухпроходной режим есть. А возможно ли "порционное" сжатие - я без понятия.

                                                                                                                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                                                                                                                По первому предложению ... было бы здорово иметь систему архивации со скоростью отдачи информации равной производительности дисковой подсистемы и максимальной степенью сжатия. Это вообще сказка для больших контор, имхо.
                                                                                                                                                                                                                                                                                                Сообщение отредактировано: JoeUser -
                                                                                                                                                                                                                                                                                                  Цитата JoeUser @
                                                                                                                                                                                                                                                                                                  Навскидку два предложения:

                                                                                                                                                                                                                                                                                                  1) Распределенная версия 7z

                                                                                                                                                                                                                                                                                                  2) Процесс видеокодирования

                                                                                                                                                                                                                                                                                                  Спасибо! Есть над чем подумать... Хотя для распараллеливания обработки видео, скорее всего, IBB или HPX, а может даже и OpenMP, будут более подходящими инструментами.

                                                                                                                                                                                                                                                                                                  Тут вспомнилось несколько простых примеров, которые, с одной стороны, посложнее hello_world-а, а с другой более-менее приближены к реальности (в обратном хронологическом порядке):

                                                                                                                                                                                                                                                                                                  Чуть подробне про решение md5_bruteforce2 на SObjectizer
                                                                                                                                                                                                                                                                                                  Многопоточность и Pub-Sub с помощью SObjectizer
                                                                                                                                                                                                                                                                                                  На пути к 50M msg/sec... (Akka нам не страшна?)
                                                                                                                                                                                                                                                                                                  Разбор примера простой реализации дедлайнов для сообщений
                                                                                                                                                                                                                                                                                                  Пример решения проблемы Producer-Consumer в SO-5.5.1
                                                                                                                                                                                                                                                                                                  Асинхронность без порталов и телепортации :)
                                                                                                                                                                                                                                                                                                    Цитата eao197 @
                                                                                                                                                                                                                                                                                                    Хотя для распараллеливания обработки видео, скорее всего, IBB или HPX, а может даже и OpenMP, будут более подходящими инструментами.


                                                                                                                                                                                                                                                                                                    Если посмотреть с другой стороны, сжатие компрессорами и обработка видео - одного поля ягоды. Обработка входящего потока + получение сжатого. Просто на выходе разного качества инфа. В первом случае строго loseless, во втором - желательно. Одно только разнит их. Для архивов не принципиальна скорость разархивирования, для видеоматериала скорость "извлечения" кадров принципиальна.
                                                                                                                                                                                                                                                                                                      Одна из важнейших тем при работе с SO5 -- это использование исключений. Долго не удавалось выкроить время и подготовить более-менее подробный рассказ на эту тему. Сейчас удалось. Очередную часть серии Dive into SObjectizer-5.5, полностью посвященную исключениям, можно найти здесь (или на SlideShare).
                                                                                                                                                                                                                                                                                                        В одном из обсуждений SO-5 подкинули идею о том, а нельзя ли декларативно описывать цепочки обработки сообщений таким образом, чтобы все необходимые агенты и связи между ними создавались автоматически. Да еще и с контролем со стороны компилятора за соответствием типов сообщений и их обработчиков.

                                                                                                                                                                                                                                                                                                        Оказалось, что можно. Получается что-то вроде:
                                                                                                                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                          virtual void so_evt_start() override
                                                                                                                                                                                                                                                                                                          {
                                                                                                                                                                                                                                                                                                              // Создание конвейера.
                                                                                                                                                                                                                                                                                                              // Возвращается mbox самой первой стадии созданного конвейера.
                                                                                                                                                                                                                                                                                                              // Отсылая сообщения на этот mbox инициируется цепочка событий
                                                                                                                                                                                                                                                                                                              // по обработке отосланного сообщения.
                                                                                                                                                                                                                                                                                                              auto pipeline = make_pipeline( *this,
                                                                                                                                                                                                                                                                                                                      src | stage(validation) | stage(conversion) | broadcast(
                                                                                                                                                                                                                                                                                                                          src | stage(archivation),
                                                                                                                                                                                                                                                                                                                          src | stage(distribution),
                                                                                                                                                                                                                                                                                                                          src | stage(range_checking) | stage(alarm_detector{}) | broadcast(
                                                                                                                                                                                                                                                                                                                              src | stage(alarm_initiator),
                                                                                                                                                                                                                                                                                                                              src | stage( []( const alarm_detected & v ) {
                                                                                                                                                                                                                                                                                                                                      alarm_distribution( cerr, v );
                                                                                                                                                                                                                                                                                                                                  } )
                                                                                                                                                                                                                                                                                                                              )
                                                                                                                                                                                                                                                                                                                          ),
                                                                                                                                                                                                                                                                                                                      autoname );
                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                              send_delayed_to_agent< shutdown >( *this, chrono::seconds(1) );
                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                              // Использование конвейера.
                                                                                                                                                                                                                                                                                                              // Посредством отложенных сообщений имитируется поступление
                                                                                                                                                                                                                                                                                                              // данных от датчика температуры.
                                                                                                                                                                                                                                                                                                              for( uint8_t i = 0; i < static_cast< uint8_t >(250); i += 10 )
                                                                                                                                                                                                                                                                                                                  send_delayed< raw_value >(
                                                                                                                                                                                                                                                                                                                          so_environment(),
                                                                                                                                                                                                                                                                                                                          pipeline,
                                                                                                                                                                                                                                                                                                                          chrono::milliseconds( i ),
                                                                                                                                                                                                                                                                                                                          raw_measure{ 0, 0, i } );
                                                                                                                                                                                                                                                                                                          }

                                                                                                                                                                                                                                                                                                        Более подробное описание можно найти здесь. Собственно, сейчас самый большой вопрос такой: имеет смысл продолжать эти эксперименты? Или можно зафиксировать то, что получилось и пойти дальше.
                                                                                                                                                                                                                                                                                                          В следующей версии 5.6 планируется нарушить совместимость с версией 5.5. Что дает возможность упростить какие-то вещи в использовании SObjectizer. Например, отказаться от использования so_define_agent().

                                                                                                                                                                                                                                                                                                          Иногда говорят, что в SObjectizer "сложно врубиться". Можно упростить. И не только это. Нужно только определить, что вызывает сложности и недопонимание.
                                                                                                                                                                                                                                                                                                            Вышла версия 5.5.8.

                                                                                                                                                                                                                                                                                                            Версию 5.5.8 можно взять либо из секции Files на SF, либо из Svn-репозитория, либо из зеркала на GitHub.

                                                                                                                                                                                                                                                                                                            Если говорить кратко, то в версии 5.5.8 появилось следующее:
                                                                                                                                                                                                                                                                                                            • приоритеты у агентов и три новых диспетчера, которые выполняют обработку событий с учетом приоритетов;
                                                                                                                                                                                                                                                                                                            • более удобные средства работы с ad-hoc агентами;
                                                                                                                                                                                                                                                                                                            • несколько новых примеров.

                                                                                                                                                                                                                                                                                                            Если интересны подробности, то сюда, либо сюда, либо сюда.

                                                                                                                                                                                                                                                                                                            Краткую информацию о том, что такое SObjectizer можно найти здесь и далее по ссылкам.
                                                                                                                                                                                                                                                                                                              Мы подготовили рассказ о работе с таймерами (т.е. об использовании отложенных и периодических сообщений) в виде небольшой презентации (копия на slideshare).
                                                                                                                                                                                                                                                                                                                Может быть кого-то из читателей темы заинтересует: вот здесь дано описание нового примера, который показывает, для чего может потребоваться создавать несколько экземпляров SO Environment внутри одного приложения, и как это может выглядеть.
                                                                                                                                                                                                                                                                                                                  SObjectizer обновился до версии 5.5.9. Вкратце изменения таковы:
                                                                                                                                                                                                                                                                                                                  • возможность использовать произвольные типы в качестве типов сообщение (наследование от message_t больше не обязательно, но тип должен быть MoveConstructible);
                                                                                                                                                                                                                                                                                                                  • класс wrapped_env_t, позволяющий работать с SObjectizer Environment в более привычном для ООП стиле;
                                                                                                                                                                                                                                                                                                                  • возможность трассировки механизма доставки сообщения (для упрощения отладки SObjectizer-приложений и поиска ошибок, связанных с подписками и отсылкой сообщений не тем получателям);
                                                                                                                                                                                                                                                                                                                  • новые функции request_value и request_future для упрощения синхронного взаимодействия агентов;
                                                                                                                                                                                                                                                                                                                  • несколько новых вариантов функции send, позволяющие использовать send вместо send_to_agent (что удобно при обобщенном программировании);
                                                                                                                                                                                                                                                                                                                  • исправлено несколько ошибок, добавлена пара новых примеров.
                                                                                                                                                                                                                                                                                                                  Чуть подробнее об изменениях рассказывается в этой презентации или в этом посте. Полный список изменений можно найти в Wiki.

                                                                                                                                                                                                                                                                                                                  Так же сделаны две новые презентации, которые коротко рассказывают о таких возможностях SO-5.5, как синхронное взаимодействие агентов и лимиты для сообщений.

                                                                                                                                                                                                                                                                                                                  Версию 5.5.9 можно взять либо из секции Files на SF, либо из Svn-репозитория, либо из зеркала на GitHub (на GitHub-е теперь git submodules не используется, так что самую последнюю версию можно просто скачать с GitHub-а в виде архива и в ней сразу будут все необходимые подпроекты).
                                                                                                                                                                                                                                                                                                                    В обсуждениях SO-5 часто упоминалось, что у нас не удобный/понятный API. Есть желание сделать его удобнее и понятнее. Например, вот такой шаг был бы шагом в верном направлении?
                                                                                                                                                                                                                                                                                                                      Цитата eao197 @
                                                                                                                                                                                                                                                                                                                      Например, вот такой шаг был бы шагом в верном направлении?

                                                                                                                                                                                                                                                                                                                      Возможно вам удобнее, но, имхо, количество подчеркиваний в вашем коде зашкаливает за 9000! Не скажу за всех, скажу за себя, наличие подчеркиваний в "публичных интерфейсах" библиотеки меня приводит в уныние. Не знаю. Возможно дело привычки. Стереотипы ломать сложно. Это наверное самое первое, но, как говорят "встречают по одежке".

                                                                                                                                                                                                                                                                                                                      Второе. "Шапка" темы ужасная и неструктурированная. Уберите нафик детали!

                                                                                                                                                                                                                                                                                                                      * описание
                                                                                                                                                                                                                                                                                                                      * возможности
                                                                                                                                                                                                                                                                                                                      * области применения
                                                                                                                                                                                                                                                                                                                      * работающие примеры использования
                                                                                                                                                                                                                                                                                                                      * глоссарий и "расшифровка" деталей под сполйлерах

                                                                                                                                                                                                                                                                                                                      Остальное все нафик, ибо пофик! Меньше слов, больше конкретики и обобщений.
                                                                                                                                                                                                                                                                                                                      Чисто мое ИМХО, без обид.
                                                                                                                                                                                                                                                                                                                        Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                        Не скажу за всех, скажу за себя, наличие подчеркиваний в "публичных интерфейсах" библиотеки меня приводит в уныние.


                                                                                                                                                                                                                                                                                                                        Э... Ну вот возьмем произвольный пример:

                                                                                                                                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                          namespace props = so_5::rt::mchain_props;
                                                                                                                                                                                                                                                                                                                          so_5::rt::mchain_params{
                                                                                                                                                                                                                                                                                                                               props::capacity::make_limited_without_waiting(
                                                                                                                                                                                                                                                                                                                                    5,
                                                                                                                                                                                                                                                                                                                                    props::storage_memory::dynamic,
                                                                                                                                                                                                                                                                                                                                    props::overflow_reaction::drop_newest ) }


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

                                                                                                                                                                                                                                                                                                                        Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                        Второе. "Шапка" темы ужасная и неструктурированная. Уберите нафик детали!


                                                                                                                                                                                                                                                                                                                        На счет "шапки" темы не понял. Речь по самое первое сообщение в теме?
                                                                                                                                                                                                                                                                                                                        Сообщение отредактировано: eao197 -
                                                                                                                                                                                                                                                                                                                          Цитата eao197 @
                                                                                                                                                                                                                                                                                                                          Э... Ну вот возьмем произвольный пример: Как бы вы уменьшили количество подчеркиваний в нем?


                                                                                                                                                                                                                                                                                                                          Мне бы так читалось в 7,4 раза бы приятнее:
                                                                                                                                                                                                                                                                                                                          ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                namespace Props = Olib::Rt::MChainProps;
                                                                                                                                                                                                                                                                                                                                Olib::Rt::MChainParams{
                                                                                                                                                                                                                                                                                                                                     Props::Capacity::MakeLimitedWithoutWaiting(
                                                                                                                                                                                                                                                                                                                                          5,
                                                                                                                                                                                                                                                                                                                                          Props::StorageMemory::Dynamic,
                                                                                                                                                                                                                                                                                                                                          Props::OverflowReaction::DropNewest ) }

                                                                                                                                                                                                                                                                                                                          Цитата eao197 @
                                                                                                                                                                                                                                                                                                                          На счет "шапки" темы не понял. Речь по самое первое сообщение в теме?

                                                                                                                                                                                                                                                                                                                          Именно. Если в тему "влететь" на середине обсуждения - черт ногу сломит. Ясный перец, прыгаем в начало начал. Там должны быть анонсы, резюмешки, и прочая обобщающая инфа. А в середине, внезапно, видим ... куски кода. Зачем код, когда еще "интерес не захвачен"???
                                                                                                                                                                                                                                                                                                                            Цитата eao197 @
                                                                                                                                                                                                                                                                                                                            Например, вот такой шаг был бы шагом в верном направлении?

                                                                                                                                                                                                                                                                                                                            Лично я вообще против всяких префиксов/суффиксов, и прочих способов выделения идентификатора.

                                                                                                                                                                                                                                                                                                                            Добавлено
                                                                                                                                                                                                                                                                                                                            Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                            Мне бы так читалось в 7,4 раза бы приятнее

                                                                                                                                                                                                                                                                                                                            Это всё субъективщина. Мне stl-style нравится гораздо больше.
                                                                                                                                                                                                                                                                                                                              Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                              Лично я вообще против всяких префиксов/суффиксов, и прочих способов выделения идентификатора.

                                                                                                                                                                                                                                                                                                                              Плюсую.
                                                                                                                                                                                                                                                                                                                                Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                                Мне бы так читалось в 7,4 раза бы приятнее:
                                                                                                                                                                                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                      namespace Props = Olib::Rt::MChainProps;
                                                                                                                                                                                                                                                                                                                                      Olib::Rt::MChainParams{
                                                                                                                                                                                                                                                                                                                                           Props::Capacity::MakeLimitedWithoutWaiting(
                                                                                                                                                                                                                                                                                                                                                5,
                                                                                                                                                                                                                                                                                                                                                Props::StorageMemory::Dynamic,
                                                                                                                                                                                                                                                                                                                                                Props::OverflowReaction::DropNewest ) }

                                                                                                                                                                                                                                                                                                                                Библиотека была написана с использованием snake_case, в C++компьюнити это один из самых распространенных стилей. Перейти на CamelCase означает все переписать. Да и у CamelCase противников даже больше, чем у snake_case. Я сам, например, очень долго использовал CamelCase, но затем отказался от него в пользу snake_case, дабы глаза поберечь.
                                                                                                                                                                                                                                                                                                                                  Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                  Это всё субъективщина. Мне stl-style нравится гораздо больше.

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

                                                                                                                                                                                                                                                                                                                                  ЗЫ: За исключением clib, где это возведено в ритуалЪ:)
                                                                                                                                                                                                                                                                                                                                    Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                                    Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                    На счет "шапки" темы не понял. Речь по самое первое сообщение в теме?

                                                                                                                                                                                                                                                                                                                                    Именно. Если в тему "влететь" на середине обсуждения - черт ногу сломит. Ясный перец, прыгаем в начало начал. Там должны быть анонсы, резюмешки, и прочая обобщающая инфа. А в середине, внезапно, видим ... куски кода. Зачем код, когда еще "интерес не захвачен"???

                                                                                                                                                                                                                                                                                                                                    По согласованию с администрацией форума мы обсуждения всех обновлений SO-5 делаем в той же самой теме, в которой был сделан первый анонс. Поэтому вот такая вот картинка и получается.
                                                                                                                                                                                                                                                                                                                                      Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                      Библиотека была написана с использованием snake_case, в C++компьюнити это один из самых распространенных стилей. Перейти на CamelCase означает все переписать. Да и у CamelCase противников даже больше, чем у snake_case. Я сам, например, очень долго использовал CamelCase, но затем отказался от него в пользу snake_case, дабы глаза поберечь.

                                                                                                                                                                                                                                                                                                                                      Вы меня теряете!!! :lol:
                                                                                                                                                                                                                                                                                                                                        Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                        Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                        Например, вот такой шаг был бы шагом в верном направлении?

                                                                                                                                                                                                                                                                                                                                        Лично я вообще против всяких префиксов/суффиксов, и прочих способов выделения идентификатора.

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

                                                                                                                                                                                                                                                                                                                                        Добавлено
                                                                                                                                                                                                                                                                                                                                        Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                                        Вы меня теряете!!! :lol:

                                                                                                                                                                                                                                                                                                                                        Так как же вы стандартной библиотекой C++ пользуетесь? Или Boost-ом?
                                                                                                                                                                                                                                                                                                                                          Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                          Ну вот сейчас предоставляется возможность от суффиксов избавиться и привести имена в библиотеке к стилю, который используется в STL/Boost. Но т.к. это не бесплатно, то хочется понять, оправдано ли это будет или нет. Грубо говоря, определить, скольким людям суффиксы мешают.

                                                                                                                                                                                                                                                                                                                                          Это всё субъективно, а не объективно. Потому и заменяться должно по такому же принципу: захотелось - заменили.
                                                                                                                                                                                                                                                                                                                                            Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                            Или Boost-ом?

                                                                                                                                                                                                                                                                                                                                            Я очень уважаю коллег, которые пользуются бустом! Но, к своему стыду, никогда им не пользовался. Использую Qt5 для своих задач. Сперва все было просто фантастически, но, со временем, эйфория ушла. Увы. Возможно тутошнее общение, возможно Oraizer, возможно искривление пространственно-временного континуума, привели меня к мысли, что - кулл это STL, это хорошо и правильно!

                                                                                                                                                                                                                                                                                                                                            Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                            Грубо говоря, определить, скольким людям суффиксы мешают.

                                                                                                                                                                                                                                                                                                                                            Отсебятина. Нафик вложение в переменные смысла! Если_вы_определите_переменную_обладающую_смыслом - легче не будет! Используйте однобуквенный идентификатор + комментарии. Это сократит код и повысит наглядность. ИМХО.
                                                                                                                                                                                                                                                                                                                                              Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                              Это всё субъективно, а не объективно. Потому и заменяться должно по такому же принципу: захотелось - заменили.

                                                                                                                                                                                                                                                                                                                                              Так-то оно так, но есть объективные течения. И плыть против них сейчас, наверное, смысла нет.
                                                                                                                                                                                                                                                                                                                                                Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                Это всё субъективно, а не объективно. Потому и заменяться должно по такому же принципу: захотелось - заменили.

                                                                                                                                                                                                                                                                                                                                                Так-то оно так, но есть объективные течения. И плыть против них сейчас, наверное, смысла нет.

                                                                                                                                                                                                                                                                                                                                                Объективно суффикс _t используется в исчезающем числе библиотек, и я никогда не встречал его в своей практике.
                                                                                                                                                                                                                                                                                                                                                  Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                                                  привели меня к мысли, что - кулл это STL, это хорошо и правильно!

                                                                                                                                                                                                                                                                                                                                                  Ну так как же unordered_map, enable_if, is_trivially_copyable, is_member_function_pointer, high_resolution_clock, treat_as_floating_point и т.д.? ;)
                                                                                                                                                                                                                                                                                                                                                    Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                    Ну так как же unordered_map, enable_if, is_trivially_copyable, is_member_function_pointer, high_resolution_clock, treat_as_floating_point и т.д.?

                                                                                                                                                                                                                                                                                                                                                    Вот ты специально привел примеры, которые меня раздражают? :lol:
                                                                                                                                                                                                                                                                                                                                                      Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                      Объективно суффикс _t используется в исчезающем числе библиотек, и я никогда не встречал его в своей практике.

                                                                                                                                                                                                                                                                                                                                                      В стандартной библиотеке _t присутствует давно (в виде size_t, ptrdiff_t, intptr_t), а в последних стандартах его становится все больше и больше (начиная от int8_t со товарищи, и заканчивая enable_if_t, decay_t, common_type_t и т.д.) Другое дело, что лет 15 назад был зоопарк нотаций (скажем, в STL своя нотация, в Qt своя, в ACE своя). Теперь этот зоопарк резко уменьшился. И уже нет смысла выбиваться из мейнстримовых направлений :)
                                                                                                                                                                                                                                                                                                                                                        Просто для инфы ... к С/С++ я шел долгими путями. Если не ошибусь, это примерно так: PL/1-Pascal-ASM86-Clarion-Perl-C++ ... Подчеркивания зажигают во мне берсерка :lol:
                                                                                                                                                                                                                                                                                                                                                          Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                                                          Вот ты специально привел примеры, которые меня раздражают?

                                                                                                                                                                                                                                                                                                                                                          Да нет, просто показываю, что мы не делаем ничего экстраординарного :)
                                                                                                                                                                                                                                                                                                                                                            И тем не менее... so_5::rt::mchain_params - выделенное некрасиво и убого, имхо. Последний идентификатор - длинный и ничего не говорит новичку, ничего. Если бы это было "a", ничего бы не изменилось.
                                                                                                                                                                                                                                                                                                                                                              Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                              В стандартной библиотеке _t присутствует давно (в виде size_t, ptrdiff_t, intptr_t)

                                                                                                                                                                                                                                                                                                                                                              Это из C.
                                                                                                                                                                                                                                                                                                                                                              Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                              начиная от int8_t со товарищи

                                                                                                                                                                                                                                                                                                                                                              Вот это хз почему.
                                                                                                                                                                                                                                                                                                                                                              Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                              и заканчивая enable_if_t, decay_t, common_type_t

                                                                                                                                                                                                                                                                                                                                                              А это для алиасов.
                                                                                                                                                                                                                                                                                                                                                                Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                                А это для алиасов.

                                                                                                                                                                                                                                                                                                                                                                Ну вот как раз потому, что новые стандарты C++ стали использовать суффикс _t таким образом, и возникло в очередной раз желание пересмотреть свою нотацию дабы не вводить пользователей в заблуждение.
                                                                                                                                                                                                                                                                                                                                                                  Думал тут интересное что-то, а они о стилях спорят :)

                                                                                                                                                                                                                                                                                                                                                                  Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                                  Ну вот как раз потому, что новые стандарты C++ стали использовать суффикс _t таким образом, и возникло в очередной раз желание пересмотреть свою нотацию дабы не вводить пользователей в заблуждение.

                                                                                                                                                                                                                                                                                                                                                                  Ну так вы каждый раз будете под кого-то подстраиваться? :)
                                                                                                                                                                                                                                                                                                                                                                  Префиксы/постфиксы полезны в С, в С++ особого смысла в них не вижу.
                                                                                                                                                                                                                                                                                                                                                                    Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                                                                    выделенное некрасиво и убого, имхо. Последний идентификатор - длинный и ничего не говорит новичку, ничего. Если бы это было "a", ничего бы не изменилось.

                                                                                                                                                                                                                                                                                                                                                                    SO-5, хоть и небольшая библиотека, но не сказал бы, что тривиальная. Без некоторого погружения в тему не обойтись. Поэтому mchain_params ничего не говорит абсолютному новичку, но это не значит, что такое имя останется непонятным при знакомстве с библиотекой.

                                                                                                                                                                                                                                                                                                                                                                    so_5 -- это имя самого верхнего пространства имен. Как в Boost-е -- boost, в spd_log -- spdlog и т.д. Цифра 5 в so_5 так же имеет смысл, поскольку раньше был so_4. И были проекты, в которых совместно использовались so_4 и so_5.

                                                                                                                                                                                                                                                                                                                                                                    Добавлено
                                                                                                                                                                                                                                                                                                                                                                    Цитата D_KEY @
                                                                                                                                                                                                                                                                                                                                                                    Ну так вы каждый раз будете под кого-то подстраиваться?

                                                                                                                                                                                                                                                                                                                                                                    Практика показывает, что в любом публичном обсуждении SO-5 наибольшее количество обсуждений возникает не вокруг функциональности и возможностей, а вокруг имен и нотации. Может выбрасывание суффикса _t хоть чуть-чуть подсократит это дело :)
                                                                                                                                                                                                                                                                                                                                                                      Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                                      SO-5

                                                                                                                                                                                                                                                                                                                                                                      Библиотека ниочем! "Больно" слышать? Верю! SO-5 неправильная "торговая марка"! И именно она делает ее такой, и не реализация, и не возможности! Именно подача. Должно быть "СуперБиблиотека" с переменными A,B,C ... А не наоборот, библиотека A,B,C (или SO-5), с классными красивыми по названиям методами.

                                                                                                                                                                                                                                                                                                                                                                      Чисто ради интереса ...
                                                                                                                                                                                                                                                                                                                                                                        Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                                        Практика показывает, что в любом публичном обсуждении SO-5 наибольшее количество обсуждений возникает не вокруг функциональности и возможностей, а вокруг имен и нотации

                                                                                                                                                                                                                                                                                                                                                                        :D
                                                                                                                                                                                                                                                                                                                                                                          ... Хотя ... умерю пыл :lol: Вы же законно сможете спросить "а сколько библиотек продал ты?!". К своему стыду, ни одной. Впору вспомнить Жванецкого с его корреляцией московской прописки к уровню познания архитектуры .... :lol:

                                                                                                                                                                                                                                                                                                                                                                          Добавлено
                                                                                                                                                                                                                                                                                                                                                                          Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                                          :D

                                                                                                                                                                                                                                                                                                                                                                          Игорь, как ты считаешь, есть ли повод для "призадуматься"? Ну по поводу имен, нотаций ... ;) ?
                                                                                                                                                                                                                                                                                                                                                                            Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                                                                            Игорь, как ты считаешь, есть ли повод для "призадуматься"? Ну по поводу имен, нотаций ... ?

                                                                                                                                                                                                                                                                                                                                                                            О чём призадуматься? Стилей наименования много, мой любимый я озвучил. Какой применять для библиотеки - дело её авторов.
                                                                                                                                                                                                                                                                                                                                                                              Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                                              я озвучил

                                                                                                                                                                                                                                                                                                                                                                              Кинь, плс, линк. Я пропустил где это.
                                                                                                                                                                                                                                                                                                                                                                                Вот же
                                                                                                                                                                                                                                                                                                                                                                                Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                                                Мне stl-style нравится гораздо больше
                                                                                                                                                                                                                                                                                                                                                                                  Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                                                  Вот же

                                                                                                                                                                                                                                                                                                                                                                                  А, оке! Пасип.
                                                                                                                                                                                                                                                                                                                                                                                    Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                                                                                    И тем не менее... so_5::rt::mchain_params - выделенное некрасиво и убого, имхо. Последний идентификатор - длинный и ничего не говорит новичку, ничего. Если бы это было "a", ничего бы не изменилось.
                                                                                                                                                                                                                                                                                                                                                                                    JoeUser, а как надо-то?
                                                                                                                                                                                                                                                                                                                                                                                    А в целом, никто не запрещает namespace fromTheCeiling = so_5. Или namespace mySo = so_5::rt.

                                                                                                                                                                                                                                                                                                                                                                                    Добавлено
                                                                                                                                                                                                                                                                                                                                                                                    Цитата JoeUser @
                                                                                                                                                                                                                                                                                                                                                                                    Возможно тутошнее общение, возможно Oraizer, возможно искривление пространственно-временного континуума, привели меня к мысли, что - кулл это STL, это хорошо и правильно!
                                                                                                                                                                                                                                                                                                                                                                                    Вообще-то, если я правильно помню контекст, я только предложил не путать библиотеки с фреймворками. Так-то против Qt я ничего не имею, однако всему своё место.
                                                                                                                                                                                                                                                                                                                                                                                      Цитата Qraizer @
                                                                                                                                                                                                                                                                                                                                                                                      JoeUser, а как надо-то?

                                                                                                                                                                                                                                                                                                                                                                                      Вместо этого, нечто типа "SuperLibrary", ну или как-то так. S0_ как-то несерьезно (но это чисто имхо).

                                                                                                                                                                                                                                                                                                                                                                                      Цитата Qraizer @
                                                                                                                                                                                                                                                                                                                                                                                      А в целом, никто не запрещает

                                                                                                                                                                                                                                                                                                                                                                                      ... и не кто не запрещает подчеркивание ... а почему тогда гавняют UTF-8 в именах преременных?
                                                                                                                                                                                                                                                                                                                                                                                        Кто? Стандарт разрешает реализациям использовать любые символы из расширенного набора, но сам расширенный набор не определяет. Так что если твой компилятор позволяет, юзай на здоровье, но в переносимости ты потеряешь. Также не стандартизированы допустимые кодировки для файлов исходных текстов. Но ты всегда можешь использовать UNC, только это будет нечитабельно от слова вообще.

                                                                                                                                                                                                                                                                                                                                                                                        Так что Стандарт не возражает, но если ты имеешь в виду коллег, то это более чем ожидаемо.
                                                                                                                                                                                                                                                                                                                                                                                          Цитата Qraizer @
                                                                                                                                                                                                                                                                                                                                                                                          Вообще-то, если я правильно помню контекст, я только предложил не путать библиотеки с фреймворками. Так-то против Qt я ничего не имею, однако всему своё место.

                                                                                                                                                                                                                                                                                                                                                                                          Не, ты вообще не при чем. Вернее, сознательно. :D Просто я тебя упомянул по той причине, что в твоих примерах я видел хорошее применение STL, не худшее, чем это можно реализовать с помощью Qt. Вот такой вот был контекст.
                                                                                                                                                                                                                                                                                                                                                                                            Вот какая штука готовиться к релизу в версии 5.5.13. Уже полностью работает, но окончательно не зафиксирована. Поэтому еще есть возможность что-то переделать, если вдруг обнаружатся какие-то фатальные недостатки.
                                                                                                                                                                                                                                                                                                                                                                                              SObjectizer обновился до версии 5.5.13. Подробности релиза можно узнать здесь. Сорри, что не выкладываю краткого описания изменений. Надеюсь, что тем, кто проектом интересуется, не составит труда пройти по ссылке и прочесть нормальное описание релиза.
                                                                                                                                                                                                                                                                                                                                                                                                За последнее время:
                                                                                                                                                                                                                                                                                                                                                                                                • состоялся релиз версии 5.5.14, в которой произведена унификация форматов разных типов обработчиков сообщений;
                                                                                                                                                                                                                                                                                                                                                                                                • подготовлен пример, показывающий, как механизм mchain может использоваться в механизмах overload control для агентов;
                                                                                                                                                                                                                                                                                                                                                                                                • более-менее обозначились планы на ближайшее будущее:
                                                                                                                                                                                                                                                                                                                                                                                                  • подготовка презентации об опыте использования SObjectizer-а и извлеченных из этого опыта уроках;
                                                                                                                                                                                                                                                                                                                                                                                                  • эксперименты по интеграции SObjectizer-а в GUI-приложения посредством использования механизма mchain-ов;
                                                                                                                                                                                                                                                                                                                                                                                                  • подготовка еще одной, может быть двух, презентаций для серии Deep Dive into SObjectizer-5.5. По крайней мере нужно рассказать подробнее о диспетчерах. Ну и об mchain-ах, если получится;
                                                                                                                                                                                                                                                                                                                                                                                                  • проработка двух больших фич для следующих версий SO-5: возможность представления агентов в виде иерархических конечных автоматов (с историческими состояниями, с реакциями на вход-выход и т.д.) и возможность использования в диспетчерах преаллоцированных буферов в качестве очередей сообщений (при этом экземпляр сообщения не создается динамически, как сейчас, а конструируется in-place в буфере диспетчера). Имхо, фичи очень важные, особенно для определенных классов задач. Но пока понятные лишь в общих чертах. Так что здесь еще над чем подумать.
                                                                                                                                                                                                                                                                                                                                                                                                Собственно говоря, если у кого-то есть вопросы/замечания/предложения, то сейчас удобный момент для того, чтобы уделить этому какое-то время. Так, если вам что-то не нравится в SO-5 или чего-то сильно не хватает и вы найдете возможность об этом сказать, то ваши пожелания вполне могут быть учтены в ближайших релизах SObjectizer-а.
                                                                                                                                                                                                                                                                                                                                                                                                  Есть мысль расшить возможности агентов SO-5 так, чтобы они могли представлять из себя иерархические конечные автоматы. Вот здесь описано первое приближение к тому, как это могло бы выглядеть. Интересно было бы получить фидбек по поводу этой идеи.
                                                                                                                                                                                                                                                                                                                                                                                                    В SO-5.5.15 будет возможность задавать ограничение по времени пребывания агента в конкретном состоянии. А так же отменять это ограничения. Но не станет ли поведение связки методов time_limit/drop_time_limit неприятным сюрпризом для пользователей? Интересны любые мнения.
                                                                                                                                                                                                                                                                                                                                                                                                        SObjectizer -- это небольшой фреймворк для упрощения разработки многопоточных приложений на C++11 за счет использования идей из моделей акторов и publish-subscribe. SObjectizer является OpenSource-проектом и распространяется под трехпунктной BSD-лицензией.

                                                                                                                                                                                                                                                                                                                                                                                                        Этот релиз добавляет возможность создания агентов в виде иерархических конечных автоматов. В версии 5.5.15 поддерживаются такие вещи, как композитные состояния, shallow- и deep-история, обработчики входа/выхода, лимиты времени, передача события на обработку в другое состояние (что-то вроде defer) и подавление событий.

                                                                                                                                                                                                                                                                                                                                                                                                        Малюсенький примерчик для демонстрации новых возможностей: агент, который реализует мигающий LED-индикатор. Этот агент обрабатывает сигнал `turn_on_off` для включения и выключения режима мигания. Когда режим мигания включен, агент зажигает LED-индикатор на 1.5 секунды, затем тушит его на 0.75 секунды, затем опять зажигает и опять тушит и так до тех пор, пока не получит следующий сигнал `turn_on_off`. В виде диаграммы состояний этот конечный автомат может быть представлен следующим образом:
                                                                                                                                                                                                                                                                                                                                                                                                        user posted image

                                                                                                                                                                                                                                                                                                                                                                                                        Код этого агента может выглядеть вот так:
                                                                                                                                                                                                                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                          class blinking_led final : public so_5::agent_t
                                                                                                                                                                                                                                                                                                                                                                                                          {
                                                                                                                                                                                                                                                                                                                                                                                                              state_t off{ this },
                                                                                                                                                                                                                                                                                                                                                                                                                  blinking{ this },
                                                                                                                                                                                                                                                                                                                                                                                                                  blink_on{ initial_substate_of{ blinking } },
                                                                                                                                                                                                                                                                                                                                                                                                                  blink_off{ substate_of{ blinking } };
                                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                          public :
                                                                                                                                                                                                                                                                                                                                                                                                              struct turn_on_off : public so_5::signal_t {};
                                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                              blinking_led( context_t ctx ) : so_5::agent_t{ ctx }
                                                                                                                                                                                                                                                                                                                                                                                                              {
                                                                                                                                                                                                                                                                                                                                                                                                                  this >>= off;
                                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                  off.just_switch_to< turn_on_off >( blinking );
                                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                  blinking.just_switch_to< turn_on_off >( off );
                                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                  blink_on
                                                                                                                                                                                                                                                                                                                                                                                                                      .on_enter( []{ /* some device-specific code */ } )
                                                                                                                                                                                                                                                                                                                                                                                                                      .on_exit( []{ /* some device-specific code */ } )
                                                                                                                                                                                                                                                                                                                                                                                                                      .time_limit( std::chrono::milliseconds{1500}, blink_off );
                                                                                                                                                                                                                                                                                                                                                                                                           
                                                                                                                                                                                                                                                                                                                                                                                                                  blink_off
                                                                                                                                                                                                                                                                                                                                                                                                                      .time_limit( std::chrono::milliseconds{750}, blink_on );
                                                                                                                                                                                                                                                                                                                                                                                                              }
                                                                                                                                                                                                                                                                                                                                                                                                          };


                                                                                                                                                                                                                                                                                                                                                                                                        Более подробно поддержка иерархических конечных автоматов описана в Wiki проекта: so-5.5 In-depth - Agent States и в обновленной презентации Dive into SObjectizer-5.5. Second Part: Agent's States

                                                                                                                                                                                                                                                                                                                                                                                                        Взять версию 5.5.15 можно либо из раздела Files на SouceForge, либо из Svn репозитория, либо из зеркала на GitHub.
                                                                                                                                                                                                                                                                                                                                                                                                          Обновилась серия презентаций Dive into SObjectizer-5.5, которая выполняет плавное погружение пользователя в возможности и особенности SObjectizer-а. Теперь все части описывают самую последнюю стабильную версию -- 5.5.15.

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

                                                                                                                                                                                                                                                                                                                                                                                                          На данный момент в серию входит семь презентаций:Еще парочка (про диспетчеры и mchain-ы), надеюсь, появится в ближайшие две-три недели.
                                                                                                                                                                                                                                                                                                                                                                                                              Создана тема для сбора хотелок для следующей версии SObjectizer: Version 5.5.16 Wish List.

                                                                                                                                                                                                                                                                                                                                                                                                              Предположительно, она будет выпущена в марте или в апреле 2016. Сроки выхода зависят от объема и сложности нововведений. А повлиять на этот объем/сложность можно оставив свою хотелку в обсуждении по ссылке или прямо здесь.
                                                                                                                                                                                                                                                                                                                                                                                                                Еще один маленький примерчик: Конкурентный HelloWorld на Go и на C++.
                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                                                                                  Еще один маленький примерчик: Конкурентный HelloWorld на Go и на C++.

                                                                                                                                                                                                                                                                                                                                                                                                                  :facepalm: кто так пишет? Ничего, что между print("hello ") и println("world!") какой-нибудь другой поток может вставить свой print?

                                                                                                                                                                                                                                                                                                                                                                                                                  ExpandedWrap disabled
                                                                                                                                                                                                                                                                                                                                                                                                                    package main
                                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                    import "fmt"
                                                                                                                                                                                                                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                                                                                                                                                                    func main() {
                                                                                                                                                                                                                                                                                                                                                                                                                        sayHello := make(chan string)
                                                                                                                                                                                                                                                                                                                                                                                                                        messages := make(chan string)
                                                                                                                                                                                                                                                                                                                                                                                                                        done     := make(chan string)
                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                        go func() {
                                                                                                                                                                                                                                                                                                                                                                                                                            for i := 0; i < 10; i++ {
                                                                                                                                                                                                                                                                                                                                                                                                                                sayHello <- "Hello"
                                                                                                                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                                                                                                                            close(sayHello)
                                                                                                                                                                                                                                                                                                                                                                                                                        }()
                                                                                                                                                                                                                                                                                                                                                                                                                        go func() {
                                                                                                                                                                                                                                                                                                                                                                                                                            for hello := range sayHello {
                                                                                                                                                                                                                                                                                                                                                                                                                                messages <- hello + " World!"
                                                                                                                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                                                                                                                            close(messages)
                                                                                                                                                                                                                                                                                                                                                                                                                        }()
                                                                                                                                                                                                                                                                                                                                                                                                                        go func() {
                                                                                                                                                                                                                                                                                                                                                                                                                            i := 0
                                                                                                                                                                                                                                                                                                                                                                                                                            for msg := range messages {
                                                                                                                                                                                                                                                                                                                                                                                                                                fmt.Println(fmt.Sprintf("%d. %s", i, msg))
                                                                                                                                                                                                                                                                                                                                                                                                                                i++
                                                                                                                                                                                                                                                                                                                                                                                                                            }
                                                                                                                                                                                                                                                                                                                                                                                                                            done <- "Done"
                                                                                                                                                                                                                                                                                                                                                                                                                        }()
                                                                                                                                                                                                                                                                                                                                                                                                                        <-done
                                                                                                                                                                                                                                                                                                                                                                                                                    }


                                                                                                                                                                                                                                                                                                                                                                                                                  http://play.golang.org/p/57HuG9jgt8
                                                                                                                                                                                                                                                                                                                                                                                                                    Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                                    Ничего, что между print("hello ") и println("world!") какой-нибудь другой поток может вставить свой print?
                                                                                                                                                                                                                                                                                                                                                                                                                    В данном примере это не страшно, так как никаких других потоков просто нет.
                                                                                                                                                                                                                                                                                                                                                                                                                    Другое дело, что использовать каналы всего лишь для синхронизации потоков, пожалуй, слишком расточительно.
                                                                                                                                                                                                                                                                                                                                                                                                                      Цитата korvin @
                                                                                                                                                                                                                                                                                                                                                                                                                      кто так пишет? Ничего, что между print("hello ") и println("world!") какой-нибудь другой поток может вставить свой print?


                                                                                                                                                                                                                                                                                                                                                                                                                      Во-первых, исходный пример не мой. Я его нашел уже в таком вот виде. Моей задачей было показать, как тоже самое можно сделать на C++.

                                                                                                                                                                                                                                                                                                                                                                                                                      Во-вторых, как раз в данном примере никто не должен вставлять свои принты между hello и world. Это типа демонстрация детерминированной передачи управления между рабочими потоками посредством каналов.
                                                                                                                                                                                                                                                                                                                                                                                                                        Выпущена версия 5.5.15.2 с поддержкой Android-а (поддержка реализована на основе CrystaX NDK).
                                                                                                                                                                                                                                                                                                                                                                                                                          Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                                                                                          Выпущена версия 5.5.15.2 с поддержкой Android-а (поддержка реализована на основе CrystaX NDK).

                                                                                                                                                                                                                                                                                                                                                                                                                          А на стандартном NDK почему не собирается?
                                                                                                                                                                                                                                                                                                                                                                                                                            Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                                                                                            А на стандартном NDK почему не собирается?


                                                                                                                                                                                                                                                                                                                                                                                                                            SO-5 был портирован под Андроид силами команды CrystaX NDK, целью которых является насыщение CrystaX NDK полезным для них софтом. Сам CrystaX NDK появился как следствие недостатков родного NDK из-за которых нормальная разработка под Android на С++ обходится слишком дорого. Подробнее об этом написано на сайте проекта CrystaX NDK.
                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                                                                                              Сам CrystaX NDK появился как следствие недостатков родного NDK из-за которых нормальная разработка под Android на С++ обходится слишком дорого. Подробнее об этом написано на сайте проекта CrystaX NDK.

                                                                                                                                                                                                                                                                                                                                                                                                                              Я как бы в курсе. Но многое, из-за чего изначально появился CrystaX NDK, было исправлено в оригинальном NDK. И вот прямо сейчас нам вовсе не дорого обходится единая кодовая база для Windows/Linux/Mac/Android.
                                                                                                                                                                                                                                                                                                                                                                                                                              CrystaX NDK, насколько мне известно, и сейчас, после всех улучшений оригинального NDK, более продвинутый. Потому я и спрашиваю: что такого вы используете в коде SO, что вам понадобился CrystaX? Вы вообще пробовали собирать SO оригинальным NDK?
                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                                                                                              SO-5 был портирован под Андроид силами команды CrystaX NDK

                                                                                                                                                                                                                                                                                                                                                                                                                              Что же они там изменяли для портирования?
                                                                                                                                                                                                                                                                                                                                                                                                                              Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                                                                                              целью которых является насыщение CrystaX NDK полезным для них софтом

                                                                                                                                                                                                                                                                                                                                                                                                                              Странно как-то... NDK нужен для разработчика. Какие библиотеки им собирать, решать разработчику. Зачем насыщать NDK каким-то софтом? Кому надо, тот соберёт.
                                                                                                                                                                                                                                                                                                                                                                                                                              Сообщение отредактировано: MyNameIsIgor -
                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                                                                                                Потому я и спрашиваю: что такого вы используете в коде SO, что вам понадобился CrystaX?

                                                                                                                                                                                                                                                                                                                                                                                                                                Еще раз: это не нам потребовался CrystaX NDK, это разработчики CrystaX NDK заинтересовались портированием SO под Android. И сделали этот порт под свой NDK.

                                                                                                                                                                                                                                                                                                                                                                                                                                Сам SO-5 не использует ничего за пределами стандартной библиотеки C++11.

                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                                                                                                Вы вообще пробовали собирать SO оригинальным NDK.

                                                                                                                                                                                                                                                                                                                                                                                                                                Нет. Основной команде SO-5 надобности в поддержке платформы Android не было до сих пор.

                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                                                                                                Что же они там изменяли для портирования?

                                                                                                                                                                                                                                                                                                                                                                                                                                Были поправлены CMake-овские проектные файлы под особенности кросс-платформенной сборки. Так же были увеличены тайм-ауты в ряде юнит-тестов, чтобы тестовые сценарии успевали отрабатывать на слабых процессорах и на эмуляторах.

                                                                                                                                                                                                                                                                                                                                                                                                                                В самом SO-5 ничего не исправлялось.

                                                                                                                                                                                                                                                                                                                                                                                                                                Цитата MyNameIsIgor @
                                                                                                                                                                                                                                                                                                                                                                                                                                Странно как-то... NDK нужен для разработчика.

                                                                                                                                                                                                                                                                                                                                                                                                                                Разработчики CrystaX NDK решают свою задачи. Как я понимаю, им нужно простота разработки под Android, поэтому они и сделали свой NDK и на основе этого NDK портировали на Android тот же Boost. Потому что им нужен Boost. Может им и SO-5 для чего-то понадобился. Вот они и его решили портировать. Заодно реализовав поддержку CMake в своем NDK.
                                                                                                                                                                                                                                                                                                                                                                                                                                  Цитата eao197 @
                                                                                                                                                                                                                                                                                                                                                                                                                                  Еще раз: это не нам потребовался CrystaX NDK, это разработчики CrystaX NDK заинтересовались портированием SO под Android

                                                                                                                                                                                                                                                                                                                                                                                                                                  Ok
                                                                                                                                                                                                                                                                                                                                                                                                                                    Мы провели сравнение производительности SO-5.5.15 и CAF-0.14.4. Вкратце результаты такие: операции создания/удаления агентов в SO-5 медленнее, отсылка и доставка сообщений в SO-5 быстрее.

                                                                                                                                                                                                                                                                                                                                                                                                                                    Плюс объяснение, почему в SO-5 создание/удаление агентов обходится дороже, чем в других инструментах.
                                                                                                                                                                                                                                                                                                                                                                                                                                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                                                                                                                                                                                                                                                                                                                                                                      0 пользователей:


                                                                                                                                                                                                                                                                                                                                                                                                                                      Рейтинг@Mail.ru
                                                                                                                                                                                                                                                                                                                                                                                                                                      [ Script execution time: 0,5432 ]   [ 18 queries used ]   [ Generated: 28.03.24, 16:13 GMT ]