sample/chstate/main.cpp

00001 /*
00002   Пример агента, изменяющего свое состояние.
00003 
00004   Агент обладает состояниями: st_1, st_2, st_3, st_4, st_shutdown.
00005   В каждом из состояний с разным приоритетом обрабатывается
00006   сообщение msg_1.
00007 
00008   Показывается, как назначение нескольких обработчиков
00009   одного сообщения в одно состояние с одинаковым приоритетом
00010   приводит к игнорированию обоих событий.
00011 
00012   Показывается возможность автоматической рассылки сообщений
00013   об изменении состояния агента и обработка этого сообщения.
00014 
00015   Показывается назначение обработчиков входа и выхода
00016   в состояние.
00017 
00018   Показывается назначение "слушателей" состояния агента.
00019 */
00020 
00021 #include <iostream>
00022 
00023 // Загружаем основные заголовочные файлы SObjectizer.
00024 #include <so_4/rt/h/rt.hpp>
00025 #include <so_4/api/h/api.hpp>
00026 
00027 // Загружаем описание нити таймера и диспетчера.
00028 #include <so_4/timer_thread/simple/h/pub.hpp>
00029 #include <so_4/disp/one_thread/h/pub.hpp>
00030 
00031 // Слушатель состояния агента.
00032 class sample_listener_t
00033   : public so_4::rt::agent_state_listener_t
00034 {
00035   private :
00036     // Имя данного слушателя.
00037     std::string m_name;
00038   public :
00039     sample_listener_t(
00040       const std::string & name )
00041     : m_name( name )
00042     {}
00043     virtual ~sample_listener_t()
00044     {
00045       // Отладочная печать покажет, когда слушатель будет уничтожен.
00046       std::cout << "listener destroyed: " << m_name << std::endl;
00047     }
00048 
00049     virtual void
00050     changed(
00051       so_4::rt::agent_t & agent,
00052       const std::string & state_name )
00053     {
00054       std::cout << m_name << ": state of '"
00055         << agent.so_query_name() << "' is '"
00056         << state_name << "'" << std::endl;
00057     }
00058 };
00059 
00060 // C++ описание класса агента.
00061 class a_main_t
00062   : public so_4::rt::agent_t
00063 {
00064   typedef so_4::rt::agent_t base_type_t;
00065 
00066   public :
00067     a_main_t();
00068     virtual ~a_main_t();
00069 
00070     virtual const char *
00071     so_query_type() const;
00072 
00073     virtual void
00074     so_on_subscription();
00075 
00076     struct  msg_1 {};
00077 
00078     void
00079     evt_start();
00080 
00081     void
00082     evt_msg_1_st_1();
00083 
00084     void
00085     evt_msg_1_st_2_pri_1();
00086 
00087     void
00088     evt_msg_1_st_2_pri_0();
00089 
00090     void
00091     evt_msg_1_st_3_pri_1_one();
00092 
00093     void
00094     evt_msg_1_st_3_pri_1_two();
00095 
00096     void
00097     evt_msg_1_st_3_pri_0();
00098 
00099     void
00100     evt_msg_1_st_4();
00101 
00102     // Возникает при смене собственного состояния.
00103     void
00104     evt_self_state_notify(
00105       const so_4::rt::so_msg_state * cmd );
00106 
00107     void
00108     on_enter_state(
00109       const std::string & state_name );
00110 
00111     void
00112     on_exit_state(
00113       const std::string & state_name );
00114 
00115     void
00116     on_enter_st_shutdown(
00117       const std::string & state_name );
00118 };
00119 
00120 SOL4_CLASS_START( a_main_t )
00121 
00122   SOL4_MSG_START( msg_1, a_main_t::msg_1 )
00123   SOL4_MSG_FINISH()
00124 
00125   SOL4_EVENT( evt_start )
00126   SOL4_EVENT( evt_msg_1_st_1 )
00127   SOL4_EVENT( evt_msg_1_st_2_pri_1 )
00128   SOL4_EVENT( evt_msg_1_st_2_pri_0 )
00129   SOL4_EVENT( evt_msg_1_st_3_pri_1_one )
00130   SOL4_EVENT( evt_msg_1_st_3_pri_1_two )
00131   SOL4_EVENT( evt_msg_1_st_3_pri_0 )
00132   SOL4_EVENT( evt_msg_1_st_4 )
00133 
00134   SOL4_EVENT_STC(
00135     evt_self_state_notify,
00136     so_4::rt::so_msg_state )
00137 
00138   SOL4_STATE_START( st_1 )
00139     SOL4_STATE_EVENT( evt_start )
00140     SOL4_STATE_EVENT( evt_msg_1_st_1 )
00141 
00142     SOL4_STATE_EVENT( evt_self_state_notify )
00143 
00144     SOL4_STATE_ON_ENTER( on_enter_state )
00145     SOL4_STATE_ON_EXIT( on_exit_state )
00146   SOL4_STATE_FINISH()
00147 
00148   SOL4_STATE_START( st_2 )
00149     SOL4_STATE_EVENT( evt_msg_1_st_2_pri_1 )
00150     SOL4_STATE_EVENT( evt_msg_1_st_2_pri_0 )
00151 
00152     SOL4_STATE_EVENT( evt_self_state_notify )
00153 
00154     SOL4_STATE_ON_ENTER( on_enter_state )
00155     SOL4_STATE_ON_EXIT( on_exit_state )
00156   SOL4_STATE_FINISH()
00157 
00158   SOL4_STATE_START( st_3 )
00159     // Назначение этих событий в одно состояние
00160     // приводит к их игнорированию из-за
00161     // непредсказуемости системы.
00162     SOL4_STATE_EVENT( evt_msg_1_st_3_pri_1_one )
00163     SOL4_STATE_EVENT( evt_msg_1_st_3_pri_1_two )
00164 
00165     SOL4_STATE_EVENT( evt_msg_1_st_3_pri_0 )
00166 
00167     SOL4_STATE_EVENT( evt_self_state_notify )
00168 
00169     SOL4_STATE_ON_ENTER( on_enter_state )
00170     SOL4_STATE_ON_EXIT( on_exit_state )
00171   SOL4_STATE_FINISH()
00172 
00173   SOL4_STATE_START( st_4 )
00174     SOL4_STATE_EVENT( evt_msg_1_st_4 )
00175 
00176     SOL4_STATE_EVENT( evt_self_state_notify )
00177 
00178     SOL4_STATE_ON_ENTER( on_enter_state )
00179     SOL4_STATE_ON_EXIT( on_exit_state )
00180   SOL4_STATE_FINISH()
00181 
00182   SOL4_STATE_START( st_shutdown )
00183 
00184     SOL4_STATE_EVENT( evt_self_state_notify )
00185 
00186     SOL4_STATE_ON_ENTER( on_enter_state )
00187     SOL4_STATE_ON_ENTER( on_enter_st_shutdown )
00188   SOL4_STATE_FINISH()
00189 
00190   // Указание SObjectizer-у рассылать сообщения об
00191   // изменении состояния агента.
00192   SOL4_CHANGE_STATE_NOTIFY()
00193 
00194 SOL4_CLASS_FINISH()
00195 
00196 //
00197 // a_main_t
00198 //
00199 a_main_t::a_main_t()
00200 :
00201   base_type_t( "a_main" )
00202 {}
00203 
00204 a_main_t::~a_main_t()
00205 {}
00206 
00207 void
00208 a_main_t::so_on_subscription()
00209 {
00210   so_subscribe( "evt_start",
00211     so_4::rt::sobjectizer_agent_name(), "msg_start" );
00212 
00213   so_subscribe( "evt_msg_1_st_1", "msg_1" );
00214 
00215   so_subscribe( "evt_msg_1_st_2_pri_1", "msg_1", 1 );
00216 
00217   so_subscribe( "evt_msg_1_st_2_pri_0", "msg_1" );
00218 
00219   so_subscribe( "evt_msg_1_st_3_pri_1_one", "msg_1", 1 );
00220 
00221   so_subscribe( "evt_msg_1_st_3_pri_1_two", "msg_1", 1 );
00222 
00223   so_subscribe( "evt_msg_1_st_3_pri_0", "msg_1" );
00224 
00225   so_subscribe( "evt_msg_1_st_4", "msg_1" );
00226 
00227   so_subscribe( "evt_self_state_notify", "so_msg_state", 10 );
00228 }
00229 
00230 void
00231 a_main_t::evt_start()
00232 {
00233   std::cout << so_query_name() << ".evt_start" << std::endl;
00234 
00235   // Сообщение msg_1 должно возникать переодически.
00236   so_4::api::send_msg( so_query_name(), "msg_1", 0,
00237     "", 500, 1000 );
00238 }
00239 
00240 void
00241 a_main_t::evt_msg_1_st_1()
00242 {
00243   std::cout << so_query_name() << ".evt_msg_1_st_1" << std::endl;
00244 
00245   so_change_state( "st_2" );
00246 }
00247 
00248 void
00249 a_main_t::evt_msg_1_st_2_pri_1()
00250 {
00251   std::cout << so_query_name() << ".evt_msg_1_st_2_pri_1" << std::endl;
00252 }
00253 
00254 void
00255 a_main_t::evt_msg_1_st_2_pri_0()
00256 {
00257   std::cout << so_query_name() << ".evt_msg_1_st_2_pri_0" << std::endl;
00258 
00259   so_change_state( "st_3" );
00260 }
00261 
00262 void
00263 a_main_t::evt_msg_1_st_3_pri_1_one()
00264 {
00265   std::cout << so_query_name() << ".evt_msg_1_st_3_pri_1_one" << std::endl;
00266 }
00267 
00268 void
00269 a_main_t::evt_msg_1_st_3_pri_1_two()
00270 {
00271   std::cout << so_query_name() << ".evt_msg_1_st_3_pri_1_two" << std::endl;
00272 }
00273 
00274 void
00275 a_main_t::evt_msg_1_st_3_pri_0()
00276 {
00277   std::cout << so_query_name() << ".evt_msg_1_st_3_pri_0" << std::endl;
00278 
00279   so_change_state( "st_4" );
00280 }
00281 
00282 void
00283 a_main_t::evt_msg_1_st_4()
00284 {
00285   std::cout << so_query_name() << ".evt_msg_1_st_4" << std::endl;
00286 
00287   so_change_state( "st_shutdown" );
00288 }
00289 
00290 void
00291 a_main_t::evt_self_state_notify(
00292   const so_4::rt::so_msg_state * cmd )
00293 {
00294   std::cout << "so_msg_state: agent: " << cmd->m_agent
00295     << ", state: " << cmd->m_state << std::endl;
00296 }
00297 
00298 void
00299 a_main_t::on_enter_state(
00300   const std::string & state_name )
00301 {
00302   std::cout << "\tenter state: " << state_name <<std::endl;
00303 }
00304 
00305 void
00306 a_main_t::on_exit_state(
00307   const std::string & state_name )
00308 {
00309   std::cout << "\texit state: " << state_name <<std::endl;
00310 }
00311 
00312 void
00313 a_main_t::on_enter_st_shutdown(
00314   const std::string & state_name )
00315 {
00316   std::cout << "System is shutting down..." << std::endl;
00317   so_4::api::send_msg( so_4::rt::sobjectizer_agent_name(),
00318     "msg_normal_shutdown" );
00319 }
00320 
00321 int
00322 main()
00323 {
00324   // Наш агент.
00325   a_main_t a_main;
00326   // Статический слушатель состояний.
00327   sample_listener_t l( "static_listener" );
00328   a_main.so_add_nondestroyable_listener( l );
00329   // И динамический слушатель.
00330   // Т.к. динамический слушатель назначается агенту до
00331   // регистрации агента, то он не сможет определить начальное
00332   // состояние агента в своем методе stored.
00333   a_main.so_add_destroyable_listener(
00334     new sample_listener_t( "dynamic_listener" ) );
00335 
00336   // И кооперация для агента.
00337   so_4::rt::agent_coop_t  a_main_coop( a_main );
00338 
00339   // Запускаем SObjectizer Run-Time.
00340   so_4::ret_code_t rc = so_4::api::start(
00341     so_4::disp::one_thread::create_disp(
00342       so_4::timer_thread::simple::create_timer_thread(),
00343       so_4::auto_destroy_timer ),
00344     so_4::auto_destroy_disp,
00345     &a_main_coop );
00346   if( rc )
00347   {
00348     // Запустить SObjectizer Run-Time не удалось.
00349     std::cerr << "start: " << rc << std::endl;
00350   }
00351   else
00352     std::cout << "successful finish" << std::endl;
00353 
00354   return int( rc );
00355 }

Документация по SObjectizer. Последние изменения: Thu Jan 12 10:52:49 2006. Создано системой  doxygen 1.4.6-NO
Hosted by uCoz