sample/dyn_reg/main.cpp

/*
  Пример использования:
  - динамической кооперации;
  - обработки сообщений SObjectizer-а о регистрации и
  дерегистрации коопераций;
  - переопределения метода so_4::rt::agent_t::so_on_deregistration().
*/

#include <iostream>

#include <ace/OS_main.h>

// Загружаем основные заголовочные файлы SObjectizer.
#include <so_4/rt/h/rt.hpp>
#include <so_4/api/h/api.hpp>

// Загружаем описание нити таймера и диспетчера.
#include <so_4/timer_thread/simple/h/pub.hpp>
#include <so_4/disp/one_thread/h/pub.hpp>

// Имя дочернего агента и динамической кооперации.
const std::string child_name( "a_child" );

// Класс агента, который будет входить в динамическую кооперацию.
class a_child_t
  :   public so_4::rt::agent_t
{
  typedef so_4::rt::agent_t base_type_t;

  public :
    a_child_t();
    virtual ~a_child_t();

    virtual const char *
    so_query_type() const;

    virtual void
    so_on_subscription();

    virtual void
    so_on_deregistration();

    // Сообщение, которым обладает данный агент.
    struct  msg_say_it_again {};

    void
    evt_start();

    void
    evt_say_it_again( const so_4::rt::event_data_t & data );
};

SOL4_CLASS_START( a_child_t )

  SOL4_MSG_START( msg_say_it_again, a_child_t::msg_say_it_again )
  SOL4_MSG_FINISH()

  SOL4_EVENT( evt_start )

  SOL4_EVENT( evt_say_it_again )

  SOL4_STATE_START( st_initial )
    SOL4_STATE_EVENT( evt_start )
    SOL4_STATE_EVENT( evt_say_it_again )
  SOL4_STATE_FINISH()

SOL4_CLASS_FINISH()

a_child_t::a_child_t()
:
  base_type_t( child_name )
{
  // Информируем о том, что мы созданы.
  std::cout << so_query_name() << " created" << std::endl;
}

a_child_t::~a_child_t()
{
  // Информируем о том, что мы уничтожены.
  std::cout << so_query_name() << " destroyed" << std::endl;
}

void
a_child_t::so_on_subscription()
{
  so_subscribe( "evt_start",
    so_4::rt::sobjectizer_agent_name(), "msg_start" );

  so_subscribe( "evt_say_it_again", "msg_say_it_again" );
}

void
a_child_t::so_on_deregistration()
{
  // Сообщаем о том, что нас дерегистрируют.
  std::cout << so_query_name() << " deregistered" << std::endl;
}

void
a_child_t::evt_start()
{
  // Сообщаем о том, что мы стартовали.
  std::cout << so_query_name()
    << ": Hello, World!" << std::endl;
}

void
a_child_t::evt_say_it_again( const so_4::rt::event_data_t & data )
{
  // Сообщаем, что мы получили сообщение.
  std::cout << so_query_name()
    << ": and again - Hello, World!" << std::endl;

  // Отошлем его самим себе с задержкой. Если нас за это
  // время дерегистрируют, то мы его не получим.
  so_4::api::send_msg( data.agent(), data.msg(), 0,
    so_query_name(), 15000 );
}

//
// Класс агента, который создает и уничтожает динамическую кооперацию.
//
class a_parent_t
  : public so_4::rt::agent_t
{
  typedef so_4::rt::agent_t base_type_t;
  public :
    a_parent_t();
    virtual ~a_parent_t();

    virtual const char *
    so_query_type() const;

    virtual void
    so_on_subscription();

    // При поступлении этого сообщения кооперация будет создана.
    struct  msg_reg_time {};

    // При поступлении этого сообщения кооперация
    // будет дерегистрирована.
    struct  msg_dereg_time {};

    void
    evt_start();

    void
    evt_reg_time();

    void
    evt_dereg_time();

    void
    evt_coop_registered(
      const so_4::rt::msg_coop_registered & cmd );

    void
    evt_coop_deregistered(
      const so_4::rt::msg_coop_deregistered & cmd );
};

SOL4_CLASS_START( a_parent_t )

  SOL4_MSG_START( msg_reg_time, a_parent_t::msg_reg_time )
  SOL4_MSG_FINISH()

  SOL4_MSG_START( msg_dereg_time, a_parent_t::msg_dereg_time )
  SOL4_MSG_FINISH()

  SOL4_EVENT( evt_start )

  SOL4_EVENT( evt_reg_time )

  SOL4_EVENT( evt_dereg_time )

  SOL4_EVENT_STC(
    evt_coop_registered,
    so_4::rt::msg_coop_registered )

  SOL4_EVENT_STC(
    evt_coop_deregistered,
    so_4::rt::msg_coop_deregistered )

  SOL4_STATE_START( st_initial )
    SOL4_STATE_EVENT( evt_start )
    SOL4_STATE_EVENT( evt_reg_time )
    SOL4_STATE_EVENT( evt_dereg_time )
    SOL4_STATE_EVENT( evt_coop_registered )
    SOL4_STATE_EVENT( evt_coop_deregistered )
  SOL4_STATE_FINISH()

