Giter Club home page Giter Club logo

Comments (15)

DonMathi avatar DonMathi commented on August 25, 2024 1

Yes that would solve it.
From my understanding of state machines, I would say that the natural order of invocation should be from the inner state first (bottom-to-top order)

You could implement both invocation orders (as I suggests), so that possible to choose.
Or you could provide 2 solutions.

from hfsm2.

andrew-gresyk avatar andrew-gresyk commented on August 25, 2024 1

Ok, merged your example in.

I'm trying to understand how the change in order of invocation would solve your problem.
Could you write down a sequence of calls that happens right now and the sequence of calls you'd like to have?

Just a small one around the problem to illustrate the issue should suffice.

from hfsm2.

andrew-gresyk avatar andrew-gresyk commented on August 25, 2024

Thanks!
Sure. In your case - by 'higher priority' - you mean the order of invocation?

from hfsm2.

DonMathi avatar DonMathi commented on August 25, 2024

Yes: Like if I have state A with an inner state B, and both will react on event E.
Then first A will react on E
Then B will react on E
Then B should rereact on E
And finally A should rereact on E

The problem came across when calling control.changeTo() in both A and B.
Once A had called the changeTo method then B could not overwrite it.
My current implentation has a check in A that determines the work for B.
But I think by adding a rereact or retract pattern that this could be a nice work-around

from hfsm2.

DonMathi avatar DonMathi commented on August 25, 2024

`struct Ready : FSM::State
{
using FSM::State::react;

void react(const Digit_0&, FullControl& control)
{
	control.context().clearOperand1();
	control.context().insertInOperand1(0);
	control.changeTo<Zero1>();
}

void react(const Digit_1_9& digit, FullControl& control)
{
	control.context().clearOperand1();
	control.context().insertInOperand1(digit.digit);
	control.changeTo<Int1>();
}

void react(const Point&, FullControl& control)
{
	control.context().clearOperand1();
	control.changeTo<Frac1>();
}

void react(const Operator& op, FullControl& control)
{
	if (control.isActive<Begin>() && op.mathOperator==MathOperator::MINUS) // Here is the check that I had to make in a higher state
		control.changeTo<Negated1>();
	else
	{
		control.context().mathOperator = op.mathOperator;
		control.changeTo<opEntered>();
	}
}

};`

from hfsm2.

andrew-gresyk avatar andrew-gresyk commented on August 25, 2024

I see, interesting.
Would changing top-to-bottom invocation order of the .react() methods to bottom-to-top solve the issue?
The parent region's .react() will still be called, even if later than the child state's one.

from hfsm2.

DonMathi avatar DonMathi commented on August 25, 2024

As reference I can provide this link where you in "Figure 2.18: The final calculator statechart" can see the state machine that I tried to implement.

from hfsm2.

DonMathi avatar DonMathi commented on August 25, 2024

I have uploaded the complete calculator example

from hfsm2.

andrew-gresyk avatar andrew-gresyk commented on August 25, 2024

Nice, let me have a look.
Always interesting to see different ways the library is used!
I'd love to have this example in the main HFSM2 repo as well if you don't mind?

from hfsm2.

DonMathi avatar DonMathi commented on August 25, 2024

Yes, please go ahead. I'm happy to contribute

from hfsm2.

DonMathi avatar DonMathi commented on August 25, 2024

In the BEGIN state the MINUS operator work as sign for operand 1, in any other case it work as operator between operand 1 and 2.
So in the BEGIN state I would test for the MINUS operator at change state to NEGATED1. In the outer state READY I would react on any operator and change to OPENTERED.
With the top-to-bottom invocation order READY will react on the MINUS first, and BEGIN would react after.
With bottom-to-top invocation order BEGIN would react first and READY after.
When BEGIN doesn't make a changeTo call then READY will.

from hfsm2.

andrew-gresyk avatar andrew-gresyk commented on August 25, 2024

I see.

I would move void react(const Operator& op) from Ready to both Begin and Result and leverage the fact that only one of them could be active.

from hfsm2.

andrew-gresyk avatar andrew-gresyk commented on August 25, 2024

Also, related to the change in order.

When FSM::Instance::react() is called, calls to Control::changeTo<>() don't result in immediate transitions.
First, react(TEvent&) with be called on all active states, and all of them will have the chance to queue transitions.

The actual transitions will not be executed until the end of FSM::Instance::react(), after all active states had their react(TEvent&) executed.

FSM::Instance::update() works the same way: first all active states' update() methods are called, and only then all transitions are executed, with the appropriate guards, and exit() and enter().

So even if the order is changed, the transitions from all states will be executed during FSM::Instance::react() or FSM::Instance::update().

The reason for this, is that within hierarchy, it's often important to be able to batch multiple transitions together, e.g. with orthogonal regions.

from hfsm2.

DonMathi avatar DonMathi commented on August 25, 2024

I see.

I would move void react(const Operator& op) from Ready to both Begin and Result and leverage the fact that only one of them could be active.

Yes. That could be a solution.

I was just thinking in terms of the state machine diagram for the calculator, the transition on OPER event is going from READY to opENTERED, and the transition on OPER[e->keyID=='-'] is going from BEGIN to NEGATED1. Here you see an example of how outer states (READY) makes transition when no inner states does.
Either it was not an '-' on the BEGIN state or the inner state was RESULT.

This is a general property of state machine diagrams, that inner states handles specializations, and outer states handles generalizations.

I appreciate your time and consideration

from hfsm2.

andrew-gresyk avatar andrew-gresyk commented on August 25, 2024

Yes.
The way inner states are handled might be different.
In HFSM2, when a state is activated - the entire edge from root to leaf containing the said state will be activated.

In your example, READY region will never be activated without either RESULT or BEGIN sub-states.
For a composite region (which READY is), when READY is activated - the initial state (RESULT) will be activated by default.
You can check Wiki page for more details on this.

from hfsm2.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.