diff options
author | Gunnar Sletta <gunnar@trolltech.com> | 2009-10-30 09:06:17 (GMT) |
---|---|---|
committer | Gunnar Sletta <gunnar@trolltech.com> | 2009-10-30 09:06:17 (GMT) |
commit | dc4e074324eb91a8a16e14c86ff41b03647b4cfa (patch) | |
tree | 55bfad60a6c1ea55d75171596ffd019b0906abb1 /src/corelib/statemachine | |
parent | 7881773800c05c09f0e85a80c1cbb678981bd6c0 (diff) | |
parent | af92a4e78613ee3a0d402d3f67126284d0bb6656 (diff) | |
download | Qt-dc4e074324eb91a8a16e14c86ff41b03647b4cfa.zip Qt-dc4e074324eb91a8a16e14c86ff41b03647b4cfa.tar.gz Qt-dc4e074324eb91a8a16e14c86ff41b03647b4cfa.tar.bz2 |
Merge branch '4.6' of git@scm.dev.nokia.troll.no:qt/qt into 4.6
Diffstat (limited to 'src/corelib/statemachine')
-rw-r--r-- | src/corelib/statemachine/qabstractstate.cpp | 8 | ||||
-rw-r--r-- | src/corelib/statemachine/qabstractstate_p.h | 2 | ||||
-rw-r--r-- | src/corelib/statemachine/qstate.cpp | 44 | ||||
-rw-r--r-- | src/corelib/statemachine/qstate_p.h | 4 | ||||
-rw-r--r-- | src/corelib/statemachine/qstatemachine.cpp | 93 | ||||
-rw-r--r-- | src/corelib/statemachine/qstatemachine_p.h | 11 |
6 files changed, 124 insertions, 38 deletions
diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp index 72d640b..cf67cdd 100644 --- a/src/corelib/statemachine/qabstractstate.cpp +++ b/src/corelib/statemachine/qabstractstate.cpp @@ -78,7 +78,8 @@ QT_BEGIN_NAMESPACE function to perform custom processing when the state is exited. */ -QAbstractStatePrivate::QAbstractStatePrivate() +QAbstractStatePrivate::QAbstractStatePrivate() + : parentState(0) { } @@ -150,7 +151,10 @@ QAbstractState::~QAbstractState() */ QState *QAbstractState::parentState() const { - return qobject_cast<QState*>(parent()); + Q_D(const QAbstractState); + if (d->parentState != parent()) + d->parentState = qobject_cast<QState*>(parent()); + return d->parentState; } /*! diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h index 4b1306d..cd57815 100644 --- a/src/corelib/statemachine/qabstractstate_p.h +++ b/src/corelib/statemachine/qabstractstate_p.h @@ -76,6 +76,8 @@ public: void emitEntered(); void emitExited(); + + mutable QState *parentState; }; QT_END_NAMESPACE diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index a6e4a57..bcd8364 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -124,7 +124,8 @@ QT_BEGIN_NAMESPACE */ QStatePrivate::QStatePrivate() - : errorState(0), initialState(0), childMode(QState::ExclusiveStates) + : errorState(0), initialState(0), childMode(QState::ExclusiveStates), + childStatesListNeedsRefresh(true), transitionsListNeedsRefresh(true) { } @@ -180,15 +181,18 @@ QState::~QState() QList<QAbstractState*> QStatePrivate::childStates() const { - QList<QAbstractState*> result; - QList<QObject*>::const_iterator it; - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QAbstractState *s = qobject_cast<QAbstractState*>(*it); - if (!s || qobject_cast<QHistoryState*>(s)) - continue; - result.append(s); + if (childStatesListNeedsRefresh) { + childStatesList.clear(); + QList<QObject*>::const_iterator it; + for (it = children.constBegin(); it != children.constEnd(); ++it) { + QAbstractState *s = qobject_cast<QAbstractState*>(*it); + if (!s || qobject_cast<QHistoryState*>(s)) + continue; + childStatesList.append(s); + } + childStatesListNeedsRefresh = false; } - return result; + return childStatesList; } QList<QHistoryState*> QStatePrivate::historyStates() const @@ -205,14 +209,17 @@ QList<QHistoryState*> QStatePrivate::historyStates() const QList<QAbstractTransition*> QStatePrivate::transitions() const { - QList<QAbstractTransition*> result; - QList<QObject*>::const_iterator it; - for (it = children.constBegin(); it != children.constEnd(); ++it) { - QAbstractTransition *t = qobject_cast<QAbstractTransition*>(*it); - if (t) - result.append(t); + if (transitionsListNeedsRefresh) { + transitionsList.clear(); + QList<QObject*>::const_iterator it; + for (it = children.constBegin(); it != children.constEnd(); ++it) { + QAbstractTransition *t = qobject_cast<QAbstractTransition*>(*it); + if (t) + transitionsList.append(t); + } + transitionsListNeedsRefresh = false; } - return result; + return transitionsList; } #ifndef QT_NO_PROPERTIES @@ -468,6 +475,11 @@ void QState::setChildMode(ChildMode mode) */ bool QState::event(QEvent *e) { + Q_D(QState); + if ((e->type() == QEvent::ChildAdded) || (e->type() == QEvent::ChildRemoved)) { + d->childStatesListNeedsRefresh = true; + d->transitionsListNeedsRefresh = true; + } return QAbstractState::event(e); } diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h index 20cda29..34c8838 100644 --- a/src/corelib/statemachine/qstate_p.h +++ b/src/corelib/statemachine/qstate_p.h @@ -99,6 +99,10 @@ public: QAbstractState *errorState; QAbstractState *initialState; QState::ChildMode childMode; + mutable bool childStatesListNeedsRefresh; + mutable QList<QAbstractState*> childStatesList; + mutable bool transitionsListNeedsRefresh; + mutable QList<QAbstractTransition*> transitionsList; QList<QPropertyAssignment> propertyAssignments; }; diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index e182c88..689967a 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1216,8 +1216,7 @@ void QStateMachinePrivate::_q_process() delete e; e = 0; } - if (enabledTransitions.isEmpty() && !internalEventQueue.isEmpty()) { - e = internalEventQueue.takeFirst(); + if (enabledTransitions.isEmpty() && ((e = dequeueInternalEvent()) != 0)) { #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": dequeued internal event" << e << "of type" << e->type(); #endif @@ -1228,13 +1227,7 @@ void QStateMachinePrivate::_q_process() } } if (enabledTransitions.isEmpty()) { - if (externalEventQueue.isEmpty()) { - if (internalEventQueue.isEmpty()) { - processing = false; - stopProcessingReason = EventQueueEmpty; - } - } else { - e = externalEventQueue.takeFirst(); + if ((e = dequeueExternalEvent()) != 0) { #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": dequeued external event" << e << "of type" << e->type(); #endif @@ -1243,6 +1236,11 @@ void QStateMachinePrivate::_q_process() delete e; e = 0; } + } else { + if (isInternalEventQueueEmpty()) { + processing = false; + stopProcessingReason = EventQueueEmpty; + } } } if (!enabledTransitions.isEmpty()) { @@ -1278,17 +1276,60 @@ void QStateMachinePrivate::_q_process() } } +void QStateMachinePrivate::postInternalEvent(QEvent *e) +{ + QMutexLocker locker(&internalEventMutex); + internalEventQueue.append(e); +} + +void QStateMachinePrivate::postExternalEvent(QEvent *e) +{ + QMutexLocker locker(&externalEventMutex); + externalEventQueue.append(e); +} + +QEvent *QStateMachinePrivate::dequeueInternalEvent() +{ + QMutexLocker locker(&internalEventMutex); + if (internalEventQueue.isEmpty()) + return 0; + return internalEventQueue.takeFirst(); +} + +QEvent *QStateMachinePrivate::dequeueExternalEvent() +{ + QMutexLocker locker(&externalEventMutex); + if (externalEventQueue.isEmpty()) + return 0; + return externalEventQueue.takeFirst(); +} + +bool QStateMachinePrivate::isInternalEventQueueEmpty() +{ + QMutexLocker locker(&internalEventMutex); + return internalEventQueue.isEmpty(); +} + +bool QStateMachinePrivate::isExternalEventQueueEmpty() +{ + QMutexLocker locker(&externalEventMutex); + return externalEventQueue.isEmpty(); +} + void QStateMachinePrivate::processEvents(EventProcessingMode processingMode) { + Q_Q(QStateMachine); if ((state != Running) || processing || processingScheduled) return; switch (processingMode) { case DirectProcessing: - _q_process(); - break; + if (QThread::currentThread() == q->thread()) { + _q_process(); + break; + } // fallthrough -- processing must be done in the machine thread case QueuedProcessing: processingScheduled = true; - QMetaObject::invokeMethod(q_func(), "_q_process", Qt::QueuedConnection); + QMetaObject::invokeMethod(q, "_q_process", Qt::QueuedConnection); break; } } @@ -1296,6 +1337,7 @@ void QStateMachinePrivate::processEvents(EventProcessingMode processingMode) void QStateMachinePrivate::cancelAllDelayedEvents() { Q_Q(QStateMachine); + QMutexLocker locker(&delayedEventsMutex); QHash<int, QEvent*>::const_iterator it; for (it = delayedEvents.constBegin(); it != delayedEvents.constEnd(); ++it) { int id = it.key(); @@ -1547,7 +1589,7 @@ void QStateMachinePrivate::handleFilteredEvent(QObject *watched, QEvent *event) { Q_ASSERT(qobjectEvents.contains(watched)); if (qobjectEvents[watched].contains(event->type())) { - internalEventQueue.append(new QStateMachine::WrappedEvent(watched, handler->cloneEvent(event))); + postInternalEvent(new QStateMachine::WrappedEvent(watched, handler->cloneEvent(event))); processEvents(DirectProcessing); } } @@ -1571,7 +1613,7 @@ void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalInd qDebug() << q_func() << ": sending signal event ( sender =" << sender << ", signal =" << sender->metaObject()->method(signalIndex).signature() << ')'; #endif - internalEventQueue.append(new QStateMachine::SignalEvent(sender, signalIndex, vargs)); + postInternalEvent(new QStateMachine::SignalEvent(sender, signalIndex, vargs)); processEvents(DirectProcessing); } @@ -1825,6 +1867,8 @@ void QStateMachine::stop() } /*! + \threadsafe + Posts the given \a event of the given \a priority for processing by this state machine. @@ -1852,16 +1896,18 @@ void QStateMachine::postEvent(QEvent *event, EventPriority priority) #endif switch (priority) { case NormalPriority: - d->externalEventQueue.append(event); + d->postExternalEvent(event); break; case HighPriority: - d->internalEventQueue.append(event); + d->postInternalEvent(event); break; } d->processEvents(QStateMachinePrivate::QueuedProcessing); } /*! + \threadsafe + Posts the given \a event for processing by this state machine, with the given \a delay in milliseconds. Returns an identifier associated with the delayed event, or -1 if the event could not be posted. @@ -1893,12 +1939,15 @@ int QStateMachine::postDelayedEvent(QEvent *event, int delay) #ifdef QSTATEMACHINE_DEBUG qDebug() << this << ": posting event" << event << "with delay" << delay; #endif + QMutexLocker locker(&d->delayedEventsMutex); int tid = startTimer(delay); d->delayedEvents[tid] = event; return tid; } /*! + \threadsafe + Cancels the delayed event identified by the given \a id. The id should be a value returned by a call to postDelayedEvent(). Returns true if the event was successfully cancelled, otherwise returns false. @@ -1912,6 +1961,7 @@ bool QStateMachine::cancelDelayedEvent(int id) qWarning("QStateMachine::cancelDelayedEvent: the machine is not running"); return false; } + QMutexLocker locker(&d->delayedEventsMutex); QEvent *e = d->delayedEvents.take(id); if (!e) return false; @@ -1921,8 +1971,6 @@ bool QStateMachine::cancelDelayedEvent(int id) } /*! - \internal - Returns the maximal consistent set of states (including parallel and final states) that this state machine is currently in. If a state \c s is in the configuration, it is always the case that the parent of \c s is also in @@ -1963,18 +2011,23 @@ bool QStateMachine::event(QEvent *e) int tid = te->timerId(); if (d->state != QStateMachinePrivate::Running) { // This event has been cancelled already + QMutexLocker locker(&d->delayedEventsMutex); Q_ASSERT(!d->delayedEvents.contains(tid)); return true; } + d->delayedEventsMutex.lock(); QEvent *ee = d->delayedEvents.take(tid); if (ee != 0) { killTimer(tid); - d->externalEventQueue.append(ee); + d->delayedEventsMutex.unlock(); + d->postExternalEvent(ee); d->processEvents(QStateMachinePrivate::DirectProcessing); return true; + } else { + d->delayedEventsMutex.unlock(); } } - return QObject::event(e); + return QState::event(e); } #ifndef QT_NO_STATEMACHINE_EVENTFILTER diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index cf7a073..69b727d 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -58,6 +58,7 @@ #include <QtCore/qcoreevent.h> #include <QtCore/qhash.h> #include <QtCore/qlist.h> +#include <QtCore/qmutex.h> #include <QtCore/qpair.h> #include <QtCore/qset.h> #include <QtCore/qvector.h> @@ -159,6 +160,13 @@ public: void unregisterAllTransitions(); void handleTransitionSignal(QObject *sender, int signalIndex, void **args); + + void postInternalEvent(QEvent *e); + void postExternalEvent(QEvent *e); + QEvent *dequeueInternalEvent(); + QEvent *dequeueExternalEvent(); + bool isInternalEventQueueEmpty(); + bool isExternalEventQueueEmpty(); void processEvents(EventProcessingMode processingMode); void cancelAllDelayedEvents(); @@ -181,6 +189,8 @@ public: QSet<QAbstractState*> configuration; QList<QEvent*> internalEventQueue; QList<QEvent*> externalEventQueue; + QMutex internalEventMutex; + QMutex externalEventMutex; QStateMachine::Error error; QStateMachine::RestorePolicy globalRestorePolicy; @@ -214,6 +224,7 @@ public: QHash<QObject*, QHash<QEvent::Type, int> > qobjectEvents; #endif QHash<int, QEvent*> delayedEvents; + QMutex delayedEventsMutex; typedef QEvent* (*f_cloneEvent)(QEvent*); struct Handler { |