This is an old revision of the document!
Table of Contents
Generate code from state machines with regions
In state diagrams usually only one state is active at a time. In UML state diagrams regions also allow to model concurrency - i.e. more than one state is active at a time (AND states).
The latest beta now supports the modeling of parallel regions with the following constraints:
- Transitions must not cross region boarders. Why this is important is discussed further down
- No regions in regions
- No support for fork
- Join can be realized with transitions using guards like
isInS221 && isInS222
as an example - UModel and EnterpriseArchitect as modeling tools
Here is the simplified C-code example of the oven state machine.
void oven(OVEN_INSTANCEDATA_T *instanceVar){ OVEN_EV_CONSUMED_FLAG_T evConsumed = 0U; OVEN_INSTANCEDATA_T instanceVarCopy = *instanceVar; switch (instanceVar->stateVar) { case Active: /* calling region code */ evConsumed |= ovenActiveLight(instanceVar, &instanceVarCopy, msg); evConsumed |= ovenActivePower(instanceVar, &instanceVarCopy, msg); evConsumed |= ovenActiveRadioator(instanceVar, &instanceVarCopy, msg); /* Check if event was already processed */ if(evConsumed==0U){ .... /* handle event on parent level */ break; } /* end switch stateVar_root */ /* Save the modified instance data */ *instanceVar = instanceVarCopy; } OVEN_EV_CONSUMED_FLAG_T ovenActiveLight(OVEN_INSTANCEDATA_T *instanceVar, OVEN_INSTANCEDATA_T *instanceVarCopy, OVEN_EVENT_T msg){ ... } OVEN_EV_CONSUMED_FLAG_T ovenActivePower(OVEN_INSTANCEDATA_T *instanceVar, OVEN_INSTANCEDATA_T *instanceVarCopy, OVEN_EVENT_T msg){ ... } OVEN_EV_CONSUMED_FLAG_T ovenActiveRadioator(OVEN_INSTANCEDATA_T *instanceVar, OVEN_INSTANCEDATA_T *instanceVarCopy, OVEN_EVENT_T msg){ ... }
And the same example for C++:
// State machine event handler int oven::processEvent(OVEN_EVENT_T msg){ int evConsumed = 0; OVEN_INSTANCEDATA_T instanceVarCopy = *instanceVar; if(m_initialized==false) return 0; switch (stateVar) { case Active: /* calling region code */ evConsumed |= ovenActiveLight(msg); evConsumed |= ovenActivePower(msg); evConsumed |= ovenActiveRadioator(msg); /* Check if event was already processed */ if(evConsumed==0){ .... /* handle event on parent level */ ... return evConsumed; } /* Region code for state Active */ int oven::ovenActiveLight(OVEN_EVENT_T msg){ ... } int oven::ovenActivePower(OVEN_EVENT_T msg){ ... } int oven::ovenActiveRadioator(OVEN_EVENT_T msg){ ... }
Points to consider with regions
Transitions must not cross region boundaries
In the first diagram state transitions do not cross region boundaries and therefore the modeller’s intension is quite clear. But look at the next diagram which is a valid diagram too. Now it is not clear anymore what the modeller had in mind. And it is also not very obvious what a code generator would/should generate. For that reason it is necessary that a code generator defines some limits here.
Regions must work on the same instance data
State diagrams follow the run-to-completion concept: Transitions that fire are fully executed and the state machine reaches a stable state configuration until it returns and can respond to the next event. To ensure this a copy of the instance data is kept and state changes are only performed on that copy. In practice this means that changes in one region does not influence other regions. Look into the following figure below.
- If the event
evClosed
is sent regionValveA
andValveB
change state. - But there is no state change in region
Motor
at the same time. The reason is that the transition fromStop
→Run
was not triggered at the beginning of the machine execution. - This behavior ensures that the result of a machine execution step is 100% predictable and e.g. not dependent of the execution order of the regions.
- But on the other side it means that a second run of the machine is required to reach state
MachineRun
. I.e. the regionMotor
is always one cycle behind theValve
regions.
And the conclusions?
Usually there is a way to model a problem with regions and without regions. The solution with regions allows to model a kind of parallelism and allows to explicitly display independent parts of a system.
On the other side exactly this parallelism is responsible that models with regions looks a bit more complex at first view.
If you have comments and suggestions please let me know! If you are interested to test this version download the latest beta following this download link.