Synchronize with possible concurrent writers to the NvComputer object

This commit is contained in:
Cameron Gutman 2023-10-01 17:46:27 -05:00
parent 0976bc39b3
commit 49e0679864
3 changed files with 8 additions and 2 deletions

View file

@ -257,6 +257,7 @@ void DelayedFlushThread::run() {
for (const NvComputer* computer : m_ComputerManager->m_KnownHosts) { for (const NvComputer* computer : m_ComputerManager->m_KnownHosts) {
// Copy the current state of the NvComputer to allow us to check later if we need // Copy the current state of the NvComputer to allow us to check later if we need
// to serialize it again when attribute updates occur. // to serialize it again when attribute updates occur.
QReadLocker computerLock(&computer->lock);
m_ComputerManager->m_LastSerializedHosts[computer->uuid] = *computer; m_ComputerManager->m_LastSerializedHosts[computer->uuid] = *computer;
} }
} }
@ -446,8 +447,10 @@ void ComputerManager::saveHost(NvComputer *computer)
{ {
// If no serializable properties changed, don't bother saving hosts // If no serializable properties changed, don't bother saving hosts
QMutexLocker lock(&m_DelayedFlushMutex); QMutexLocker lock(&m_DelayedFlushMutex);
QReadLocker computerLock(&computer->lock);
if (!m_LastSerializedHosts.value(computer->uuid).isEqualSerialized(*computer)) { if (!m_LastSerializedHosts.value(computer->uuid).isEqualSerialized(*computer)) {
// Queue a request for a delayed flush to QSettings outside of the lock // Queue a request for a delayed flush to QSettings outside of the lock
computerLock.unlock();
lock.unlock(); lock.unlock();
saveHosts(); saveHosts();
} }

View file

@ -267,7 +267,7 @@ private:
QVector<MdnsPendingComputer*> m_PendingResolution; QVector<MdnsPendingComputer*> m_PendingResolution;
CompatFetcher m_CompatFetcher; CompatFetcher m_CompatFetcher;
DelayedFlushThread* m_DelayedFlushThread; DelayedFlushThread* m_DelayedFlushThread;
QMutex m_DelayedFlushMutex; QMutex m_DelayedFlushMutex; // Lock ordering: Must never be acquired while holding NvComputer lock
QWaitCondition m_DelayedFlushCondition; QWaitCondition m_DelayedFlushCondition;
bool m_NeedsDelayedFlush; bool m_NeedsDelayedFlush;
}; };

View file

@ -34,8 +34,10 @@ private:
public: public:
NvComputer() = default; NvComputer() = default;
NvComputer(const NvComputer& other) = default; // Caller is responsible for synchronizing read access to the other host
NvComputer(const NvComputer&) = default;
// Caller is responsible for synchronizing read access to the other host
NvComputer& operator=(const NvComputer &) = default; NvComputer& operator=(const NvComputer &) = default;
explicit NvComputer(NvHTTP& http, QString serverInfo); explicit NvComputer(NvHTTP& http, QString serverInfo);
@ -67,6 +69,7 @@ public:
void void
serialize(QSettings& settings, bool serializeApps) const; serialize(QSettings& settings, bool serializeApps) const;
// Caller is responsible for synchronizing read access to both hosts
bool bool
isEqualSerialized(const NvComputer& that) const; isEqualSerialized(const NvComputer& that) const;