Browse Source

ctkDicomObjectLocatorCache - Add "ref count" for cached item

If insert method is called three time with the same uuid, three
invocation of the remove method would be necessary before the cache
entry is removed.
Jean-Christophe Fillion-Robin 14 years ago
parent
commit
9ed8ad40a9

+ 75 - 9
Plugins/org.commontk.dah.core/ctkDicomObjectLocatorCache.cpp

@@ -21,17 +21,32 @@
 // Qt includes
 #include <QHash>
 #include <QUuid>
+#include <QSet>
+#include <QDebug>
 
 // CTK includes
 #include "ctkDicomAppHostingTypes.h"
 #include "ctkDicomObjectLocatorCache.h"
 
+namespace
+{
+struct ObjectLocatorCacheItem
+{
+  ObjectLocatorCacheItem():RefCount(1){}
+  ctkDicomAppHosting::ObjectLocator ObjectLocator;
+  int RefCount;
+};
+}
+
 class ctkDicomObjectLocatorCachePrivate
 {
 public:
   ctkDicomObjectLocatorCachePrivate();
 
-  QHash<QString, ctkDicomAppHosting::ObjectLocator> ObjectLocatorMap;
+  bool find(const QString& objectUuid, ObjectLocatorCacheItem& objectLocatorCacheItem)const;
+
+  QHash<QString, ObjectLocatorCacheItem> ObjectLocatorMap;
+  QSet<QString> TemporaryObjectLocatorSet;
 };
 
 //----------------------------------------------------------------------------
@@ -43,6 +58,18 @@ ctkDicomObjectLocatorCachePrivate::ctkDicomObjectLocatorCachePrivate()
 }
 
 //----------------------------------------------------------------------------
+bool ctkDicomObjectLocatorCachePrivate::find(const QString& objectUuid,
+                                             ObjectLocatorCacheItem& objectLocatorCacheItem)const
+{
+  if (!this->ObjectLocatorMap.contains(objectUuid))
+    {
+    return false;
+    }
+  objectLocatorCacheItem = this->ObjectLocatorMap[objectUuid];
+  return true;
+}
+
+//----------------------------------------------------------------------------
 // ctkDicomObjectLocatorCache methods
 
 //----------------------------------------------------------------------------
@@ -59,10 +86,12 @@ ctkDicomObjectLocatorCache::~ctkDicomObjectLocatorCache()
 bool ctkDicomObjectLocatorCache::isCached(const ctkDicomAppHosting::AvailableData& availableData)const
 {
   Q_D(const ctkDicomObjectLocatorCache);
+  bool hasCachedData = false;
   QList<QString> uuids = d->ObjectLocatorMap.keys();
   // Loop over top level object descriptors
   foreach(const ctkDicomAppHosting::ObjectDescriptor& objectDescriptor, availableData.objectDescriptors)
     {
+    if (!hasCachedData) { hasCachedData = true; }
     if (!uuids.contains(objectDescriptor.descriptorUUID))
       {
       return false;
@@ -74,6 +103,7 @@ bool ctkDicomObjectLocatorCache::isCached(const ctkDicomAppHosting::AvailableDat
     // Loop over patient level object descriptors
     foreach(const ctkDicomAppHosting::ObjectDescriptor& objectDescriptor, patient.objectDescriptors)
       {
+      if (!hasCachedData) { hasCachedData = true; }
       if (!uuids.contains(objectDescriptor.descriptorUUID))
         {
         return false;
@@ -104,40 +134,76 @@ bool ctkDicomObjectLocatorCache::isCached(const ctkDicomAppHosting::AvailableDat
         }
       }
     }
+  return hasCachedData;
 }
 
 //----------------------------------------------------------------------------
 bool ctkDicomObjectLocatorCache::find(const QString& objectUuid,
-                                         ctkDicomAppHosting::ObjectLocator& objectLocator)const
+                                      ctkDicomAppHosting::ObjectLocator& objectLocator)const
 {
   Q_D(const ctkDicomObjectLocatorCache);
-  if (!d->ObjectLocatorMap.contains(objectUuid))
+
+  ObjectLocatorCacheItem item;
+  bool found = d->find(objectUuid, item);
+  if (!found)
     {
     return false;
     }
-  objectLocator = d->ObjectLocatorMap.value(objectUuid);
+  objectLocator = item.ObjectLocator;
   return true;
 }
 
 //----------------------------------------------------------------------------
 void ctkDicomObjectLocatorCache::insert(const QString& objectUuid,
-                                        const ctkDicomAppHosting::ObjectLocator& objectLocator)
+                                        const ctkDicomAppHosting::ObjectLocator& objectLocator,
+                                        bool temporary)
 {
   Q_D(ctkDicomObjectLocatorCache);
+  ObjectLocatorCacheItem item;
+  d->find(objectUuid, item);
   if(d->ObjectLocatorMap.contains(objectUuid))
     {
+    Q_ASSERT(objectLocator == item.ObjectLocator); // ObjectLocator are expected to match
+    item.RefCount++;
+    d->ObjectLocatorMap.insert(objectUuid, item);
     return;
     }
-  d->ObjectLocatorMap.insert(objectUuid, objectLocator);
+  item.ObjectLocator = objectLocator;
+  d->ObjectLocatorMap.insert(objectUuid, item);
+
+  if (temporary)
+    {
+    d->TemporaryObjectLocatorSet.insert(objectUuid);
+    }
 }
 
 //----------------------------------------------------------------------------
 bool ctkDicomObjectLocatorCache::remove(const QString& objectUuid)
 {
   Q_D(ctkDicomObjectLocatorCache);
-  int removed = d->ObjectLocatorMap.remove(objectUuid);
-  Q_ASSERT(removed > 1);
-  return (removed == 1);
+  ObjectLocatorCacheItem item;
+  bool found = d->find(objectUuid, item);
+  if (!found)
+    {
+    return false;
+    }
+  Q_ASSERT(item.RefCount > 0);
+  item.RefCount--;
+  d->ObjectLocatorMap.insert(objectUuid, item);
+  if (item.RefCount == 0)
+    {
+    if (d->TemporaryObjectLocatorSet.contains(objectUuid))
+      {
+      // Not implemented - Delete the object
+      qDebug() << "ctkDicomObjectLocatorCache::remove - RefCount [1] - Temporary [True] - Not implemented";
+
+      bool removed = d->TemporaryObjectLocatorSet.remove(objectUuid);
+      Q_ASSERT(removed);
+      }
+    int removed = d->ObjectLocatorMap.remove(objectUuid);
+    Q_ASSERT(removed == 1);
+    }
+  return true;
 }
 
 //----------------------------------------------------------------------------

+ 2 - 1
Plugins/org.commontk.dah.core/ctkDicomObjectLocatorCache.h

@@ -46,7 +46,8 @@ public:
 
   bool find(const QString& objectUuid, ctkDicomAppHosting::ObjectLocator& objectLocator)const;
 
-  void insert(const QString& objectUuid, const ctkDicomAppHosting::ObjectLocator& objectLocator);
+  void insert(
+    const QString& objectUuid, const ctkDicomAppHosting::ObjectLocator& objectLocator, bool temporary = false);
 
   bool remove(const QString& objectUuid);