sample/inheritance/main.cpp

00001 /*
00002   Демонстрация наследования агентов.
00003 
00004   Определяется базовый класс транзакции. От него
00005   производятся классы конкретной транзакции и
00006   прерываемой по таймеру транзакции. От классов
00007   конкретной транзакции и прерываемой по таймеру
00008   транзакции производится класс конкретной,
00009   прерываемой по таймеру транзакции.
00010 */
00011 
00012 #include <iostream>
00013 #include <memory>
00014 
00015 #include <so_4/rt/h/rt.hpp>
00016 #include <so_4/api/h/api.hpp>
00017 
00018 #include <so_4/timer_thread/simple/h/pub.hpp>
00019 #include <so_4/disp/one_thread/h/pub.hpp>
00020 
00021 /*
00022   Базовый класс для транзакции.
00023 
00024   Играет роль интерфейса, т.к. только определяет основные
00025   сообщения и состояния. Но не выполняет никаких действий.
00026 
00027   Виртуально наследуется от so_4::rt::agent_t, т.к.
00028   впоследствии будет использоваться во множественном
00029   наследовании.
00030 */
00031 class a_trx_t :
00032   public virtual so_4::rt::agent_t
00033 {
00034   typedef so_4::rt::agent_t agent_type_t;
00035   public :
00036     a_trx_t();
00037     virtual ~a_trx_t();
00038 
00039     virtual const char *
00040     so_query_type() const;
00041 
00042     virtual void
00043     so_on_subscription();
00044 
00045     // Сообщение о начале транзакции.
00046     struct  msg_start {};
00047 
00048     // Сообщение о необходимости завершить
00049     // транзакцию с сохранением всех изменений.
00050     struct  msg_commit {};
00051 
00052     // Сообщение о необходимости откатить
00053     // транзакцию в начальное состояние.
00054     struct  msg_rollback {};
00055 
00056   protected :
00057     // Реальная подписка.
00058     /*
00059       Ничего не делает, но введен для того,
00060       чтобы при множественном наследовании
00061       избежать ошибки множественного
00062       вызова a_trx_t::so_on_subscription().
00063     */
00064     void
00065     do_subscription();
00066 };
00067 
00068 SOL4_CLASS_START( a_trx_t )
00069 
00070   SOL4_MSG_START( msg_start, a_trx_t::msg_start )
00071   SOL4_MSG_FINISH()
00072 
00073   SOL4_MSG_START( msg_commit, a_trx_t::msg_commit )
00074   SOL4_MSG_FINISH()
00075 
00076   SOL4_MSG_START( msg_rollback, a_trx_t::msg_rollback )
00077   SOL4_MSG_FINISH()
00078 
00079 SOL4_CLASS_FINISH()
00080 
00081 a_trx_t::a_trx_t()
00082   :
00083     agent_type_t( "a_trx" )
00084 {
00085 }
00086 
00087 a_trx_t::~a_trx_t()
00088 {
00089 }
00090 
00091 void
00092 a_trx_t::so_on_subscription()
00093 {
00094   do_subscription();
00095 }
00096 
00097 void
00098 a_trx_t::do_subscription()
00099 {
00100 }
00101 
00102 
00103 /*
00104   Класс конкретной транзакции, которая выполняет
00105   какую-то работу.
00106 
00107   Виртуально производится от a_trx_t, т.к. впоследствии
00108   будет использоваться во множественном наследовании.
00109 */
00110 class a_concrete_trx_t :
00111   public virtual a_trx_t
00112 {
00113   typedef so_4::rt::agent_t agent_type_t;
00114   public :
00115     a_concrete_trx_t(
00116       // Время (в миллисекундах) через которое
00117       // будет сымитировано сообщение msg_commit.
00118       unsigned int commit_timeout,
00119       // Время (в миллисекундах) через которое
00120       // будет сымитировано сообщение msg_rollback.
00121       unsigned int rollback_timeout );
00122     virtual ~a_concrete_trx_t();
00123 
00124     virtual const char *
00125     so_query_type() const;
00126 
00127     virtual void
00128     so_on_subscription();
00129 
00130     /*
00131       Реакция на появление агента в системе.
00132 
00133       Для имитации работы начинает транзакцию.
00134     */
00135     void
00136     evt_start();
00137 
00138     /*
00139       Начинает транзакцию.
00140     */
00141     void
00142     evt_trx_start();
00143 
00144     /*
00145       Подтверждает транзакцию.
00146     */
00147     void
00148     evt_trx_commit();
00149 
00150     /*
00151       Откатывает транзакцию.
00152     */
00153     void
00154     evt_trx_rollback();
00155 
00156   protected :
00157     // Реальная подписка.
00158     void
00159     do_subscription();
00160 
00161   private :
00162     // Время (в миллисекундах) через которое
00163     // будет сымитировано сообщение msg_commit.
00164     unsigned int m_commit_timeout;
00165     // Время (в миллисекундах) через которое
00166     // будет сымитировано сообщение msg_rollback.
00167     unsigned int m_rollback_timeout;
00168 };
00169 
00170 SOL4_CLASS_START( a_concrete_trx_t )
00171   // Указываем наследование.
00172   SOL4_SUPER_CLASS( a_trx_t )
00173 
00174   // Поскольку есть наследование, нужно
00175   // сразу определить начальное состояние.
00176   SOL4_INITIAL_STATE( st_not_started )
00177 
00178   SOL4_EVENT( evt_start )
00179   SOL4_EVENT( evt_trx_start )
00180   SOL4_EVENT( evt_trx_commit )
00181   SOL4_EVENT( evt_trx_rollback )
00182 
00183   SOL4_STATE_START( st_not_started )
00184     SOL4_STATE_EVENT( evt_start )
00185     SOL4_STATE_EVENT( evt_trx_start )
00186   SOL4_STATE_FINISH()
00187 
00188   SOL4_STATE_START( st_started )
00189     SOL4_STATE_EVENT( evt_trx_commit )
00190     SOL4_STATE_EVENT( evt_trx_rollback )
00191   SOL4_STATE_FINISH()
00192 
00193   // Конечное состояние, в которое осуществляется
00194   // переход по подтверждению транзакции.
00195   SOL4_STATE_START( st_commited )
00196   SOL4_STATE_FINISH()
00197 
00198 SOL4_CLASS_FINISH()
00199 
00200 a_concrete_trx_t::a_concrete_trx_t(
00201   unsigned int commit_timeout,
00202   unsigned int rollback_timeout )
00203 :
00204   agent_type_t( "a_concrete_trx" ),
00205   m_commit_timeout( commit_timeout ),
00206   m_rollback_timeout( rollback_timeout )
00207 {
00208   std::cout << "commit_timeout: " << commit_timeout
00209     << "\nrollback_timeout: " << rollback_timeout
00210     << std::endl;
00211 }
00212 
00213 a_concrete_trx_t::~a_concrete_trx_t()
00214 {
00215 }
00216 
00217 void
00218 a_concrete_trx_t::so_on_subscription()
00219 {
00220   a_trx_t::do_subscription();
00221   do_subscription();
00222 }
00223 
00224 void
00225 a_concrete_trx_t::evt_start()
00226 {
00227   // Имитируем начало транзакции.
00228   so_4::api::send_msg( so_query_name(), "msg_start" );
00229 
00230   // Имитируем успешное завершение транзакции.
00231   so_4::api::send_msg( so_query_name(), "msg_commit", 0,
00232     so_query_name(), m_commit_timeout );
00233   // Имитируем откат транзакции.
00234   so_4::api::send_msg( so_query_name(), "msg_rollback", 0,
00235     so_query_name(), m_rollback_timeout );
00236 }
00237 
00238 void
00239 a_concrete_trx_t::evt_trx_start()
00240 {
00241   // Начинаем транзакцию.
00242   so_change_state( "st_started" );
00243 
00244   std::cout << "trx started" << std::endl;
00245 }
00246 
00247 void
00248 a_concrete_trx_t::evt_trx_commit()
00249 {
00250   // Подтверждаем транзакцию.
00251   so_change_state( "st_commited" );
00252 
00253   std::cout << "trx commited" << std::endl;
00254 
00255   so_4::api::send_msg(
00256     so_4::rt::sobjectizer_agent_name(),
00257     "msg_normal_shutdown" );
00258 }
00259 
00260 void
00261 a_concrete_trx_t::evt_trx_rollback()
00262 {
00263   // Откатываем транзакцию.
00264   so_change_state( "st_not_started" );
00265 
00266   std::cout << "trx rollbacked" << std::endl;
00267 
00268   so_4::api::send_msg(
00269     so_4::rt::sobjectizer_agent_name(),
00270     "msg_normal_shutdown" );
00271 }
00272 
00273 void
00274 a_concrete_trx_t::do_subscription()
00275 {
00276   so_subscribe( "evt_start",
00277     so_4::rt::sobjectizer_agent_name(), "msg_start" );
00278 
00279   so_subscribe( "evt_trx_start", "msg_start" );
00280 
00281   so_subscribe( "evt_trx_commit", "msg_commit" );
00282 
00283   so_subscribe( "evt_trx_rollback", "msg_rollback" );
00284 }
00285 
00286 /*
00287   Класс прерываемой по таймеру транзакции. Не
00288   выполняет никаких действий и предназначен
00289   быть примесью (mixin-ом) для конкретных
00290   классов транзакций.
00291 
00292   Виртуально производится от a_trx_t, т.к. впоследствии
00293   будет использоваться во множественном наследовании.
00294 */
00295 class a_timed_trx_t :
00296   public virtual a_trx_t
00297 {
00298   typedef so_4::rt::agent_t agent_type_t;
00299   public :
00300     a_timed_trx_t(
00301       // Время (в миллисекундах) через которое
00302       // будет работа транзакции будет прервана.
00303       unsigned int lifetime );
00304     virtual ~a_timed_trx_t();
00305 
00306     virtual const char *
00307     so_query_type() const;
00308 
00309     virtual void
00310     so_on_subscription();
00311 
00312     // Сообщение об истечении времени работы
00313     // транзакции.
00314     struct  msg_lifetime_left {};
00315 
00316     /*
00317       Реакция на истечение времени работы
00318       транзакции. Отсылает самому себе
00319       сообщение msg_rollback.
00320     */
00321     void
00322     evt_lifetime_left(
00323       const msg_lifetime_left * );
00324 
00325     /*
00326       Обработчик входа в состояние, означающее
00327       начало транзакции. Производный класс
00328       должен либо указать его в качестве обработчика
00329       входа в состояние, либо вызвать из собственного
00330       обработчика.
00331     */
00332     void
00333     on_enter_appropriate_state(
00334       const std::string & );
00335 
00336   protected :
00337     // Реальная подписка.
00338     void
00339     do_subscription();
00340 
00341   private :
00342     // Время (в миллисекундах) через которое
00343     // будет работа транзакции будет прервана.
00344     unsigned int m_lifetime;
00345 };
00346 
00347 SOL4_CLASS_START( a_timed_trx_t )
00348   // Указываем наследование.
00349   SOL4_SUPER_CLASS( a_trx_t )
00350 
00351   // Начальное состояние не указывается,
00352   // т.к. мы не вводим здесь своих состояний.
00353 
00354   SOL4_MSG_START( msg_lifetime_left,
00355     a_timed_trx_t::msg_lifetime_left )
00356   SOL4_MSG_FINISH()
00357 
00358   SOL4_EVENT_STC( evt_lifetime_left,
00359     a_timed_trx_t::msg_lifetime_left )
00360 
00361 SOL4_CLASS_FINISH()
00362 
00363 a_timed_trx_t::a_timed_trx_t(
00364   unsigned int lifetime )
00365   :
00366     agent_type_t( "a_timed_trx" ),
00367     m_lifetime( lifetime )
00368 {
00369   std::cout << "lifetime: " << lifetime
00370     << std::endl;
00371 }
00372 
00373 a_timed_trx_t::~a_timed_trx_t()
00374 {
00375 }
00376 
00377 void
00378 a_timed_trx_t::so_on_subscription()
00379 {
00380   a_trx_t::do_subscription();
00381   do_subscription();
00382 }
00383 
00384 void
00385 a_timed_trx_t::evt_lifetime_left(
00386   const msg_lifetime_left * )
00387 {
00388   // Транзакцию пора прерывать.
00389   so_4::api::send_msg( so_query_name(), "msg_rollback" );
00390 
00391   std::cout << "no time left" << std::endl;
00392 }
00393 
00394 void
00395 a_timed_trx_t::on_enter_appropriate_state(
00396   const std::string & )
00397 {
00398   // Начинаем отсчет времени работы транзакции.
00399   so_4::api::send_msg( so_query_name(), "msg_lifetime_left", 0,
00400     so_query_name(), m_lifetime );
00401 }
00402 
00403 void
00404 a_timed_trx_t::do_subscription()
00405 {
00406   so_subscribe( "evt_lifetime_left", "msg_lifetime_left" );
00407 }
00408 
00409 /*
00410   Класс конкретной, прерываемой по таймеру транзакции,
00411   которая выполняет какую-то работу.
00412 */
00413 class a_concrete_timed_trx_t :
00414   public virtual a_concrete_trx_t,
00415   public virtual a_timed_trx_t
00416 {
00417   typedef so_4::rt::agent_t agent_type_t;
00418   public :
00419     a_concrete_timed_trx_t(
00420       // Время (в миллисекундах) через которое
00421       // будет сымитировано сообщение msg_commit.
00422       unsigned int commit_timeout,
00423       // Время (в миллисекундах) через которое
00424       // будет сымитировано сообщение msg_rollback.
00425       unsigned int rollback_timeout,
00426       // Время (в миллисекундах) через которое
00427       // будет работа транзакции будет прервана.
00428       unsigned int lifetime );
00429     virtual ~a_concrete_timed_trx_t();
00430 
00431     virtual const char *
00432     so_query_type() const;
00433 
00434     virtual void
00435     so_on_subscription();
00436 
00437   protected :
00438     // Реальная подписка.
00439     /*
00440       Ничего не делает. Введен для единообразия
00441       и с расчетом на возможное наполнение в
00442       будущем.
00443     */
00444     void
00445     do_subscription();
00446 };
00447 
00448 SOL4_CLASS_START( a_concrete_timed_trx_t )
00449   // Указываем наследование.
00450   SOL4_SUPER_CLASS( a_concrete_trx_t )
00451   SOL4_SUPER_CLASS( a_timed_trx_t )
00452 
00453   // Поскольку есть наследование, нужно
00454   // сразу определить начальное состояние.
00455   SOL4_INITIAL_STATE( st_not_started )
00456 
00457   // Своих событий и состояний не вводится,
00458   // но событие st_started нужно преопределить
00459   // с учетом требований класса a_timed_trx_t.
00460 
00461   SOL4_STATE_START( st_started )
00462     SOL4_STATE_MERGE( a_concrete_trx_t, st_started )
00463 
00464     SOL4_STATE_EVENT( evt_lifetime_left )
00465 
00466     SOL4_STATE_ON_ENTER( on_enter_appropriate_state )
00467   SOL4_STATE_FINISH()
00468 
00469 SOL4_CLASS_FINISH()
00470 
00471 a_concrete_timed_trx_t::a_concrete_timed_trx_t(
00472   unsigned int commit_timeout,
00473   unsigned int rollback_timeout,
00474   unsigned int lifetime )
00475 :
00476   agent_type_t( "a_concrete_timed_trx" ),
00477   a_concrete_trx_t( commit_timeout, rollback_timeout ),
00478   a_timed_trx_t( lifetime )
00479 {
00480 }
00481 
00482 a_concrete_timed_trx_t::~a_concrete_timed_trx_t()
00483 {
00484 }
00485 
00486 void
00487 a_concrete_timed_trx_t::so_on_subscription()
00488 {
00489   a_trx_t::do_subscription();
00490   a_concrete_trx_t::do_subscription();
00491   a_timed_trx_t::do_subscription();
00492   do_subscription();
00493 }
00494 
00495 void
00496 a_concrete_timed_trx_t::do_subscription()
00497 {
00498 }
00499 
00500 int
00501 main()
00502 {
00503   std::auto_ptr< so_4::timer_thread::timer_thread_t >
00504     timer_ptr( so_4::timer_thread::simple::create_timer_thread() );
00505 
00506   std::auto_ptr< so_4::rt::dispatcher_t >
00507     disp_ptr( so_4::disp::one_thread::create_disp( *timer_ptr ) );
00508 
00509   // Эти значения нужно варьировать, чтобы получать
00510   // различные результаты работы примера.
00511   a_concrete_timed_trx_t agent( 2500, 2000, 1500 );
00512   so_4::rt::agent_coop_t coop( agent );
00513 
00514   so_4::ret_code_t rc = so_4::api::start( *disp_ptr, &coop );
00515   if( rc ) {
00516     std::cerr << "start: " << rc << std::endl;
00517   }
00518 
00519   return int( rc );
00520 }

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