How do you implement a choice in a state machine in Qt?

589 Views Asked by At

Imagine a part of your state machine looks like this:

How do you properly implement the choice part in Qt? I know there are guarded transitions, but that would mean that I need to:

  • Create a subclass of a QAbstractTransition which accepts e.g. an std::function<bool()> and a flag which determines if the transition happens when that boolean result is true, or when it is false
  • Create two instances of this class with the same boolean function, but opposite transition guards
  • Add two transitions from S1 using these two instances.

That approach seems kind of clumsy and error prone for something as simple as a choice. Is there a more maintainable approach to implement this?

1

There are 1 best solutions below

0
On BEST ANSWER

License Notice:

Alternatively to the default StackOverflow license you are hereby allowed to use this code through the MIT License.

I've created a BooleanChoiceTransition class with a constructor like this (might contain errors, the code is not on this machine, so I typed it by heart):

BooleanChoiceTransition::BooleanChoiceTransition(std::function<bool()> choiceFunc, QState* targetForTrueCase, QState* targetForFalseCase)
  : QState{}
{
    this->addTransition(this, &BooleanChoiceTransition::transitionToTrueTarget, targetForTrueCase);
    this->addTransition(this, &BooleanChoiceTransition::transitionToFalseTarget, targetForFalseCase);
    (void)QObject::connect(this, &QAbstractState::entered, [this]() {
        if(choiceFunc())
        {
            emit transitionToTrueTarget();
        }
        else
        {
            emit transitionToFalseTarget();
        }
    });
}

with transitionToTrueTarget and transitionToFalseTarget being signals of course.

For the case of the example in the question, the class can be used like so:

auto choiceState = new BooleanChoiceTransition([this](){ return _someConditionFullfilled; }, s2, s3);
s1->addTransition(this, &MyClass::someTrigger, choiceState);

Since BooleanChoiceTransition is a QState, this can even be nested easily:

auto outerChoiceState = new BooleanChoiceTransition([this](){ return _someOtherConditionFullfilled; }, s4, choiceState);