Port from implicit to explicit atomic pointer operations

The old code used the implicit conversions from QAtomicPointer<T> to T*
and vice versa. The semantics of these differ from the ones std::atomic
uses, so we're going to deprecate these, like we did for load() and
store(), too.

This patch fixex some users of these APIs before we deprecate them.

Change-Id: I0a88bb1c359392538bb64b511bfc62381a56a468
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2019-06-26 07:56:49 +02:00
parent 282c030785
commit 66223727c7
9 changed files with 38 additions and 38 deletions

View File

@ -519,9 +519,9 @@ static void cleanup()
ffd_atomic_store(&forkfd_status, 0, FFD_ATOMIC_RELAXED); ffd_atomic_store(&forkfd_status, 0, FFD_ATOMIC_RELAXED);
/* free any arrays we might have */ /* free any arrays we might have */
array = children.header.nextArray; array = ffd_atomic_load(&children.header.nextArray, FFD_ATOMIC_ACQUIRE);
while (array != NULL) { while (array != NULL) {
BigArray *next = array->header.nextArray; BigArray *next = ffd_atomic_load(&array->header.nextArray, FFD_ATOMIC_ACQUIRE);
free(array); free(array);
array = next; array = next;
} }

View File

@ -517,7 +517,7 @@ void QProcessPrivate::startProcess()
if (stderrChannel.pipe[0] != -1) if (stderrChannel.pipe[0] != -1)
::fcntl(stderrChannel.pipe[0], F_SETFL, ::fcntl(stderrChannel.pipe[0], F_GETFL) | O_NONBLOCK); ::fcntl(stderrChannel.pipe[0], F_SETFL, ::fcntl(stderrChannel.pipe[0], F_GETFL) | O_NONBLOCK);
if (threadData->eventDispatcher) { if (threadData->eventDispatcher.loadAcquire()) {
deathNotifier = new QSocketNotifier(forkfd, QSocketNotifier::Read, q); deathNotifier = new QSocketNotifier(forkfd, QSocketNotifier::Read, q);
QObject::connect(deathNotifier, SIGNAL(activated(int)), QObject::connect(deathNotifier, SIGNAL(activated(int)),
q, SLOT(_q_processDied())); q, SLOT(_q_processDied()));

View File

@ -385,8 +385,8 @@ struct QCoreApplicationData {
~QCoreApplicationData() { ~QCoreApplicationData() {
#ifndef QT_NO_QOBJECT #ifndef QT_NO_QOBJECT
// cleanup the QAdoptedThread created for the main() thread // cleanup the QAdoptedThread created for the main() thread
if (QCoreApplicationPrivate::theMainThread) { if (auto *t = QCoreApplicationPrivate::theMainThread.loadAcquire()) {
QThreadData *data = QThreadData::get2(QCoreApplicationPrivate::theMainThread); QThreadData *data = QThreadData::get2(t);
data->deref(); // deletes the data and the adopted thread data->deref(); // deletes the data and the adopted thread
} }
#endif #endif
@ -486,7 +486,7 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
#endif #endif
QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread! QThread *cur = QThread::currentThread(); // note: this may end up setting theMainThread!
if (cur != theMainThread) if (cur != theMainThread.loadAcquire())
qWarning("WARNING: QApplication was not created in the main() thread."); qWarning("WARNING: QApplication was not created in the main() thread.");
#endif #endif
} }
@ -862,7 +862,7 @@ void QCoreApplicationPrivate::init()
Q_ASSERT(eventDispatcher); Q_ASSERT(eventDispatcher);
if (!eventDispatcher->parent()) { if (!eventDispatcher->parent()) {
eventDispatcher->moveToThread(threadData->thread); eventDispatcher->moveToThread(threadData->thread.loadAcquire());
eventDispatcher->setParent(q); eventDispatcher->setParent(q);
} }
@ -1181,7 +1181,7 @@ static bool doNotify(QObject *receiver, QEvent *event)
bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event) bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
{ {
// We can't access the application event filters outside of the main thread (race conditions) // We can't access the application event filters outside of the main thread (race conditions)
Q_ASSERT(receiver->d_func()->threadData->thread == mainThread()); Q_ASSERT(receiver->d_func()->threadData->thread.loadAcquire() == mainThread());
if (extraData) { if (extraData) {
// application event filters are only called for objects in the GUI thread // application event filters are only called for objects in the GUI thread
@ -1234,7 +1234,7 @@ bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
// send to all application event filters (only does anything in the main thread) // send to all application event filters (only does anything in the main thread)
if (QCoreApplication::self if (QCoreApplication::self
&& receiver->d_func()->threadData->thread == mainThread() && receiver->d_func()->threadData->thread.loadAcquire() == mainThread()
&& QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) { && QCoreApplication::self->d_func()->sendThroughApplicationEventFilters(receiver, event)) {
filtered = true; filtered = true;
return filtered; return filtered;
@ -2905,7 +2905,7 @@ void QCoreApplication::installNativeEventFilter(QAbstractNativeEventFilter *filt
return; return;
} }
QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(QCoreApplicationPrivate::theMainThread); QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance(QCoreApplicationPrivate::theMainThread.loadAcquire());
if (!filterObj || !eventDispatcher) if (!filterObj || !eventDispatcher)
return; return;
eventDispatcher->installNativeEventFilter(filterObj); eventDispatcher->installNativeEventFilter(filterObj);
@ -2961,7 +2961,7 @@ bool QCoreApplication::hasPendingEvents()
*/ */
QAbstractEventDispatcher *QCoreApplication::eventDispatcher() QAbstractEventDispatcher *QCoreApplication::eventDispatcher()
{ {
if (QCoreApplicationPrivate::theMainThread) if (QCoreApplicationPrivate::theMainThread.loadAcquire())
return QCoreApplicationPrivate::theMainThread.loadRelaxed()->eventDispatcher(); return QCoreApplicationPrivate::theMainThread.loadRelaxed()->eventDispatcher();
return 0; return 0;
} }
@ -2974,7 +2974,7 @@ QAbstractEventDispatcher *QCoreApplication::eventDispatcher()
*/ */
void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher)
{ {
QThread *mainThread = QCoreApplicationPrivate::theMainThread; QThread *mainThread = QCoreApplicationPrivate::theMainThread.loadAcquire();
if (!mainThread) if (!mainThread)
mainThread = QThread::currentThread(); // will also setup theMainThread mainThread = QThread::currentThread(); // will also setup theMainThread
mainThread->setEventDispatcher(eventDispatcher); mainThread->setEventDispatcher(eventDispatcher);

View File

@ -165,7 +165,7 @@ int QEventLoop::exec(ProcessEventsFlags flags)
{ {
Q_D(QEventLoop); Q_D(QEventLoop);
//we need to protect from race condition with QThread::exit //we need to protect from race condition with QThread::exit
QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex); QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread.loadAcquire()))->mutex);
if (d->threadData->quitNow) if (d->threadData->quitNow)
return -1; return -1;

View File

@ -219,7 +219,7 @@ QObjectPrivate::QObjectPrivate(int version)
QObjectPrivate::~QObjectPrivate() QObjectPrivate::~QObjectPrivate()
{ {
if (extraData && !extraData->runningTimers.isEmpty()) { if (extraData && !extraData->runningTimers.isEmpty()) {
if (Q_LIKELY(threadData->thread == QThread::currentThread())) { if (Q_LIKELY(threadData->thread.loadAcquire() == QThread::currentThread())) {
// unregister pending timers // unregister pending timers
if (threadData->hasEventDispatcher()) if (threadData->hasEventDispatcher())
threadData->eventDispatcher.loadRelaxed()->unregisterTimers(q_ptr); threadData->eventDispatcher.loadRelaxed()->unregisterTimers(q_ptr);
@ -493,11 +493,11 @@ bool QObjectPrivate::maybeSignalConnected(uint signalIndex) const
if (!signalVector) if (!signalVector)
return false; return false;
if (signalVector->at(-1).first) if (signalVector->at(-1).first.loadAcquire())
return true; return true;
if (signalIndex < uint(cd->signalVectorCount())) { if (signalIndex < uint(cd->signalVectorCount())) {
const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first; const QObjectPrivate::Connection *c = signalVector->at(signalIndex).first.loadAcquire();
return c != nullptr; return c != nullptr;
} }
return false; return false;
@ -819,8 +819,8 @@ static bool check_parent_thread(QObject *parent,
QThreadData *currentThreadData) QThreadData *currentThreadData)
{ {
if (parent && parentThreadData != currentThreadData) { if (parent && parentThreadData != currentThreadData) {
QThread *parentThread = parentThreadData->thread; QThread *parentThread = parentThreadData->thread.loadAcquire();
QThread *currentThread = currentThreadData->thread; QThread *currentThread = currentThreadData->thread.loadAcquire();
qWarning("QObject: Cannot create children for a parent that is in a different thread.\n" qWarning("QObject: Cannot create children for a parent that is in a different thread.\n"
"(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)", "(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)",
parent->metaObject()->className(), parent->metaObject()->className(),
@ -987,11 +987,11 @@ QObject::~QObject()
QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal); QObjectPrivate::ConnectionList &connectionList = cd->connectionsForSignal(signal);
while (QObjectPrivate::Connection *c = connectionList.first.loadRelaxed()) { while (QObjectPrivate::Connection *c = connectionList.first.loadRelaxed()) {
Q_ASSERT(c->receiver); Q_ASSERT(c->receiver.loadAcquire());
QBasicMutex *m = signalSlotLock(c->receiver.loadRelaxed()); QBasicMutex *m = signalSlotLock(c->receiver.loadRelaxed());
bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m); bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
if (c->receiver) { if (c->receiver.loadAcquire()) {
cd->removeConnection(c); cd->removeConnection(c);
Q_ASSERT(connectionList.first.loadRelaxed() != c); Q_ASSERT(connectionList.first.loadRelaxed() != c);
} }
@ -1003,7 +1003,7 @@ QObject::~QObject()
/* Disconnect all senders: /* Disconnect all senders:
*/ */
while (QObjectPrivate::Connection *node = cd->senders) { while (QObjectPrivate::Connection *node = cd->senders) {
Q_ASSERT(node->receiver); Q_ASSERT(node->receiver.loadAcquire());
QObject *sender = node->sender; QObject *sender = node->sender;
// Send disconnectNotify before removing the connection from sender's connection list. // Send disconnectNotify before removing the connection from sender's connection list.
// This ensures any eventual destructor of sender will block on getting receiver's lock // This ensures any eventual destructor of sender will block on getting receiver's lock
@ -1453,7 +1453,7 @@ bool QObject::blockSignals(bool block) noexcept
*/ */
QThread *QObject::thread() const QThread *QObject::thread() const
{ {
return d_func()->threadData->thread; return d_func()->threadData->thread.loadAcquire();
} }
/*! /*!
@ -1500,7 +1500,7 @@ void QObject::moveToThread(QThread *targetThread)
{ {
Q_D(QObject); Q_D(QObject);
if (d->threadData->thread == targetThread) { if (d->threadData->thread.loadAcquire() == targetThread) {
// object is already in this thread // object is already in this thread
return; return;
} }
@ -1516,7 +1516,7 @@ void QObject::moveToThread(QThread *targetThread)
QThreadData *currentData = QThreadData::current(); QThreadData *currentData = QThreadData::current();
QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : nullptr; QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : nullptr;
if (d->threadData->thread == 0 && currentData == targetData) { if (d->threadData->thread.loadAcquire() == 0 && currentData == targetData) {
// one exception to the rule: we allow moving objects with no thread affinity to the current thread // one exception to the rule: we allow moving objects with no thread affinity to the current thread
currentData = d->threadData; currentData = d->threadData;
} else if (d->threadData != currentData) { } else if (d->threadData != currentData) {
@ -3716,7 +3716,7 @@ void doActivate(QObject *sender, int signal_index, void **argv)
bool senderDeleted = false; bool senderDeleted = false;
{ {
Q_ASSERT(sp->connections); Q_ASSERT(sp->connections.loadAcquire());
QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadRelaxed()); QObjectPrivate::ConnectionDataPointer connections(sp->connections.loadRelaxed());
QObjectPrivate::SignalVector *signalVector = connections->signalVector.loadRelaxed(); QObjectPrivate::SignalVector *signalVector = connections->signalVector.loadRelaxed();
@ -3773,7 +3773,7 @@ void doActivate(QObject *sender, int signal_index, void **argv)
QSemaphore semaphore; QSemaphore semaphore;
{ {
QBasicMutexLocker locker(signalSlotLock(sender)); QBasicMutexLocker locker(signalSlotLock(sender));
if (!c->receiver) if (!c->receiver.loadAcquire())
continue; continue;
QMetaCallEvent *ev = c->isSlotObject ? QMetaCallEvent *ev = c->isSlotObject ?
new QMetaCallEvent(c->slotObj, sender, signal_index, 0, 0, argv, &semaphore) : new QMetaCallEvent(c->slotObj, sender, signal_index, 0, 0, argv, &semaphore) :

View File

@ -312,7 +312,7 @@ public:
} }
} }
int signalVectorCount() const { int signalVectorCount() const {
return signalVector ? signalVector.loadRelaxed()->count() : -1; return signalVector.loadAcquire() ? signalVector.loadRelaxed()->count() : -1;
} }
static void deleteOrphaned(ConnectionOrSignalVector *c); static void deleteOrphaned(ConnectionOrSignalVector *c);

View File

@ -73,8 +73,8 @@ QThreadData::~QThreadData()
// crashing during QCoreApplicationData's global static cleanup we need to // crashing during QCoreApplicationData's global static cleanup we need to
// safeguard the main thread here.. This fix is a bit crude, but it solves // safeguard the main thread here.. This fix is a bit crude, but it solves
// the problem... // the problem...
if (this->thread == QCoreApplicationPrivate::theMainThread) { if (this->thread.loadAcquire() == QCoreApplicationPrivate::theMainThread.loadAcquire()) {
QCoreApplicationPrivate::theMainThread = 0; QCoreApplicationPrivate::theMainThread.storeRelease(nullptr);
QThreadData::clearCurrentThreadData(); QThreadData::clearCurrentThreadData();
} }
@ -85,8 +85,8 @@ QThreadData::~QThreadData()
// because this destructor is still running (the _ref sub-object has not // because this destructor is still running (the _ref sub-object has not
// been destroyed) and there's no reentrancy. The refcount will become // been destroyed) and there's no reentrancy. The refcount will become
// negative, but that's acceptable. // negative, but that's acceptable.
QThread *t = thread; QThread *t = thread.loadAcquire();
thread = 0; thread.storeRelease(nullptr);
delete t; delete t;
for (int i = 0; i < postEventList.size(); ++i) { for (int i = 0; i < postEventList.size(); ++i) {
@ -393,7 +393,7 @@ QThread *QThread::currentThread()
{ {
QThreadData *data = QThreadData::current(); QThreadData *data = QThreadData::current();
Q_ASSERT(data != 0); Q_ASSERT(data != 0);
return data->thread; return data->thread.loadAcquire();
} }
/*! /*!
@ -980,7 +980,7 @@ bool QThread::event(QEvent *event)
void QThread::requestInterruption() void QThread::requestInterruption()
{ {
if (this == QCoreApplicationPrivate::theMainThread) { if (this == QCoreApplicationPrivate::theMainThread.loadAcquire()) {
qWarning("QThread::requestInterruption has no effect on the main thread"); qWarning("QThread::requestInterruption has no effect on the main thread");
return; return;
} }

View File

@ -141,7 +141,7 @@ static void destroy_current_thread_data(void *p)
pthread_setspecific(current_thread_data_key, p); pthread_setspecific(current_thread_data_key, p);
QThreadData *data = static_cast<QThreadData *>(p); QThreadData *data = static_cast<QThreadData *>(p);
if (data->isAdopted) { if (data->isAdopted) {
QThread *thread = data->thread; QThread *thread = data->thread.loadAcquire();
Q_ASSERT(thread); Q_ASSERT(thread);
QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread)); QThreadPrivate *thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
Q_ASSERT(!thread_p->finished); Q_ASSERT(!thread_p->finished);
@ -253,8 +253,8 @@ QThreadData *QThreadData::current(bool createIfNecessary)
data->deref(); data->deref();
data->isAdopted = true; data->isAdopted = true;
data->threadId.storeRelaxed(to_HANDLE(pthread_self())); data->threadId.storeRelaxed(to_HANDLE(pthread_self()));
if (!QCoreApplicationPrivate::theMainThread) if (!QCoreApplicationPrivate::theMainThread.loadAcquire())
QCoreApplicationPrivate::theMainThread = data->thread.loadRelaxed(); QCoreApplicationPrivate::theMainThread.storeRelease(data->thread.loadRelaxed());
} }
return data; return data;
} }
@ -285,7 +285,7 @@ QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *dat
else else
return new QEventDispatcherUNIX; return new QEventDispatcherUNIX;
#elif !defined(QT_NO_GLIB) #elif !defined(QT_NO_GLIB)
const bool isQtMainThread = data->thread == QCoreApplicationPrivate::mainThread(); const bool isQtMainThread = data->thread.loadAcquire() == QCoreApplicationPrivate::mainThread();
if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") if (qEnvironmentVariableIsEmpty("QT_NO_GLIB")
&& (isQtMainThread || qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB")) && (isQtMainThread || qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB"))
&& QEventDispatcherGlib::versionSupported()) && QEventDispatcherGlib::versionSupported())

View File

@ -3666,7 +3666,7 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
// send to all application event filters // send to all application event filters
if (threadRequiresCoreApplication() if (threadRequiresCoreApplication()
&& receiver->d_func()->threadData->thread == mainThread() && receiver->d_func()->threadData->thread.loadAcquire() == mainThread()
&& sendThroughApplicationEventFilters(receiver, e)) { && sendThroughApplicationEventFilters(receiver, e)) {
filtered = true; filtered = true;
return filtered; return filtered;