sample/chstate/main.cpp

/*
  Пример агента, изменяющего свое состояние.

  Агент обладает состояниями: st_1, st_2, st_3, st_4, st_shutdown.
  В каждом из состояний с разным приоритетом обрабатывается
  сообщение msg_1.

  Показывается, как назначение нескольких обработчиков
  одного сообщения в одно состояние с одинаковым приоритетом
  приводит к игнорированию обоих событий.

  Показывается возможность автоматической рассылки сообщений
  об изменении состояния агента и обработка этого сообщения.

  Показывается назначение обработчиков входа и выхода
  в состояние.

  Показывается назначение "слушателей" состояния агента.
*/

#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>

// Слушатель состояния агента.
class sample_listener_t
  : public so_4::rt::agent_state_listener_t
{
  private :
    // Имя данного слушателя.
    std::string m_name;
  public :
    sample_listener_t(
      const std::string & name )
    : m_name( name )
    {}
    virtual ~sample_listener_t()
    {
      // Отладочная печать покажет, когда слушатель будет уничтожен.
      std::cout << "listener destroyed: " << m_name << std::endl;
    }

    virtual void
    changed(
      so_4::rt::agent_t & agent,
      const std::string & state_name )
    {
      std::cout << m_name << ": state of '"
        << agent.so_query_name() << "' is '"
        << state_name << "'" << std::endl;
    }
};

// C++ описание класса агента.
class a_main_t
  : public so_4::rt::agent_t
{
  typedef so_4::rt::agent_t base_type_t;

  public :
    a_main_t();
    virtual ~a_main_t();

    virtual const char *
    so_query_type() const;

    virtual void
    so_on_subscription();

    struct  msg_1 {};

    void
    evt_start();

    void
    evt_msg_1_st_1();

    void
    evt_msg_1_st_2_pri_1();

    void
    evt_msg_1_st_2_pri_0();

    void
    evt_msg_1_st_3_pri_1_one();

    void
    evt_msg_1_st_3_pri_1_two();

    void
    evt_msg_1_st_3_pri_0();

    void
    evt_msg_1_st_4();

    // Возникает при смене собственного состояния.
    void
    evt_self_state_notify(
      const so_4::rt::so_msg_state * cmd );

    void
    on_enter_state(
      const std::string & state_name );

    void
    on_exit_state(
      const std::string & state_name );

    void
    on_enter_st_shutdown(
      const std::string & state_name );
};

SOL4_CLASS_START( a_main_t )

  SOL4_MSG_START( msg_1, a_main_t::msg_1 )
  SOL4_MSG_FINISH()

  SOL4_EVENT( evt_start )
  SOL4_EVENT( evt_msg_1_st_1 )
  SOL4_EVENT( evt_msg_1_st_2_pri_1 )
  SOL4_EVENT( evt_msg_1_st_2_pri_0 )
  SOL4_EVENT( evt_msg_1_st_3_pri_1_one )
  SOL4_EVENT( evt_msg_1_st_3_pri_1_two )
  SOL4_EVENT( evt_msg_1_st_3_pri_0 )
  SOL4_EVENT( evt_msg_1_st_4 )

  SOL4_EVENT_STC(
    evt_self_state_notify,
    so_4::rt::so_msg_state )

  SOL4_STATE_START( st_1 )
    SOL4_STATE_EVENT( evt_start )
    SOL4_STATE_EVENT( evt_msg_1_st_1 )

    SOL4_STATE_EVENT( evt_self_state_notify )

    SOL4_STATE_ON_ENTER( on_enter_state )
    SOL4_STATE_ON_EXIT( on_exit_state )
  SOL4_STATE_FINISH()

  SOL4_STATE_START( st_2 )
    SOL4_STATE_EVENT( evt_msg_1_st_2_pri_1 )
    SOL4_STATE_EVENT( evt_msg_1_st_2_pri_0 )

    SOL4_STATE_EVENT( evt_self_state_notify )

    SOL4_STATE_ON_ENTER( on_enter_state )
    SOL4_STATE_ON_EXIT( on_exit_state )
  SOL4_STATE_FINISH()

  SOL4_STATE_START( st_3 )
    // Назначение этих событий в одно состояние
    // приводит к их игнорированию из-за
    // непредсказуемости системы.
    SOL4_STATE_EVENT( evt_msg_1_st_3_pri_1_one )
    SOL4_STATE_EVENT( evt_msg_1_st_3_pri_1_two )

    SOL4_STATE_EVENT( evt_msg_1_st_3_pri_0 )

    SOL4_STATE_EVENT( evt_self_state_notify )

    SOL4_STATE_ON_ENTER( on_enter_state )
    SOL4_STATE_ON_EXIT( on_exit_state )
  SOL4_STATE_FINISH()

  SOL4_STATE_START( st_4 )
    SOL4_STATE_EVENT( evt_msg_1_st_4 )

    SOL4_STATE_EVENT( evt_self_state_notify )

    SOL4_STATE_ON_ENTER( on_enter_state )
    SOL4_STATE_ON_EXIT( on_exit_state )
  SOL4_STATE_FINISH()

  SOL4_STATE_START( st_shutdown )

    SOL4_STATE_EVENT( evt_self_state_notify )

    SOL4_STATE_ON_ENTER( on_enter_state )
    SOL4_STATE_ON_ENTER( on_enter_st_shutdown )
  SOL4_STATE_FINISH()

  // Указание SObjectizer-у рассылать сообщения об
  // изменении состояния агента.
  SOL4_CHANGE_STATE_NOTIFY()

