summaryrefslogtreecommitdiffstats
path: root/src/corelib/statemachine
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/statemachine')
-rw-r--r--src/corelib/statemachine/qabstractstate.cpp15
-rw-r--r--src/corelib/statemachine/qabstractstate_p.h14
-rw-r--r--src/corelib/statemachine/qfinalstate.cpp1
-rw-r--r--src/corelib/statemachine/qhistorystate.cpp3
-rw-r--r--src/corelib/statemachine/qstate.cpp28
-rw-r--r--src/corelib/statemachine/qstate_p.h2
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp161
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h18
8 files changed, 187 insertions, 55 deletions
diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp
index 72d640b..ec5332f 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(StateType type)
+ : stateType(type), isMachine(false), parentState(0)
{
}
@@ -87,6 +88,11 @@ QAbstractStatePrivate *QAbstractStatePrivate::get(QAbstractState *q)
return q->d_func();
}
+const QAbstractStatePrivate *QAbstractStatePrivate::get(const QAbstractState *q)
+{
+ return q->d_func();
+}
+
QStateMachine *QAbstractStatePrivate::machine() const
{
QObject *par = parent;
@@ -126,7 +132,7 @@ void QAbstractStatePrivate::emitExited()
Constructs a new state with the given \a parent state.
*/
QAbstractState::QAbstractState(QState *parent)
- : QObject(*new QAbstractStatePrivate, parent)
+ : QObject(*new QAbstractStatePrivate(QAbstractStatePrivate::AbstractState), parent)
{
}
@@ -150,7 +156,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..faea6b6 100644
--- a/src/corelib/statemachine/qabstractstate_p.h
+++ b/src/corelib/statemachine/qabstractstate_p.h
@@ -65,9 +65,17 @@ class QAbstractStatePrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QAbstractState)
public:
- QAbstractStatePrivate();
+ enum StateType {
+ AbstractState,
+ StandardState,
+ FinalState,
+ HistoryState
+ };
+
+ QAbstractStatePrivate(StateType type);
static QAbstractStatePrivate *get(QAbstractState *q);
+ static const QAbstractStatePrivate *get(const QAbstractState *q);
QStateMachine *machine() const;
@@ -76,6 +84,10 @@ public:
void emitEntered();
void emitExited();
+
+ uint stateType:31;
+ uint isMachine:1;
+ mutable QState *parentState;
};
QT_END_NAMESPACE
diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp
index 761eee4..d900ddd 100644
--- a/src/corelib/statemachine/qfinalstate.cpp
+++ b/src/corelib/statemachine/qfinalstate.cpp
@@ -92,6 +92,7 @@ public:
};
QFinalStatePrivate::QFinalStatePrivate()
+ : QAbstractStatePrivate(FinalState)
{
}
diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp
index 0c2b858..18436d3 100644
--- a/src/corelib/statemachine/qhistorystate.cpp
+++ b/src/corelib/statemachine/qhistorystate.cpp
@@ -120,7 +120,8 @@ QT_BEGIN_NAMESPACE
*/
QHistoryStatePrivate::QHistoryStatePrivate()
- : defaultState(0), historyType(QHistoryState::ShallowHistory)
+ : QAbstractStatePrivate(HistoryState),
+ defaultState(0), historyType(QHistoryState::ShallowHistory)
{
}
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
index 9abf20b..5dc310b 100644
--- a/src/corelib/statemachine/qstate.cpp
+++ b/src/corelib/statemachine/qstate.cpp
@@ -124,8 +124,9 @@ QT_BEGIN_NAMESPACE
*/
QStatePrivate::QStatePrivate()
- : errorState(0), initialState(0), childMode(QState::ExclusiveStates),
- transitionsListNeedsRefresh(true)
+ : QAbstractStatePrivate(StandardState),
+ errorState(0), initialState(0), childMode(QState::ExclusiveStates),
+ childStatesListNeedsRefresh(true), transitionsListNeedsRefresh(true)
{
}
@@ -181,15 +182,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
@@ -473,8 +477,10 @@ void QState::setChildMode(ChildMode mode)
bool QState::event(QEvent *e)
{
Q_D(QState);
- if ((e->type() == QEvent::ChildAdded) || (e->type() == QEvent::ChildRemoved))
+ 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 3b5f416..34c8838 100644
--- a/src/corelib/statemachine/qstate_p.h
+++ b/src/corelib/statemachine/qstate_p.h
@@ -99,6 +99,8 @@ public:
QAbstractState *errorState;
QAbstractState *initialState;
QState::ChildMode childMode;
+ mutable bool childStatesListNeedsRefresh;
+ mutable QList<QAbstractState*> childStatesList;
mutable bool transitionsListNeedsRefresh;
mutable QList<QAbstractTransition*> transitionsList;
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index e182c88..ea5587e 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -178,6 +178,8 @@ QT_BEGIN_NAMESPACE
QStateMachinePrivate::QStateMachinePrivate()
{
+ QAbstractStatePrivate::isMachine = true;
+
state = NotRunning;
_startState = 0;
processing = false;
@@ -336,7 +338,7 @@ QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event
if (isPreempted(state, enabledTransitions))
continue;
QList<QState*> lst = properAncestors(state, rootState()->parentState());
- if (QState *grp = qobject_cast<QState*>(state))
+ if (QState *grp = toStandardState(state))
lst.prepend(grp);
bool found = false;
for (int j = 0; (j < lst.size()) && !found; ++j) {
@@ -414,7 +416,7 @@ QList<QAbstractState*> QStateMachinePrivate::exitStates(QEvent *event, const QLi
qSort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
for (int i = 0; i < statesToExit_sorted.size(); ++i) {
QAbstractState *s = statesToExit_sorted.at(i);
- if (QState *grp = qobject_cast<QState*>(s)) {
+ if (QState *grp = toStandardState(s)) {
QList<QHistoryState*> hlst = QStatePrivate::get(grp)->historyStates();
for (int j = 0; j < hlst.size(); ++j) {
QHistoryState *h = hlst.at(j);
@@ -563,7 +565,7 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root,
QSet<QAbstractState*> &statesToEnter,
QSet<QAbstractState*> &statesForDefaultEntry)
{
- if (QHistoryState *h = qobject_cast<QHistoryState*>(s)) {
+ if (QHistoryState *h = toHistoryState(s)) {
QList<QAbstractState*> hconf = QHistoryStatePrivate::get(h)->configuration;
if (!hconf.isEmpty()) {
for (int k = 0; k < hconf.size(); ++k) {
@@ -600,7 +602,7 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root,
}
statesToEnter.insert(s);
if (isParallel(s)) {
- QState *grp = qobject_cast<QState*>(s);
+ QState *grp = toStandardState(s);
QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
for (int i = 0; i < lst.size(); ++i) {
QAbstractState *child = lst.at(i);
@@ -608,7 +610,7 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root,
}
} else if (isCompound(s)) {
statesForDefaultEntry.insert(s);
- QState *grp = qobject_cast<QState*>(s);
+ QState *grp = toStandardState(s);
QAbstractState *initial = grp->initialState();
if (initial != 0) {
Q_ASSERT(initial->machine() == q_func());
@@ -660,7 +662,7 @@ void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &tr
QHash<QAbstractState*, QList<QPropertyAssignment> > propertyAssignmentsForState;
QHash<RestorableId, QVariant> pendingRestorables = registeredRestorables;
for (int i = 0; i < enteredStates.size(); ++i) {
- QState *s = qobject_cast<QState*>(enteredStates.at(i));
+ QState *s = toStandardState(enteredStates.at(i));
if (!s)
continue;
@@ -831,7 +833,7 @@ void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &tr
// Emit polished signal for entered states that have no animated properties.
for (int i = 0; i < enteredStates.size(); ++i) {
- QState *s = qobject_cast<QState*>(enteredStates.at(i));
+ QState *s = toStandardState(enteredStates.at(i));
if (s
#ifndef QT_NO_ANIMATION
&& !animationsForState.contains(s)
@@ -845,21 +847,21 @@ void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &tr
bool QStateMachinePrivate::isFinal(const QAbstractState *s)
{
- return qobject_cast<const QFinalState*>(s) != 0;
+ return s && (QAbstractStatePrivate::get(s)->stateType == QAbstractStatePrivate::FinalState);
}
bool QStateMachinePrivate::isParallel(const QAbstractState *s)
{
- const QState *ss = qobject_cast<const QState*>(s);
+ const QState *ss = toStandardState(s);
return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates);
}
bool QStateMachinePrivate::isCompound(const QAbstractState *s) const
{
- const QState *group = qobject_cast<const QState*>(s);
+ const QState *group = toStandardState(s);
if (!group)
return false;
- bool isMachine = (qobject_cast<const QStateMachine*>(group) != 0);
+ bool isMachine = QStatePrivate::get(group)->isMachine;
// Don't treat the machine as compound if it's a sub-state of this machine
if (isMachine && (group != rootState()))
return false;
@@ -869,11 +871,11 @@ bool QStateMachinePrivate::isCompound(const QAbstractState *s) const
bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const
{
- const QState *ss = qobject_cast<const QState*>(s);
+ const QState *ss = toStandardState(s);
return (ss && QStatePrivate::get(ss)->childStates().isEmpty())
|| isFinal(s)
// Treat the machine as atomic if it's a sub-state of this machine
- || (ss && (qobject_cast<const QStateMachine*>(ss) != 0) && (ss != rootState()));
+ || (ss && QStatePrivate::get(ss)->isMachine && (ss != rootState()));
}
@@ -897,10 +899,38 @@ QList<QState*> QStateMachinePrivate::properAncestors(const QAbstractState *state
return result;
}
+QState *QStateMachinePrivate::toStandardState(QAbstractState *state)
+{
+ if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState))
+ return static_cast<QState*>(state);
+ return 0;
+}
+
+const QState *QStateMachinePrivate::toStandardState(const QAbstractState *state)
+{
+ if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState))
+ return static_cast<const QState*>(state);
+ return 0;
+}
+
+QFinalState *QStateMachinePrivate::toFinalState(QAbstractState *state)
+{
+ if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::FinalState))
+ return static_cast<QFinalState*>(state);
+ return 0;
+}
+
+QHistoryState *QStateMachinePrivate::toHistoryState(QAbstractState *state)
+{
+ if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::HistoryState))
+ return static_cast<QHistoryState*>(state);
+ return 0;
+}
+
bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const
{
if (isCompound(s)) {
- QState *grp = qobject_cast<QState*>(s);
+ QState *grp = toStandardState(s);
QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
for (int i = 0; i < lst.size(); ++i) {
QAbstractState *cs = lst.at(i);
@@ -909,7 +939,7 @@ bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const
}
return false;
} else if (isParallel(s)) {
- QState *grp = qobject_cast<QState*>(s);
+ QState *grp = toStandardState(s);
QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
for (int i = 0; i < lst.size(); ++i) {
QAbstractState *cs = lst.at(i);
@@ -975,7 +1005,7 @@ QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context)
// Find error state recursively in parent hierarchy if not set explicitly for context state
QAbstractState *errorState = 0;
if (context != 0) {
- QState *s = qobject_cast<QState*>(context);
+ QState *s = toStandardState(context);
if (s != 0)
errorState = s->errorState();
@@ -1100,7 +1130,7 @@ void QStateMachinePrivate::_q_animationFinished()
animations.removeOne(anim);
if (animations.isEmpty()) {
animationsForState.erase(it);
- QStatePrivate::get(qobject_cast<QState*>(state))->emitPolished();
+ QStatePrivate::get(toStandardState(state))->emitPolished();
}
}
@@ -1216,8 +1246,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 +1257,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 +1266,11 @@ void QStateMachinePrivate::_q_process()
delete e;
e = 0;
}
+ } else {
+ if (isInternalEventQueueEmpty()) {
+ processing = false;
+ stopProcessingReason = EventQueueEmpty;
+ }
}
}
if (!enabledTransitions.isEmpty()) {
@@ -1278,17 +1306,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 +1367,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();
@@ -1346,7 +1418,7 @@ void QStateMachinePrivate::goToState(QAbstractState *targetState)
if (state == Running) {
QSet<QAbstractState*>::const_iterator it;
for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
- sourceState = qobject_cast<QState*>(*it);
+ sourceState = toStandardState(*it);
if (sourceState != 0)
break;
}
@@ -1370,7 +1442,7 @@ void QStateMachinePrivate::goToState(QAbstractState *targetState)
void QStateMachinePrivate::registerTransitions(QAbstractState *state)
{
- QState *group = qobject_cast<QState*>(state);
+ QState *group = toStandardState(state);
if (!group)
return;
QList<QAbstractTransition*> transitions = QStatePrivate::get(group)->transitions();
@@ -1547,7 +1619,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 +1643,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 +1897,8 @@ void QStateMachine::stop()
}
/*!
+ \threadsafe
+
Posts the given \a event of the given \a priority for processing by this
state machine.
@@ -1852,16 +1926,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 +1969,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 +1991,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 +2001,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 +2041,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..01c9361 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>
@@ -72,6 +73,8 @@ class QSignalEventGenerator;
class QSignalTransition;
class QAbstractState;
class QAbstractTransition;
+class QFinalState;
+class QHistoryState;
class QState;
#ifndef QT_NO_ANIMATION
@@ -137,6 +140,11 @@ public:
const QList<QAbstractState*> &exitedStates,
const QList<QAbstractState*> &enteredStates);
+ static QState *toStandardState(QAbstractState *state);
+ static const QState *toStandardState(const QAbstractState *state);
+ static QFinalState *toFinalState(QAbstractState *state);
+ static QHistoryState *toHistoryState(QAbstractState *state);
+
bool isInFinalState(QAbstractState *s) const;
static bool isFinal(const QAbstractState *s);
static bool isParallel(const QAbstractState *s);
@@ -159,6 +167,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 +196,8 @@ public:
QSet<QAbstractState*> configuration;
QList<QEvent*> internalEventQueue;
QList<QEvent*> externalEventQueue;
+ QMutex internalEventMutex;
+ QMutex externalEventMutex;
QStateMachine::Error error;
QStateMachine::RestorePolicy globalRestorePolicy;
@@ -214,6 +231,7 @@ public:
QHash<QObject*, QHash<QEvent::Type, int> > qobjectEvents;
#endif
QHash<int, QEvent*> delayedEvents;
+ QMutex delayedEventsMutex;
typedef QEvent* (*f_cloneEvent)(QEvent*);
struct Handler {