summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorDavid Faure <david.faure@kdab.com>2013-03-18 15:19:44 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-03-22 16:44:51 +0100
commitf4609b202208fe592d24c7ae3b4a48ee83045497 (patch)
treec9827efe74688595664c379085ba2a6267e49c13 /src/corelib/kernel
parent85b25fc22176b574865813fa53f7eb2fcbdc89bf (diff)
QThread: fix race when setting the eventDispatcher
Use QAtomicPointer to make this thread-safe. Change-Id: If71f204699fcefabdb59bd26342d777d1cc9e2a7 Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp2
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp19
-rw-r--r--src/corelib/kernel/qeventloop.cpp16
-rw-r--r--src/corelib/kernel/qobject.cpp20
-rw-r--r--src/corelib/kernel/qsocketnotifier.cpp10
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp4
6 files changed, 36 insertions, 35 deletions
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
index c4e02c0347..6558893036 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.cpp
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -172,7 +172,7 @@ QAbstractEventDispatcher::~QAbstractEventDispatcher()
QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
{
QThreadData *data = thread ? QThreadData::get2(thread) : QThreadData::current();
- return data->eventDispatcher;
+ return data->eventDispatcher.load();
}
/*!
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index cce8c30d81..61a8b6a18c 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -689,7 +689,7 @@ void QCoreApplication::init()
#ifndef QT_NO_QOBJECT
// use the event dispatcher created by the app programmer (if any)
if (!QCoreApplicationPrivate::eventDispatcher)
- QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher;
+ QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher.load();
// otherwise we create one
if (!QCoreApplicationPrivate::eventDispatcher)
d->createEventDispatcher();
@@ -1031,9 +1031,9 @@ bool QCoreApplication::closingDown()
void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
{
QThreadData *data = QThreadData::current();
- if (!data->eventDispatcher)
+ if (!data->hasEventDispatcher())
return;
- data->eventDispatcher->processEvents(flags);
+ data->eventDispatcher.load()->processEvents(flags);
}
/*!
@@ -1055,11 +1055,11 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime)
{
QThreadData *data = QThreadData::current();
- if (!data->eventDispatcher)
+ if (!data->hasEventDispatcher())
return;
QElapsedTimer start;
start.start();
- while (data->eventDispatcher->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
+ while (data->eventDispatcher.load()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
if (start.elapsed() > maxtime)
break;
}
@@ -1258,8 +1258,9 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
data->canWait = false;
locker.unlock();
- if (data->eventDispatcher)
- data->eventDispatcher->wakeUp();
+ QAbstractEventDispatcher* dispatcher = data->eventDispatcher.loadAcquire();
+ if (dispatcher)
+ dispatcher->wakeUp();
}
/*!
@@ -1379,8 +1380,8 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
}
--data->postEventList.recursion;
- if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
- data->eventDispatcher->wakeUp();
+ if (!data->postEventList.recursion && !data->canWait && data->hasEventDispatcher())
+ data->eventDispatcher.load()->wakeUp();
// clear the global list, i.e. remove everything that was
// delivered.
diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp
index fe254b5593..549b8db9ca 100644
--- a/src/corelib/kernel/qeventloop.cpp
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -103,7 +103,7 @@ QEventLoop::QEventLoop(QObject *parent)
Q_D(QEventLoop);
if (!QCoreApplication::instance()) {
qWarning("QEventLoop: Cannot be used without QApplication");
- } else if (!d->threadData->eventDispatcher) {
+ } else if (!d->threadData->eventDispatcher.load()) {
QThreadPrivate::createEventDispatcher(d->threadData);
}
}
@@ -131,9 +131,9 @@ QEventLoop::~QEventLoop()
bool QEventLoop::processEvents(ProcessEventsFlags flags)
{
Q_D(QEventLoop);
- if (!d->threadData->eventDispatcher)
+ if (!d->threadData->eventDispatcher.load())
return false;
- return d->threadData->eventDispatcher->processEvents(flags);
+ return d->threadData->eventDispatcher.load()->processEvents(flags);
}
/*!
@@ -234,7 +234,7 @@ int QEventLoop::exec(ProcessEventsFlags flags)
void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
{
Q_D(QEventLoop);
- if (!d->threadData->eventDispatcher)
+ if (!d->threadData->eventDispatcher.load())
return;
QElapsedTimer start;
@@ -263,12 +263,12 @@ void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
void QEventLoop::exit(int returnCode)
{
Q_D(QEventLoop);
- if (!d->threadData->eventDispatcher)
+ if (!d->threadData->eventDispatcher.load())
return;
d->returnCode = returnCode;
d->exit = true;
- d->threadData->eventDispatcher->interrupt();
+ d->threadData->eventDispatcher.load()->interrupt();
}
/*!
@@ -292,9 +292,9 @@ bool QEventLoop::isRunning() const
void QEventLoop::wakeUp()
{
Q_D(QEventLoop);
- if (!d->threadData->eventDispatcher)
+ if (!d->threadData->eventDispatcher.load())
return;
- d->threadData->eventDispatcher->wakeUp();
+ d->threadData->eventDispatcher.load()->wakeUp();
}
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 1312e64d8b..583e580762 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -216,8 +216,8 @@ QObjectPrivate::~QObjectPrivate()
{
if (extraData && !extraData->runningTimers.isEmpty()) {
// unregister pending timers
- if (threadData->eventDispatcher)
- threadData->eventDispatcher->unregisterTimers(q_ptr);
+ if (threadData->eventDispatcher.load())
+ threadData->eventDispatcher.load()->unregisterTimers(q_ptr);
// release the timer ids back to the pool
for (int i = 0; i < extraData->runningTimers.size(); ++i)
@@ -1074,7 +1074,7 @@ bool QObject::event(QEvent *e)
case QEvent::ThreadChange: {
Q_D(QObject);
QThreadData *threadData = d->threadData;
- QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
+ QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.load();
if (eventDispatcher) {
QList<QAbstractEventDispatcher::TimerInfo> timers = eventDispatcher->registeredTimers(this);
if (!timers.isEmpty()) {
@@ -1354,9 +1354,9 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData
++eventsMoved;
}
}
- if (eventsMoved > 0 && targetData->eventDispatcher) {
+ if (eventsMoved > 0 && targetData->eventDispatcher.load()) {
targetData->canWait = false;
- targetData->eventDispatcher->wakeUp();
+ targetData->eventDispatcher.load()->wakeUp();
}
// the current emitting thread shouldn't restore currentSender after calling moveToThread()
@@ -1379,7 +1379,7 @@ void QObjectPrivate::_q_reregisterTimers(void *pointer)
{
Q_Q(QObject);
QList<QAbstractEventDispatcher::TimerInfo> *timerList = reinterpret_cast<QList<QAbstractEventDispatcher::TimerInfo> *>(pointer);
- QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
+ QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher.load();
for (int i = 0; i < timerList->size(); ++i) {
const QAbstractEventDispatcher::TimerInfo &ti = timerList->at(i);
eventDispatcher->registerTimer(ti.timerId, ti.interval, ti.timerType, q);
@@ -1438,11 +1438,11 @@ int QObject::startTimer(int interval, Qt::TimerType timerType)
return 0;
}
- if (!d->threadData->eventDispatcher) {
+ if (!d->threadData->eventDispatcher.load()) {
qWarning("QObject::startTimer: QTimer can only be used with threads started with QThread");
return 0;
}
- int timerId = d->threadData->eventDispatcher->registerTimer(interval, timerType, this);
+ int timerId = d->threadData->eventDispatcher.load()->registerTimer(interval, timerType, this);
if (!d->extraData)
d->extraData = new QObjectPrivate::ExtraData;
d->extraData->runningTimers.append(timerId);
@@ -1472,8 +1472,8 @@ void QObject::killTimer(int id)
return;
}
- if (d->threadData->eventDispatcher)
- d->threadData->eventDispatcher->unregisterTimer(id);
+ if (d->threadData->eventDispatcher.load())
+ d->threadData->eventDispatcher.load()->unregisterTimer(id);
d->extraData->runningTimers.remove(at);
QAbstractEventDispatcherPrivate::releaseTimerId(id);
diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp
index ad687491f1..e0c7f171c3 100644
--- a/src/corelib/kernel/qsocketnotifier.cpp
+++ b/src/corelib/kernel/qsocketnotifier.cpp
@@ -187,10 +187,10 @@ QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent)
d->sntype = type;
d->snenabled = true;
- if (!d->threadData->eventDispatcher) {
+ if (!d->threadData->eventDispatcher.load()) {
qWarning("QSocketNotifier: Can only be used with threads started with QThread");
} else {
- d->threadData->eventDispatcher->registerSocketNotifier(this);
+ d->threadData->eventDispatcher.load()->registerSocketNotifier(this);
}
}
@@ -273,12 +273,12 @@ void QSocketNotifier::setEnabled(bool enable)
return;
d->snenabled = enable;
- if (!d->threadData->eventDispatcher) // perhaps application/thread is shutting down
+ if (!d->threadData->eventDispatcher.load()) // perhaps application/thread is shutting down
return;
if (d->snenabled)
- d->threadData->eventDispatcher->registerSocketNotifier(this);
+ d->threadData->eventDispatcher.load()->registerSocketNotifier(this);
else
- d->threadData->eventDispatcher->unregisterSocketNotifier(this);
+ d->threadData->eventDispatcher.load()->unregisterSocketNotifier(this);
}
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index f24843dc4a..242702b304 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -135,7 +135,7 @@ QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent)
: QObject(*new QWinEventNotifierPrivate(hEvent, false), parent)
{
Q_D(QWinEventNotifier);
- QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher;
+ QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.load();
if (!eventDispatcher) {
qWarning("QWinEventNotifier: Can only be used with threads started with QThread");
} else {
@@ -208,7 +208,7 @@ void QWinEventNotifier::setEnabled(bool enable)
return;
d->enabled = enable;
- QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher;
+ QAbstractEventDispatcher *eventDispatcher = d->threadData->eventDispatcher.load();
if (!eventDispatcher) // perhaps application is shutting down
return;