SOL4_CLASS_FINISH()

//
// a_main_t
//
a_main_t::a_main_t()
:
  base_type_t( "a_main" )
{}

a_main_t::~a_main_t()
{}

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

  so_subscribe( "evt_msg_1_st_1", "msg_1" );

  so_subscribe( "evt_msg_1_st_2_pri_1", "msg_1", 1 );

  so_subscribe( "evt_msg_1_st_2_pri_0", "msg_1" );

  so_subscribe( "evt_msg_1_st_3_pri_1_one", "msg_1", 1 );

  so_subscribe( "evt_msg_1_st_3_pri_1_two", "msg_1", 1 );

  so_subscribe( "evt_msg_1_st_3_pri_0", "msg_1" );

  so_subscribe( "evt_msg_1_st_4", "msg_1" );

  so_subscribe( "evt_self_state_notify", "so_msg_state", 10 );
}

void
a_main_t::evt_start()
{
  std::cout << so_query_name() << ".evt_start" << std::endl;

  // Сообщение msg_1 должно возникать переодически.
  so_4::api::send_msg( so_query_name(), "msg_1", 0,
    "", 500, 1000 );
}

void
a_main_t::evt_msg_1_st_1()
{
  std::cout << so_query_name() << ".evt_msg_1_st_1" << std::endl;

  so_change_state( "st_2" );
}

void
a_main_t::evt_msg_1_st_2_pri_1()
{
  std::cout << so_query_name() << ".evt_msg_1_st_2_pri_1" << std::endl;
}

void
a_main_t::evt_msg_1_st_2_pri_0()
{
  std::cout << so_query_name() << ".evt_msg_1_st_2_pri_0" << std::endl;

  so_change_state( "st_3" );
}

void
a_main_t::evt_msg_1_st_3_pri_1_one()
{
  std::cout << so_query_name() << ".evt_msg_1_st_3_pri_1_one" << std::endl;
}

void
a_main_t::evt_msg_1_st_3_pri_1_two()
{
  std::cout << so_query_name() << ".evt_msg_1_st_3_pri_1_two" << std::endl;
}

void
a_main_t::evt_msg_1_st_3_pri_0()
{
  std::cout << so_query_name() << ".evt_msg_1_st_3_pri_0" << std::endl;

  so_change_state( "st_4" );
}

void
a_main_t::evt_msg_1_st_4()
{
  std::cout << so_query_name() << ".evt_msg_1_st_4" << std::endl;

  so_change_state( "st_shutdown" );
}

void
a_main_t::evt_self_state_notify(
  const so_4::rt::so_msg_state * cmd )
{
  std::cout << "so_msg_state: agent: " << cmd->m_agent
    << ", state: " << cmd->m_state << std::endl;
}

void
a_main_t::on_enter_state(
  const std::string & state_name )
{
  std::cout << "\tenter state: " << state_name <<std::endl;
}

void
a_main_t::on_exit_state(
  const std::string & state_name )
{
  std::cout << "\texit state: " << state_name <<std::endl;
}

void
a_main_t::on_enter_st_shutdown(
  const std::string & state_name )
{
  std::cout << "System is shutting down..." << std::endl;
  so_4::api::send_msg( so_4::rt::sobjectizer_agent_name(),
    "msg_normal_shutdown" );
}

int
main( int, char ** )
{
  // Наш агент.
  a_main_t a_main;
  // Статический слушатель состояний.
  sample_listener_t l( "static_listener" );
  a_main.so_add_nondestroyable_listener( l );
  // И динамический слушатель.
  // Т.к. динамический слушатель назначается агенту до
  // регистрации агента, то он не сможет определить начальное
  // состояние агента в своем методе stored.
  a_main.so_add_destroyable_listener(
    new sample_listener_t( "dynamic_listener" ) );

  // И кооперация для агента.
  so_4::rt::agent_coop_t  a_main_coop( a_main );

  // Запускаем 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_main_coop );
  if( rc )
  {
    // Запустить SObjectizer Run-Time не удалось.
    std::cerr << "start: " << rc << std::endl;
  }
  else
    std::cout << "successful finish" << std::endl;

  return int( rc );
}

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