SOL4_CLASS_FINISH()

a_parent_t::a_parent_t()
:
  base_type_t( "a_parent" )
{}

a_parent_t::~a_parent_t()
{}

void
a_parent_t::so_on_subscription()
{
  so_subscribe( "evt_start",
    so_4::rt::sobjectizer_agent_name(), "msg_start" );

  so_subscribe( "evt_reg_time", "msg_reg_time" );

  so_subscribe( "evt_dereg_time", "msg_dereg_time" );

  // Если приоритит у этого события больше, чем приоритет
  // evt_start у дочернего агента, то мы должны отработать
  // быстрее, чем дочерний агент (для приоритеных диспетчеров).
  so_subscribe( "evt_coop_registered",
    so_4::rt::sobjectizer_agent_name(), "msg_coop_registered", 1 );

  so_subscribe( "evt_coop_deregistered",
    so_4::rt::sobjectizer_agent_name(), "msg_coop_deregistered" );
}

void
a_parent_t::evt_start()
{
  // Указываем, когда дочерняя кооперация будет зарегистрирована.
  unsigned int sec = 1;
  std::cout << so_query_name()
    << ": child coop will be registered after "
    << sec << " sec" << std::endl;

  so_4::api::send_msg( so_query_name(), "msg_reg_time", 0,
    so_query_name(), sec * 1000 );
}

void
a_parent_t::evt_reg_time()
{
  std::cout << so_query_name()
    << ": It's time to register child coop"
    << std::endl;

  // Регистрируем дочернюю кооперацию.
  so_4::rt::dyn_agent_coop_helper_t helper(
    new so_4::rt::dyn_agent_coop_t( new a_child_t() ) );
  if( helper.result() )
  {
    // Ошибка регистрации!
    std::cerr << "register_coop: " << helper.result() << std::endl;
    so_4::api::send_msg( so_4::rt::sobjectizer_agent_name(),
      "msg_alarm_shutdown", 0 );
  }
}

void
a_parent_t::evt_dereg_time()
{
  std::cout << so_query_name()
    << ": It's time to deregister child coop" << std::endl;

  so_4::ret_code_t rc = so_4::api::deregister_coop( child_name );
  if( rc )
  {
    std::cerr << "deregister_coop: " << rc << std::endl;
    so_4::api::send_msg( so_4::rt::sobjectizer_agent_name(),
      "msg_alarm_shutdown", 0 );
  }
}

void
a_parent_t::evt_coop_registered(
  const so_4::rt::msg_coop_registered & cmd )
{
  std::cout << so_query_name()
    << ": Cooperation registered: "
    << cmd.m_coop_name << std::endl;

  if( child_name == cmd.m_coop_name )
  {
    // Это наша дочерняя кооперация, которую нужно
    // дерегистрировать.

    unsigned int sec = 2;
    std::cout << so_query_name()
      << ": child coop will be deregistered after "
      << sec << " sec" << std::endl;

    so_4::api::send_msg(
      so_query_name(), "msg_dereg_time", 0,
      so_query_name(), sec * 1000 );

    // Заставляем дочернего агента еще раз сказать Hello...
    so_4::api::send_msg( child_name, "msg_say_it_again" );
  }
}

void
a_parent_t::evt_coop_deregistered(
  const so_4::rt::msg_coop_deregistered & cmd )
{
  std::cout << so_query_name()
    << ": Cooperation deregistered: "
    << cmd.m_coop_name << std::endl;

  if( child_name == cmd.m_coop_name )
  {
    // Дочерняя кооперация дерегистрирована. Можно завершать работу.
    std::cout << so_query_name()
      << ": Work finished" << std::endl;

    so_4::api::send_msg(
      so_4::rt::sobjectizer_agent_name(),
      "msg_normal_shutdown", 0 );
  }
}

int
main( int, char ** )
{
  // Родительский агент.
  a_parent_t a_parent;
  // И кооперация для него.
  so_4::rt::agent_coop_t  a_parent_coop( a_parent );

  // Запускаем SObjectizer Run-Time.
  so_4::ret_code_t rc = so_4::api::start(
    so_4::disp::one_thread::create_disp(
      so_4::timer_thread::simple::create_timer_thread(),
      so_4::auto_destroy_timer ),
    so_4::auto_destroy_disp,
    &a_parent_coop );
  if( rc ) {
    // Запустить SObjectizer Run-Time не удалось.
    std::cerr << "start: " << rc << std::endl;
  }

  return int( rc );
}

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