summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/statemachine
diff options
context:
space:
mode:
authorKent Hansen <kent.hansen@nokia.com>2012-06-04 21:51:04 +0200
committerQt by Nokia <qt-info@nokia.com>2012-06-06 13:27:32 +0200
commit302e6968f1152d5dee8d5debafb313bd53fa55ff (patch)
tree983df82f4846fd042efec5979dc0c46d8c85d31c /tests/auto/corelib/statemachine
parentfc15a1d5e2cb064df7b6e7b9e821e9db20a91b85 (diff)
statemachine: Make delayed event posting work from secondary thread
postDelayedEvent() and cancelDelayedEvent() are marked as thread-safe in the documentation. Unfortunately, they didn't actually work when called from another thread; they just produced some warnings: QObject::startTimer: timers cannot be started from another thread QObject::killTimer: timers cannot be stopped from another thread As the warnings indicate, the issue was that postDelayedEvent() (cancelDelayedEvent()) unconditionally called QObject::startTimer() (stopTimer()), i.e. without considering which thread the function was called from. If the function is called from a different thread, the actual starting/stopping of the associated timer is now done from the correct thread, by asynchronously calling a private slot on the state machine. This also means that the raw timer id can no longer be used as the id of the delayed event, since a valid event id must be returned before the timer has started. The state machine now manages those ids itself (using a QFreeList, just like startTimer() and killTimer() do), and also keeps a mapping from timer id to event id once the timer has been started. This is inherently more complex than before, but at least the API should work as advertised/intended now. Task-number: QTBUG-17975 Change-Id: I3a866d01dca23174c8841112af50b87141df0943 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
Diffstat (limited to 'tests/auto/corelib/statemachine')
-rw-r--r--tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
index c5d33e7437..14a0bed1b4 100644
--- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp
@@ -101,6 +101,7 @@ private slots:
void postEvent();
void cancelDelayedEvent();
void postDelayedEventAndStop();
+ void postDelayedEventFromThread();
void stopAndPostEvent();
void stateFinished();
void parallelStates();
@@ -1731,6 +1732,55 @@ void tst_QStateMachine::postDelayedEventAndStop()
QVERIFY(machine.configuration().contains(s1));
}
+class DelayedEventPosterThread : public QThread
+{
+ Q_OBJECT
+public:
+ DelayedEventPosterThread(QStateMachine *machine, QObject *parent = 0)
+ : QThread(parent), firstEventWasCancelled(false),
+ m_machine(machine), m_count(0)
+ {
+ moveToThread(this);
+ QObject::connect(m_machine, SIGNAL(started()),
+ this, SLOT(postEvent()));
+ }
+
+ mutable bool firstEventWasCancelled;
+
+private Q_SLOTS:
+ void postEvent()
+ {
+ int id = m_machine->postDelayedEvent(new QEvent(QEvent::User), 1000);
+ firstEventWasCancelled = m_machine->cancelDelayedEvent(id);
+
+ m_machine->postDelayedEvent(new QEvent(QEvent::User), 1);
+
+ quit();
+ }
+private:
+ QStateMachine *m_machine;
+ int m_count;
+};
+
+void tst_QStateMachine::postDelayedEventFromThread()
+{
+ QStateMachine machine;
+ QState *s1 = new QState(&machine);
+ QFinalState *f = new QFinalState(&machine);
+ s1->addTransition(new EventTransition(QEvent::User, f));
+ machine.setInitialState(s1);
+
+ DelayedEventPosterThread poster(&machine);
+ poster.start();
+
+ QSignalSpy finishedSpy(&machine, SIGNAL(finished()));
+ QVERIFY(finishedSpy.isValid());
+ machine.start();
+ QTRY_COMPARE(finishedSpy.count(), 1);
+
+ QVERIFY(poster.firstEventWasCancelled);
+}
+
void tst_QStateMachine::stopAndPostEvent()
{
QStateMachine machine;