State machine: In which state is an action on a transition performed? - state-machine

I'm just reading into the theory of state machines. Please consider this:
event[guard]/action
State A -----------------------------> State B
Here's my question: If I define a transition between states A and B, with event, guard, and action, like in the above "picture"; and furthermore the event is received and the guard expression evaluates to true, then: will the action be performed while my object is in state A, or B?
In other words, do I need the action to be configured to be performable in state A, or B (let's assume I want to choose only one state in which the action can be performed)?
Google finds tell me that the action will be performed at the exact time of transitioning; but my brain has problems to accept it: imo my object needs to be in a certain state while the action is being performed (just because my object needs to always be in a certain state). And the performing of the action may take a while.
Related: What happens if an error occurs during the performing of the action. Will my object stay in state A, or will it transition to state B anyways (remember that the event was received and the guard expression evaluated to true)?

This is fairly easy to check with a custom state machine listener, in which you override the corresponding methods for entering/exiting state and transitions.
will the action be performed while my object is in state A, or B?
Your action (which is on transition) will be performed while you're in state A.
The order of what happens is the following:
Started transition
State Entered: A
SM changed states from:null to: A
Ended transition
---
Executing guard logic
Started transition
Executing normal action //action is executed before exiting State A
State exited: A
State Entered: B
SM changed states from:A to: B
Ended transition
What happens if an error occurs during the performing of the action.
Will my object stay in state A, or will it transition to state B
anyways
You will stay in State A.
As you can see in the above output, the exit of the state happens after the action is executed (successfully). If an exception occurs before that you will still be in state A.

The action will be performed while your object is in state A.
If an error happens during action your state machine will not go to target state B and remain in state A. Additionally you can also define custom Action() for error scenario when actual action() throws exception.

Related

Accessing state in an IO-Monad

I'm trying to access a state of a State Monad inside an IO action.
More specifically: I'm trying to write a state-dependent signal handler using installHandlerfrom System.Posix.Signals which requires IO, however, I'd like to do different actions and change the state from inside the handler. I took a look at unliftio, but I read that State-Monads shouldn't be unlifted.
Is this possible? I'm more looking for an explanation than for a "copy-paste" solution. If unlifting State inside IO doesn't work, what would a solution look like, for when one wants to do some state-aware processing inside IO?
A value of type State a b does not contain a state. It is just an encapsulated function that can provide a resulting state and a result if you pass it a starting state (using the runState function. There is no way to access an intermediate (or "current") state from the outside of this function. This is what makes the State Monad "pure".
You seem to intend to have a handler, that does not always behave the same (even if invoked with the same parameters), but depends on an outside state. This kind of behaviour is "impure", and cannot be achieved by using only pure means. So what you need in this case is something that encapsulates the impureness in a way that you can access a "current value" of some state from the handler, without the current value itself getting passed into the handler.
As you already know from the comments, the go-to tool to provide access to mutable state to an IO action is using an IORef. IORefs work, because the Haskell runtime (traditionally, before multithreading at least) serializes IO actions. So the concept of the "current value" always makes sense. After every IO action, the value pointed to by every IORef is fixed. The order IO actions happen is also fixed, as it needs to be the order you chain them inside do blocks or using the >>= operators. Handling of Signals is performed by the Haskell runtime in a deterministic way, kind of like everytime you chain two IO actions, the runtime checks for pending signals, and invokes the corresponding handler.
In case you want to write code that manipulates data in an imperative way (where you can have a lot of variables, and even arrays where you update sinlge elements), you could write your code as I/O action and use IORef and IOArray for it, but there is a special "lite" version of IO that just supports mutable state in the same way as I/O without being able to interact with the environment. The shared state needs to be created, read and written from inside the same "capsule" of this special IO lite, so that running the whole action does not interact with outside state, but just with its internal state - the capsule as a whole is thus pure, even if single statements inside the capsule can be considered impure. The name of this lite version of IO is called ST, which is short for "state thread".

UML activity diagram: fork with guard conditions on the outputs

I have met a semantic problem with guard conditions and fork in activity diagrams. Suppose terminating action A leads to a fork, and the out put of the fork leads to action B and C (that is, this fork has 1 input and 2 outputs). If A has successfully terminated, and guard condition of B is valid while guard condition of C is not, will the whole activity continue to action B and waits for guard condition of C to become true, or neither B nor C would be executed?
Update: consider the following activity example
Suppose that the first time A terminates, guard condition of C is not valid while B does not have guard. Along the merge node, A is exectued the second time. After the second termination of A, guard condition of C becomes eternally valid and it will be executed twice continuously due to the first and second termination of A. Is this correct?
Once A is finished it will emerge a token and the fork will duplicate that. One token goes straight to B which after finalization re-triggers A to infinity. Now, what happens to the token(s) traveling to C? They just queue at the guard. When the guard is opened after some time it lets pass a single token (because C can hold only a single one). When C is finished it will allow another token to enter (if meanwhile multiple tokens have reached) depending additionally on the guard. Basically C can be started as many times as A has been completed before.
N.B. Your implication in the question "guard conditions on the outputs" is wrong. A guard is always on an incoming control flow of an action. The fork will not control the guard, it's the action. And further an action can never have a guard on the output. This is controlled be the action's behavior. When it terminates it will emerge a token on each of its outgoing control flows (so called implicit fork).
Answer to initial question left as common information
Actually when you draw it, the situation is obvious:
The token emerging right from the top fork will be blocked. B will start since the token passed the guard. Because C does not start the lower fork will hang as it needs 2 tokens. So D is not reached. Unless the guard from C will somewhen be unblocked externally.

UML State Machines: Deep History Pseudostate and Final State

In UML state machines, what exactly happens to the history of a composite state if a final state of a substate is entered?
Consider the state machine shown below. After the trigger sequence T1-T2-T3-T4 it will end up in the final state. By entering the final state the history of the region of State21 gets cleared, and since the region also gets completed by this, the completion transition to State1 will be executed. Now, when trigger T5 gets enabled, the state machine enters the deep history state. I suppose that in this situation the deep history state represents State21, which means the state machine enters State21 and then executes the transition from the initial pseudostate of State21 to State211. Is this correct?
I prefer the behavior described above, but I can see an alternative in which the history of State2 also gets cleared when the final state in State21 is entered. In that case the state machine executes the transition from the the initial pseudostate of State2 to to State22. So what do you think?
From my understanding of deepHistory description
This type of Pseudostate is a kind of variable that represents the most recent active state configuration of its owning Region. As explained above, a Transition terminating on this Pseudostate implies restoring the Region to that same state configuration, but with all the semantics of entering a State (see the Subclause describing State entry).
Your first behavior description seems to be the good one. By trigerring T1, T2, T3, T4, and T5 transitionns you are back to State21 entry i.e. State211.
I read this diagram in the following way:
While in State1 you can enter into State2 by calling T1 (which is a fresh sequence) or via T2 (a retry of the previous sequence).
When the application / system is in State1 it appears to have logic in it that allows for retrying a previous State2 sequence in certain situations. As such deep history keeps those process variables around in the parent state until State1 can make a decision on which way it wants to proceed.
However ambiguities exist in the example state machine model:
The transition back to State1 is not named/numbered, and
An intermediate partially complete state, that requires deep history, has not been defined. The model needs an exit state / criteria defined as a sub-state within State21 that serves as the source for this unnamed transition back to State1.
The current flow within State21 only has one end state and therefore runs to completion every time. Its only when you need to re-enter a state at a given sub-state location that deep history makes sense.

State machine timer self transition

Please explain to me if I get right the meaning of these 3 state machines.
1, StateA Enter action is called (which is nothing at the moment) and then the timer is set up. When the timer triggers Acion1 is executed, then the StateA Exit action (also nothing) is executed, then the whole loop repeats. So StateA Enter action, setting up the timer, etc. This makes a kind of polling with Action1
2, StateB Enter action is called, timer set up and triggers after 10ms and executes Action2. The timer will be not renewed, so it is a kind of delayed action on the state
3, StateC Enter action, Timer is set up, when triggers then Action3 is called, then StateC Exit action and finally StateD Enter action is executed.
Please confirm or correct if it is correct.
1: Your description is correct, with one exception: the exit action is executed before Action1 is executed, at least, that is how I interpret the UML 2.5 spec. Section 14.2.3.4.6 says:
If the composite State has an exit Behavior defined, it is executed (...) before any effect Behavior of the outgoing external Transition.
I think you can safely assume that this is also true for non-composite states, but the UML 2.5 spec should be more explicit in this respect.
2: I don't think this is a proper UML notation, so I cannot confirm or deny your description.
3: This state machine diagram does not specify whether the initial state is StateC or StateD. If it is StateC, then your description is correct, with the exception that StateC's exit action is executed before Action3. To be unambiguous, the diagram should have an initial pseudostate (filled circle) with a transition from the initial pseudostate to StateC.
Generally states are drawn with rounded rect.
1) The notation along the transition is <trigger>/<effect>. The semantics of After(10) leaves some room for interpretation. So when the <trigger> fires it will perform <effect> and return to the same state.
2) I don't know this notation. You can specify entry/do/exit operations like this
3) Is like 1 but enters a new state.

