diff base/ById.h @ 1731:601851995f4b by-id

Introduce Model to ById
author Chris Cannam
date Fri, 21 Jun 2019 13:37:00 +0100
parents abd8b9673028
children bffccc8de3c1 d91ff235e69d
line wrap: on
line diff
--- a/base/ById.h	Thu Jun 20 14:57:39 2019 +0100
+++ b/base/ById.h	Fri Jun 21 13:37:00 2019 +0100
@@ -17,31 +17,77 @@
 
 #include <memory>
 #include <map>
+#include <typeinfo>
+#include <iostream>
+#include <climits>
 
 #include <QMutex>
+#include <QString>
 
-typedef int Id;
+template <typename T>
+struct SvId {
+    int id;
 
+    bool operator<(const SvId &other) const { return id < other.id; }
+
+    QString toString() const {
+        return QString("%1").arg(id);
+    }
+};
+
+template <typename T>
 class WithId
 {
 public:
+    typedef SvId<T> Id;
+    
     WithId() :
         m_id(getNextId()) {
     }
 
+    /**
+     * Return an id for this object. The id is a unique identifier for
+     * this object among all objects that implement WithId within this
+     * single run of the application.
+     */
     Id getId() const {
-        return m_id;
+        Id id;
+        id.id = m_id;
+        return id;
     }
 
 private:
-    Id m_id;
-    static int getNextId();
+    int m_id;
+
+    static int getNextId() {
+        static int nextId = 0;
+        static QMutex mutex;
+        QMutexLocker locker(&mutex);
+        int i = nextId;
+        if (nextId == INT_MAX) {
+            nextId = INT_MIN;
+        }
+        ++nextId;
+        return i;
+    }
 };
 
-template <typename Item>
+template <typename Item, typename Id>
 class ById
 {
 public:
+    ~ById() {
+        QMutexLocker locker(&m_mutex);
+        for (const auto &p: m_items) {
+            if (p.second && p.second.use_count() > 0) {
+                std::cerr << "WARNING: ById map destroyed with use count of "
+                          << p.second.use_count() << " for item with type "
+                          << typeid(*p.second.get()).name()
+                          << " and id " << p.first.id << std::endl;
+            }
+        }
+    }
+    
     void add(std::shared_ptr<Item> item) {
         QMutexLocker locker(&m_mutex);
         m_items[item->getId()] = item;
@@ -72,34 +118,36 @@
     mutable QMutex m_mutex;
     std::map<Id, std::shared_ptr<Item>> m_items;
 };
-/*
-class Imagined : public WithId {
-};
 
-class ImaginedById
+template <typename Item, typename Id>
+class StaticById
 {
 public:
-    static void add(std::shared_ptr<Imagined> imagined) {
-        m_byId.add(imagined);
+    static void add(std::shared_ptr<Item> imagined) {
+        byId().add(imagined);
     }
 
     static void release(Id id) {
-        m_byId.release(id);
+        byId().release(id);
     }
 
-    static std::shared_ptr<Imagined> get(Id id) {
-        return m_byId.get(id);
+    static std::shared_ptr<Item> get(Id id) {
+        return byId().get(id);
     }
 
     template <typename Derived>
     static
     std::shared_ptr<Derived> getAs(Id id) {
-        return m_byId.getAs<Derived>(id);
+        return std::dynamic_pointer_cast<Derived>(get(id));
     }
 
 private:
-    static ById<Imagined> m_byId;
+    static
+    ById<Item, Id> &byId() {
+        static ById<Item, Id> b;
+        return b;
+    }
 };
-*/
+
 #endif