so_4: Версия 4.2.6. Автоматически уничтожаемые свойства агентов

Механизм свойств агентов позволяет связать с агентом произвольное количество вспомогательных объектов, поддерживающих интерфейс so_4::rt::agent_traits_t. При регистрации агента SObjectizer вызывает у них метод so_4::rt::agent_traits_t::init(), что позволяет проводить дополнительную инициализацию агента непосредственно перед началом его работы в SObjectizer Run-Time. В некоторых построенных на SObjectizer проектах, например, MBAPI, свойства агентов играют важную роль.

Но в предшествующих v.4.2.6 версиях SObjectizer агент не мог контролировать время жизни объекта-свойства. Это приводило к тому, что в случае, когда свойство должно было существовать столько же, сколько и агент, свойство должно было быть атрибутом агента. Вот пример из использования MBAPI:

class a_receive_processor_t
  : public so_4::rt::agent_t
{
  typedef so_4::rt::agent_t base_type_t;
  public :
    ...
    

    typedef mbapi_3::router::so_msg_templ_t<
        mbsms_1::receive_t,
        mbapi_3::client_dest_t,
        mbapi_3::server_dest_t >
      msg_receive;


    typedef mbapi_3::router::so_msg_templ_t<
        mbsms_1::receive_ack_t >
      msg_receive_ack;


    typedef mbapi_3::router::so_msg_templ_t<
        mbsms_1::receive_finish_t,
        mbapi_3::client_dest_t,
        mbapi_3::server_dest_t >
      msg_receive_finish;


    typedef mbapi_3::router::so_msg_templ_t<
        mbsms_1::receive_finish_ack_t >
      msg_receive_finish_ack;

    ...
  private :
    ...

    mbapi_3::router::so_msg_templ_postman_t<
        msg_receive >
      m_receive_postman;

    mbapi_3::router::so_msg_templ_postman_t<
        msg_receive_ack >
      m_receive_ack_postman;

    mbapi_3::router::so_msg_templ_postman_t<
        msg_receive_finish >
      m_receive_finish_postman;

    mbapi_3::router::so_msg_templ_postman_t<
        msg_receive_finish_ack >
      m_receive_finish_ack_postman;
};

a_receive_processor_t::a_receive_processor_t(
  ... )
:
  base_type_t( self_name.c_str() )
  ...
, m_receive_postman(
    so_query_name(), "msg_receive",
    receive_analyzer,
    receive_postman_priority,
    mbapi_3::router::intercept_msg )

, m_receive_ack_postman(
    so_query_name(), "msg_receive_ack",
    mbapi_3::router::and_analyzer(
      mbapi_3::router::dest_equality_analyzer( we_as_server ),
      mbapi_3::router::reply_to_equality_analyzer( recipient ) ) )

, m_receive_finish_postman(
    so_query_name(), "msg_receive_finish",
    // Для сообщения receive_finish необходимо два условия:
    mbapi_3::router::and_analyzer(
      // Сообщение должно адресоваться нам и должно
      // придти от AGGREGATE.
      mbapi_3::router::and_analyzer(
        mbapi_3::router::dest_equality_analyzer( we_as_client ),
        mbapi_3::router::reply_to_equality_analyzer( aggregate_dest ) ),
      // Идентификатор SMS-а должен быть нам известен.
      new receive_finish_analyzer_t( *m_uid_map ) ),
    // Сообщение должно перехватываться.
    1, mbapi_3::router::intercept_msg )

, m_receive_finish_ack_postman(
    so_query_name(), "msg_receive_finish_ack",
    mbapi_3::router::and_analyzer(
      mbapi_3::router::dest_equality_analyzer( we_as_server ),
      mbapi_3::router::reply_to_equality_analyzer( recipient ) ) )

{
  so_add_traits( m_receive_postman );
  so_add_traits( m_receive_ack_postman );
  so_add_traits( m_receive_finish_postman );
  so_add_traits( m_receive_finish_ack_postman );
}

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

\code
class a_receive_processor_t
  : public so_4::rt::agent_t
{
  typedef so_4::rt::agent_t base_type_t;
  public :
    ...
    

    typedef mbapi_3::router::so_msg_templ_t<
        mbsms_1::receive_t,
        mbapi_3::client_dest_t,
        mbapi_3::server_dest_t >
      msg_receive;


    typedef mbapi_3::router::so_msg_templ_t<
        mbsms_1::receive_ack_t >
      msg_receive_ack;


    typedef mbapi_3::router::so_msg_templ_t<
        mbsms_1::receive_finish_t,
        mbapi_3::client_dest_t,
        mbapi_3::server_dest_t >
      msg_receive_finish;


    typedef mbapi_3::router::so_msg_templ_t<
        mbsms_1::receive_finish_ack_t >
      msg_receive_finish_ack;

    ...
};

a_receive_processor_t::a_receive_processor_t(
  ... )
:
  base_type_t( self_name.c_str() )
  ...
{
  so_add_destroyable_traits(
    new mbapi_3::router::so_msg_templ_postman_t<
        msg_receive >(
      so_query_name(), "msg_receive",
      receive_analyzer,
      receive_postman_priority,
      mbapi_3::router::intercept_msg ) );

  so_add_destroyable_traits(
    new mbapi_3::router::so_msg_templ_postman_t<
        msg_receive_ack >(
      so_query_name(), "msg_receive_ack",
      mbapi_3::router::and_analyzer(
        mbapi_3::router::dest_equality_analyzer( we_as_server ),
        mbapi_3::router::reply_to_equality_analyzer( recipient ) ) ) );

  so_add_destroyable_traits(
    new mbapi_3::router::so_msg_templ_postman_t<
        msg_receive_finish >(
      so_query_name(), "msg_receive_finish",
      // Для сообщения receive_finish необходимо два условия:
      mbapi_3::router::and_analyzer(
        // Сообщение должно адресоваться нам и должно
        // придти от AGGREGATE.
        mbapi_3::router::and_analyzer(
          mbapi_3::router::dest_equality_analyzer( we_as_client ),
          mbapi_3::router::reply_to_equality_analyzer( aggregate_dest ) ),
        // Идентификатор SMS-а должен быть нам известен.
        new receive_finish_analyzer_t( *m_uid_map ) ),
      // Сообщение должно перехватываться.
      1, mbapi_3::router::intercept_msg ) );

  so_add_destroyable_traits(
    new mbapi_3::router::so_msg_templ_postman_t<
        msg_receive_finish_ack >(
      so_query_name(), "msg_receive_finish_ack",
      mbapi_3::router::and_analyzer(
        mbapi_3::router::dest_equality_analyzer( we_as_server ),
        mbapi_3::router::reply_to_equality_analyzer( recipient ) ) ) );
}

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

Уничтожаемые агентом свойства назначаются агенту посредством метода so_4::rt::agent_t::so_add_destroyable_traits(). Добавляемое таким образом свойство должно быть динамически созданным объектом, который будет уничтожен в деструкторе агента.

Метод so_4::rt::agent_t::so_add_traits() получает ссылку на объект-свойство, чье время жизни агент не контролирует.

В отношении не контролируемых свойств агента (т.е. добавляемых агенту посредством метода so_4::rt::agent_t::so_add_traits()) v.4.2.6 сохраняет полную совместимость с предыдущими версиями.


Документация по SObjectizer v.4.4 'Тебуломста'. Последние изменения: Thu Sep 18 10:26:48 2008. Создано системой  doxygen1.5.6 Intervale SourceForge.net Logo