Прав ли генератор конечного автомата BoUML, когда он вызывает doActivity непосредственно перед выходом из состояния StateMachine? - PullRequest
3 голосов
/ 06 мая 2020

Рассмотрим простой StateMachine:

enter image description here

Below is a fragment of C++ code generated by BoUML из него:

 // to manage the event create
 void Sample::Sample_State::State1_State::create(Sample & stm) {
         _doentry(stm);
 }

 // perform the 'entry behavior'
 void Sample::Sample_State::State1_State::_doentry(Sample & stm) {
   stm.enter_state1();
 }

 // perform the 'exit behavior'
 void Sample::Sample_State::State1_State::_doexit(Sample & stm) {
   stm.exit_state1();
 }

 // perform the 'do activity'
 void Sample::Sample_State::State1_State::_do(Sample & stm) {
   stm.do_state1();
 }

 // to manage the event exit_state1
 void Sample::Sample_State::State1_State::exit_state1(Sample & stm) {
     _do(stm);
     {
       stm._sample_state._state1_state._doexit(stm);
       stm._set_currentState(stm._sample_state);
       stm._final();
     }
 }

Обратите внимание, что _do(stm) вызывается Sample::Sample_State::State1_State::exit_state1(Sample & stm), т.е. выход из состояния 1, непосредственно перед вызовом поведения выхода stm._sample_state._state1_state._doexit(stm);

Спецификация UML сообщает нам:

14.2.3.4 .3 Состояние входа, выхода и поведения doActivity

. . .

Состояние может также иметь связанное поведение doActivity. Это поведение начинает выполнение при входе в состояние (но только после того, как поведение входа в состояние завершено) и выполняется одновременно с любыми другими поведениями, которые могут быть связаны с состоянием, пока:

  • не завершится (в в этом случае генерируется событие завершения) или
  • состояние завершается, и в этом случае выполнение doActivity Behavior прерывается.

выполнение doActivity Behavior состояния на него не влияет срабатывание внутреннего перехода этого состояния.

Разве не было бы более согласованным со спецификацией UML вызывать _do(stm) из Sample::Sample_State::State1_State::create() сразу после _doentry(stm);?

1 Ответ

2 голосов
/ 06 мая 2020

На самом деле это хуже, я поменял управление поведением do между случаями входа и выхода. Учитывая этот конечный автомат (переходы от состояния к самому себе являются внутренними): enter image description here

and the main

int main()
{
  MM mm;
  
  mm.create();

  cout 

Compilation (without defining VERBOSE_STATE_MACHINE) and execution :

pi@raspberrypi:~/sm/src $ g++ -Wall -g MM.cpp mmain.cpp 
pi@raspberrypi:~/sm/src $ ./a.out
a entry

fire taa
a do
taa

fire tab
a do
a exit
tab expr
b entry

fire tbb
b do
tbb

fire tba
b do
b exit
tba expr
a entry

fire tdone
a do
a exit
tdone
pi@raspberrypi:~/sm/src $ 

So the do behavior is executed for an internal transition, wrongly when exiting a state, and is missing when entering in a state.

Note the state machine generator is the plug-out and its definition is part of BoUML delivery through the project sm_generator, it is implemented in C++ (not in Java). So you can load the project sm_generator, save-as it where you have the write permission, correct it, generate the C++ code, compile it and replace the official generator with your new version or declare your new plug-out and associate it to the state machine to have it in the menus.


I modified my state machine generator, the previous time was in 2011!

The do behavior is not anymore executed when exiting the state including through a self external transition, it is now executed after the possible do entry. I also do it after the possible transition behavior of a self internal transition, rather than before, that avoid two consecutive executions without nothing between in case the transition has a behavior.

Note it was already possible to execute the possible do behavior of the current state through the operation doActivity defined on the class associated to the machine. That allows to do it between transition firings.

With the previous state machine a little modified to add a self external transition :

введите описание изображения здесь

и что main

#include "MM.h"
#include <iostream>
using namespace std;

int main()
{
  MM mm;
  
  mm.create();

  cout << endl << "fire taa" << endl;
  mm.taa();

  cout << endl << "fire ta_a" << endl;
  mm.ta_a();

  cout << endl << "fire tab" << endl;
  mm.tab();

  cout << endl << "fire tbb" << endl;
  mm.tbb();

  cout << endl << "fire tba" << endl;
  mm.tba();

  cout << endl << "fire tdone" << endl;
  mm.tdone();
}

Компиляция (без определения VERBOSE_STATE_MACHINE ) и выполнение:

pi@raspberrypi:~/sm/src $ g++ -Wall MM.cpp mmain.cpp 
pi@raspberrypi:~/sm/src $ ./a.out
a entry
a do

fire taa
taa expr
a do

fire ta_a
a exit
ta_a expr
a entry
a do

fire tab
a exit
tab expr
b entry
b do

fire tbb
tbb expr
b do

fire tba
b exit
tba expr
a entry
a do

fire tdone
a exit
tdone expr
pi@raspberrypi:~/sm/src $ 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...