State-machine : How to change state without external event (transient state)?

The scenario:
I have a simple state machine:
Happy path:
Uninitialized->Initialized->InProgress->Done
Unhappy path:
Uninitialized->Initialized->Error
Simply put, I need to cause a transition (either into InProgress or in Error state) without an external event/trigger. I.e. Initialized state should immediately result in one of those states.
Questions:
Is it OK to cause state transition from within Initialized.Enter() ?
I could use state guards to do this, but I'd rather not have non-trivial logic in the state guard (and initialization can very well be complex).
If it is NOT OK, how can I do it differently?
Should I just take this decision out of he FSM all together and have some other component cause the appropriate transition? But then, wouldn't I still have to call that external component from within Initialized.Enter() ? so it solves nothing?
In a state machine, next state is a combinatorial logic function of both input and current state.
In the case you are describing, the same cause (Initialized state) seems to be able to trigger two different effects (either InProgress or Error state). I guess that there is a hidden input whose value makes the difference. I also guess that this input is received during transition from Uninitialized to Initialized.
Therefore I would have a different model:
Uninitialized -> Successfully initialized -> InProgress -> Done
\
`-> Failed Initialization -> Error
Possibly combining Successfully initialized with InProgress and Failed initialization with Error.
EDIT: From your comment, I understand that the hidden input actually is the result of an action (a device initialization). Taking your model, I assume that initialization takes place while in Initialized state (let's call it Initializing). This way, the result from the device is your external event which will trigger transition either to InProgress or to Error.
So keep your state machine and simply add the result of device.Initialize() to the list of inputs or external events.

Resources