# HG changeset patch # User Chris Cannam # Date 1589470539 -3600 # Node ID 14c776dad920be139469d3942a3aa9e1d002d81f # Parent ecd3152750a5517f21f8b803701509386243359a Make Serialiser cancellable while waiting for its lock diff -r ecd3152750a5 -r 14c776dad920 base/Serialiser.cpp --- a/base/Serialiser.cpp Thu May 14 16:35:21 2020 +0100 +++ b/base/Serialiser.cpp Thu May 14 16:35:39 2020 +0100 @@ -14,6 +14,7 @@ */ #include "Serialiser.h" +#include "Debug.h" #include @@ -24,7 +25,12 @@ Serialiser::m_mutexMap; Serialiser::Serialiser(QString id) : - m_id(id) + Serialiser(id, nullptr) { } + +Serialiser::Serialiser(QString id, const std::atomic *cancelled) : + m_id(id), + m_cancelled(cancelled), + m_locked(false) { m_mapMutex.lock(); @@ -43,14 +49,27 @@ m_mapMutex.unlock(); - idMutex->lock(); + if (!m_cancelled) { + idMutex->lock(); + m_locked = true; + } else { + // try to lock, polling the cancelled status occasionally + while (!m_locked && ! *m_cancelled) { + m_locked = idMutex->tryLock(500); + if (*m_cancelled) { + SVCERR << "Serialiser: cancelled!" << endl; + } + } + } } Serialiser::~Serialiser() { m_mapMutex.lock(); - - m_mutexMap[m_id]->unlock(); + + if (m_locked) { + m_mutexMap[m_id]->unlock(); + } m_mapMutex.unlock(); } diff -r ecd3152750a5 -r 14c776dad920 base/Serialiser.h --- a/base/Serialiser.h Thu May 14 16:35:21 2020 +0100 +++ b/base/Serialiser.h Thu May 14 16:35:39 2020 +0100 @@ -20,17 +20,39 @@ #include #include +#include class Serialiser { public: + /** + * Construct a serialiser that takes the lock associated with the + * given id. That is, the constructor will only complete after all + * existing serialisers with the given id have been deleted. + */ Serialiser(QString id); + + /** + * Construct a cancellable serialiser that takes the lock + * associated with the given id. That is, the constructor will + * only complete when all existing serialisers with the given id + * have been deleted, or when the (occasionally polled) bool flag + * pointed to by cancelled has been found to be true. + */ + Serialiser(QString id, const std::atomic *cancelled); + + /** + * Release the lock associated with the given id (if taken, rather + * than cancelled). + */ ~Serialiser(); QString getId() const { return m_id; } protected: QString m_id; + const std::atomic *m_cancelled; + bool m_locked; static QMutex m_mapMutex; static std::map m_mutexMap; };