summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp32
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h1
2 files changed, 27 insertions, 6 deletions
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index 1fe7f96b3c..b3e91c1ac0 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -1335,6 +1335,28 @@ void QStateMachinePrivate::clearHistory()
}
}
+/*!
+ \internal
+
+ Registers all signal transitions whose sender object lives in another thread.
+
+ Normally, signal transitions are lazily registered (when a state becomes
+ active). But if the sender is in a different thread, the transition must be
+ registered early to keep the state machine from "dropping" signals; e.g.,
+ a second (transition-bound) signal could be emitted on the sender thread
+ before the state machine gets to process the first signal.
+*/
+void QStateMachinePrivate::registerMultiThreadedSignalTransitions()
+{
+ Q_Q(QStateMachine);
+ QList<QSignalTransition*> transitions = rootState()->findChildren<QSignalTransition*>();
+ for (int i = 0; i < transitions.size(); ++i) {
+ QSignalTransition *t = transitions.at(i);
+ if ((t->machine() == q) && t->senderObject() && (t->senderObject()->thread() != q->thread()))
+ registerSignalTransition(t);
+ }
+}
+
void QStateMachinePrivate::_q_start()
{
Q_Q(QStateMachine);
@@ -1346,6 +1368,8 @@ void QStateMachinePrivate::_q_start()
externalEventQueue.clear();
clearHistory();
+ registerMultiThreadedSignalTransitions();
+
#ifdef QSTATEMACHINE_DEBUG
qDebug() << q << ": starting";
#endif
@@ -1703,8 +1727,8 @@ void QStateMachinePrivate::unregisterTransition(QAbstractTransition *transition)
void QStateMachinePrivate::maybeRegisterSignalTransition(QSignalTransition *transition)
{
Q_Q(QStateMachine);
- if (((state == Running) && configuration.contains(transition->sourceState()))
- || (transition->senderObject() && (transition->senderObject()->thread() != q->thread()))) {
+ if ((state == Running) && (configuration.contains(transition->sourceState())
+ || (transition->senderObject() && (transition->senderObject()->thread() != q->thread())))) {
registerSignalTransition(transition);
}
}
@@ -1771,14 +1795,10 @@ void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transitio
void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transition)
{
- Q_Q(QStateMachine);
int signalIndex = QSignalTransitionPrivate::get(transition)->signalIndex;
if (signalIndex == -1)
return; // not registered
const QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
- // Don't unregister if the sender is on another thread
- if (!sender || (sender->thread() != q->thread()))
- return;
QSignalTransitionPrivate::get(transition)->signalIndex = -1;
connectionsMutex.lock();
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
index cf20ee31ca..c8d09586b4 100644
--- a/src/corelib/statemachine/qstatemachine_p.h
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -175,6 +175,7 @@ public:
void maybeRegisterSignalTransition(QSignalTransition *transition);
void registerSignalTransition(QSignalTransition *transition);
void unregisterSignalTransition(QSignalTransition *transition);
+ void registerMultiThreadedSignalTransitions();
#ifndef QT_NO_STATEMACHINE_EVENTFILTER
void maybeRegisterEventTransition(QEventTransition *transition);
void registerEventTransition(QEventTransition *transition);