среда, 12 августа 2015 г.

[prog.c++11] Описание агентов в SObjectizer: старый подход против нового (модного и молодежного)...

Год назад, когда в версии 5.3.0 появились ad-hoc агенты (агенты, для которых не нужно было описывать отдельный C++ класс), область применения таких агентов казалась очень узкой. Поэтому и функциональность, доступная в ad-hoc агентах, была меньше, чем в обычных, полноценных агентах. По-началу даже не было возможности получить доступ к direct_mbox-у ad-hoc агента.

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

struct send_next : public so_5::rt::signal_t {};
struct stop : public so_5::rt::signal_t {};

class a_test_t : public so_5::rt::agent_t
   {
   public :
      a_test_t( context_t ctx )
         :  so_5::rt::agent_t( ctx +
               limit_then_drop< send_next >( 100 ) +
               limit_then_drop< stop >( 1 ) +
               so_5::prio::p0 )
         {}

      virtual void so_define_agent() override
         {
            so_subscribe_self().event< send_next >(
                  &a_test_t::evt_send_next );
            so_subscribe_self().event< stop >(
                  &a_test_t::evt_stop );
         }

      virtual void so_evt_start() override
         {
            so_5::send_to_agent< send_next >( *this );
            so_5::send_delayed_to_agent< stop >( *this,
                  std::chrono::milliseconds( 350 ) );
         }

   private :
      void evt_send_next()
         {
            so_5::send_to_agent< send_next >( *this );
            so_5::send_to_agent< send_next >( *this );
         }

      void evt_stop()
         {
            so_deregister_agent_coop_normally();
         }
   };

void
fill_coop(
   so_5::rt::agent_coop_t & coop )
   {
      coop.make_agent< a_test_t >();
   }
struct send_next : public so_5::rt::signal_t {};
struct stop : public so_5::rt::signal_t {};

void
fill_coop(
   so_5::rt::agent_coop_t & coop )
   {
      using namespace so_5::rt;

      auto a = coop.define_agent(
            coop.make_agent_context() +
            agent_t::limit_then_drop< send_next >( 100 ) +
            agent_t::limit_then_drop< stop >( 1 ) +
            so_5::prio::p0 );
      auto m = a.direct_mbox();

      a.on_start( [m, &coop] {
            so_5::send< send_next >( m );
            so_5::send_delayed< stop >(
                  coop.environment(),
                  m,
                  std::chrono::milliseconds( 350 ) );
         } )
      .event< send_next >( m, [m] {
            so_5::send< send_next >( m );
            so_5::send< send_next >( m );
         } )
      .event< stop >( m, [&coop] {
            coop.environment().deregister_coop(
                  coop.query_coop_name(),
                  dereg_reason::normal );
         } );
   }

Полагаю, функциональность ad-hoc агентов, а так же удобство работы с ними, в ближайших версиях SO-5 будет расширена еще больше. Если не в 5.5.8, то в 5.5.9 или 5.6.0. Есть некоторые мыслишки, которые могут привести к тому, что ad-hoc агенты окажутся основным способом работы с SObjectizer. Хотя для больших агентов, вроде тех, что мне доводилось разрабатывать для коммерческих проектов, старый добрый подход на основе создания наследников класса agent_t, еще долго будет вне конкуренции.

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