From fda8eb17417e92f8f80587937463be77899c7bed Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 25 May 2022 21:32:53 +0200 Subject: Optimize QThreadPrivate::addObjectWithPendingBindingStatusChange() ... and bindingStatus() QBindingStatus* is the final state of the value chain in m_statusOrPendingObjects, so we can use the Double-Checked Locking Pattern to avoid locking the mutex when we already have a status - it won't go away again, unlike the vector in the List state. To enable the change, make the data member an atomic<>. All loads and stores can continue to use memory_order::relaxed, except the loads of a potential status, which have to acquire, and the store of the status, which has to release. This creates the necessary synchronizes-with relation. So even though we synchronize out of middle of the mutex critical section in QThread::exec() this way, there's no data race between QThread::exec() and a potential bindingStatus() call. Change-Id: I0e0b7bd305649fa5f56a0f8723fb75f2577b90dd Reviewed-by: Thiago Macieira --- src/corelib/thread/qthread.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/corelib/thread/qthread.cpp') diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index d067bd06d3..208420b8fe 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -519,7 +519,8 @@ void QtPrivate::BindingStatusOrList::setStatusAndClearList(QBindingStatus *statu QObjectPrivate::get(obj)->reinitBindingStorageAfterThreadMove(); delete pendingObjects; } - data = encodeBindingStatus(status); + // synchronizes-with the load-acquire in bindingStatus(): + data.store(encodeBindingStatus(status), std::memory_order_release); } /*! @@ -568,14 +569,13 @@ int QThread::exec() */ QBindingStatus *QtPrivate::BindingStatusOrList::addObjectUnlessAlreadyStatus(QObject *object) { - if (auto status = bindingStatus()) return status; List *objectList = list(); if (!objectList) { objectList = new List(); objectList->reserve(8); - data = encodeList(objectList); + data.store(encodeList(objectList), std::memory_order_relaxed); } objectList->push_back(object); return nullptr; @@ -583,6 +583,8 @@ QBindingStatus *QtPrivate::BindingStatusOrList::addObjectUnlessAlreadyStatus(QOb QBindingStatus *QThreadPrivate::addObjectWithPendingBindingStatusChange(QObject *obj) { + if (auto status = m_statusOrPendingObjects.bindingStatus()) + return status; QMutexLocker lock(&mutex); return m_statusOrPendingObjects.addObjectUnlessAlreadyStatus(obj); } -- cgit v1.2.3