From cecd52b89ae6c58476c39079830908d22f52ef2d Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Tue, 17 Feb 2015 17:37:32 +0100 Subject: qstatemachine: add methods detect when a machine has processed an event currently when adding an event it is not possible to know when processing it has finished. In particular if the event is ignored no method is called. Adding virtual methods to the private implementation (binary compatibility). These methods allow for extended automatic testing of the state machines. (cherry picked from commit e7feb956280105113b3e58f12e5f32f54199a95a) Change-Id: Iaa48fb9d7f6a6cde1a8a7a2bece7b4df55c147e8 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/statemachine/qstatemachine.cpp | 50 ++++++++++++++++++++++++++++-- src/corelib/statemachine/qstatemachine_p.h | 4 +++ 2 files changed, 52 insertions(+), 2 deletions(-) (limited to 'src/corelib/statemachine') diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 6e36f93c40..7e9d99a416 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1878,9 +1878,11 @@ void QStateMachinePrivate::_q_process() Q_ASSERT(!processing); processing = true; processingScheduled = false; + beginMacrostep(); #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": starting the event processing loop"; #endif + bool didChange = false; while (processing) { if (stop) { processing = false; @@ -1923,15 +1925,17 @@ void QStateMachinePrivate::_q_process() } } if (!enabledTransitions.isEmpty()) { + didChange = true; q->beginMicrostep(e); microstep(e, enabledTransitions, &calculationCache); q->endMicrostep(e); } -#ifdef QSTATEMACHINE_DEBUG else { + noMicrostep(); +#ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": no transitions enabled"; - } #endif + } delete e; } #ifdef QSTATEMACHINE_DEBUG @@ -1944,6 +1948,7 @@ void QStateMachinePrivate::_q_process() switch (stopProcessingReason) { case EventQueueEmpty: + processedPendingEvents(didChange); break; case Finished: state = NotRunning; @@ -1960,6 +1965,7 @@ void QStateMachinePrivate::_q_process() emit q->runningChanged(false); break; } + endMacrostep(didChange); } void QStateMachinePrivate::_q_startDelayedEventTimer(int id, int delay) @@ -2081,6 +2087,46 @@ void QStateMachinePrivate::emitStateFinished(QState *forState, QFinalState *guil QStatePrivate::get(forState)->emitFinished(); } +/* + This function is called when the state machine is performing no + microstep because no transition is enabled (i.e. an event is ignored). + + The default implementation does nothing. +*/ +void QStateMachinePrivate::noMicrostep() +{ } + +/* + This function is called when the state machine has reached a stable + state (no pending events), and has not finished yet. + For each event the state machine receives it is guaranteed that + 1) beginMacrostep is called + 2) selectTransition is called at least once + 3) begin/endMicrostep is called at least once or noMicrostep is called + at least once (possibly both, but at least one) + 4) the state machine either enters an infinite loop, or stops (runningChanged(false), + and either finished or stopped are emitted), or processedPendingEvents() is called. + 5) if the machine is not in an infinite loop endMacrostep is called + + didChange is set to true if at least one microstep was performed, it is possible + that the machine returned to exactly the same state as before, but some transitions + were triggered. + + The default implementation does nothing. +*/ +void QStateMachinePrivate::processedPendingEvents(bool didChange) +{ + Q_UNUSED(didChange); +} + +void QStateMachinePrivate::beginMacrostep() +{ } + +void QStateMachinePrivate::endMacrostep(bool didChange) +{ + Q_UNUSED(didChange); +} + namespace _QStateMachine_Internal{ class GoToStateTransition : public QAbstractTransition diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 28fd96f507..5584bc91ab 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -128,6 +128,10 @@ public: void removeConflictingTransitions(QList &enabledTransitions, CalculationCache *cache); void microstep(QEvent *event, const QList &transitionList, CalculationCache *cache); QList selectTransitions(QEvent *event, CalculationCache *cache); + virtual void noMicrostep(); + virtual void processedPendingEvents(bool didChange); + virtual void beginMacrostep(); + virtual void endMacrostep(bool didChange); void exitStates(QEvent *event, const QList &statesToExit_sorted, const QHash > &assignmentsForEnteredStates); QList computeExitSet(const QList &enabledTransitions, CalculationCache *cache); -- cgit v1.2.3