diff options
author | Kent Hansen <khansen@trolltech.com> | 2009-09-29 14:40:48 (GMT) |
---|---|---|
committer | Kent Hansen <khansen@trolltech.com> | 2009-09-29 14:42:15 (GMT) |
commit | 544f06f1fe29e986cd2b3fd1fd7198d688275969 (patch) | |
tree | 015c0c61ecd2141d949a7d6cefd8c31327e3bd1f | |
parent | 86a30b667e189b8659fab384d93022e55a67b81e (diff) | |
download | Qt-544f06f1fe29e986cd2b3fd1fd7198d688275969.zip Qt-544f06f1fe29e986cd2b3fd1fd7198d688275969.tar.gz Qt-544f06f1fe29e986cd2b3fd1fd7198d688275969.tar.bz2 |
Make sure delayed events are cancelled when a state machine halts
Otherwise the events might creep into the event loop if the state
machine is restarted.
Reviewed-by: Eskil Abrahamsen Blomfeldt
-rw-r--r-- | src/corelib/statemachine/qstatemachine.cpp | 20 | ||||
-rw-r--r-- | src/corelib/statemachine/qstatemachine_p.h | 1 | ||||
-rw-r--r-- | tests/auto/qstatemachine/tst_qstatemachine.cpp | 39 |
3 files changed, 60 insertions, 0 deletions
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 256763b..c7144e4 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1265,11 +1265,13 @@ void QStateMachinePrivate::_q_process() break; case Finished: state = NotRunning; + cancelAllDelayedEvents(); unregisterAllTransitions(); emit q->finished(); break; case Stopped: state = NotRunning; + cancelAllDelayedEvents(); unregisterAllTransitions(); emit q->stopped(); break; @@ -1291,6 +1293,19 @@ void QStateMachinePrivate::processEvents(EventProcessingMode processingMode) } } +void QStateMachinePrivate::cancelAllDelayedEvents() +{ + Q_Q(QStateMachine); + QHash<int, QEvent*>::const_iterator it; + for (it = delayedEvents.constBegin(); it != delayedEvents.constEnd(); ++it) { + int id = it.key(); + QEvent *e = it.value(); + q->killTimer(id); + delete e; + } + delayedEvents.clear(); +} + namespace { class GoToStateTransition : public QAbstractTransition @@ -1946,6 +1961,11 @@ bool QStateMachine::event(QEvent *e) if (e->type() == QEvent::Timer) { QTimerEvent *te = static_cast<QTimerEvent*>(e); int tid = te->timerId(); + if (d->state != QStateMachinePrivate::Running) { + // This event has been cancelled already + Q_ASSERT(!d->delayedEvents.contains(tid)); + return true; + } QEvent *ee = d->delayedEvents.take(tid); if (ee != 0) { killTimer(tid); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 141bc5c..cf7a073 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -160,6 +160,7 @@ public: void handleTransitionSignal(QObject *sender, int signalIndex, void **args); void processEvents(EventProcessingMode processingMode); + void cancelAllDelayedEvents(); #ifndef QT_NO_PROPERTIES typedef QPair<QObject *, QByteArray> RestorableId; diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 463dbf6..b808f7f 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -120,6 +120,7 @@ private slots: void assignPropertyWithAnimation(); void postEvent(); void cancelDelayedEvent(); + void postDelayedEventAndStop(); void stateFinished(); void parallelStates(); void parallelRootState(); @@ -1638,6 +1639,44 @@ void tst_QStateMachine::cancelDelayedEvent() QVERIFY(machine.configuration().contains(s2)); } +void tst_QStateMachine::postDelayedEventAndStop() +{ + QStateMachine machine; + QState *s1 = new QState(&machine); + QFinalState *s2 = new QFinalState(&machine); + s1->addTransition(new StringTransition("a", s2)); + machine.setInitialState(s1); + + QSignalSpy startedSpy(&machine, SIGNAL(started())); + machine.start(); + QTRY_COMPARE(startedSpy.count(), 1); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + + int id1 = machine.postDelayedEvent(new StringEvent("a"), 0); + QVERIFY(id1 != -1); + QSignalSpy stoppedSpy(&machine, SIGNAL(stopped())); + machine.stop(); + QTRY_COMPARE(stoppedSpy.count(), 1); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + + machine.start(); + QTRY_COMPARE(startedSpy.count(), 2); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + + int id2 = machine.postDelayedEvent(new StringEvent("a"), 1000); + QVERIFY(id2 != -1); + machine.stop(); + QTRY_COMPARE(stoppedSpy.count(), 2); + machine.start(); + QTRY_COMPARE(startedSpy.count(), 3); + QTestEventLoop::instance().enterLoop(2); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); +} + void tst_QStateMachine::stateFinished() { QStateMachine machine; |