changeset 1857:14c776dad920

Make Serialiser cancellable while waiting for its lock
author Chris Cannam
date Thu, 14 May 2020 16:35:39 +0100
parents ecd3152750a5
children 14747f24ad04
files base/Serialiser.cpp base/Serialiser.h
diffstat 2 files changed, 45 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- 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 <iostream>
 
@@ -24,7 +25,12 @@
 Serialiser::m_mutexMap;
 
 Serialiser::Serialiser(QString id) :
-    m_id(id)
+    Serialiser(id, nullptr) { }
+
+Serialiser::Serialiser(QString id, const std::atomic<bool> *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();
 }
--- 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 <QMutex>
 
 #include <map>
+#include <atomic>
 
 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<bool> *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<bool> *m_cancelled;
+    bool m_locked;
     static QMutex m_mapMutex;
     static std::map<QString, QMutex *> m_mutexMap;
 };