annotate base/ById.h @ 1736:d9082ed16931 by-id

Merge
author Chris Cannam
date Tue, 25 Jun 2019 15:29:45 +0100
parents d91ff235e69d bffccc8de3c1
children 4abc0f08adf9
rev   line source
Chris@1729 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@1729 2
Chris@1729 3 /*
Chris@1729 4 Sonic Visualiser
Chris@1729 5 An audio file viewer and annotation editor.
Chris@1729 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1729 7
Chris@1729 8 This program is free software; you can redistribute it and/or
Chris@1729 9 modify it under the terms of the GNU General Public License as
Chris@1729 10 published by the Free Software Foundation; either version 2 of the
Chris@1729 11 License, or (at your option) any later version. See the file
Chris@1729 12 COPYING included with this distribution for more information.
Chris@1729 13 */
Chris@1729 14
Chris@1729 15 #ifndef SV_BY_ID_H
Chris@1729 16 #define SV_BY_ID_H
Chris@1729 17
Chris@1734 18 #include "Debug.h"
Chris@1734 19
Chris@1729 20 #include <memory>
Chris@1729 21 #include <map>
Chris@1731 22 #include <typeinfo>
Chris@1731 23 #include <iostream>
Chris@1731 24 #include <climits>
Chris@1729 25
Chris@1729 26 #include <QMutex>
Chris@1731 27 #include <QString>
Chris@1729 28
Chris@1731 29 template <typename T>
Chris@1731 30 struct SvId {
Chris@1735 31
Chris@1731 32 int id;
Chris@1729 33
Chris@1735 34 enum {
Chris@1735 35 // The value NO_ID (-1) is never allocated by WithId
Chris@1735 36 NO_ID = -1
Chris@1735 37 };
Chris@1735 38
Chris@1735 39 SvId() : id(NO_ID) {}
Chris@1735 40
Chris@1735 41 SvId(const SvId &) =default;
Chris@1735 42 SvId &operator=(const SvId &) =default;
Chris@1735 43
Chris@1735 44 bool operator==(const SvId &other) const { return id == other.id; }
Chris@1731 45 bool operator<(const SvId &other) const { return id < other.id; }
Chris@1731 46
Chris@1735 47 bool isNone() const { return id == NO_ID; }
Chris@1735 48
Chris@1731 49 QString toString() const {
Chris@1731 50 return QString("%1").arg(id);
Chris@1731 51 }
Chris@1731 52 };
Chris@1731 53
Chris@1731 54 template <typename T>
Chris@1729 55 class WithId
Chris@1729 56 {
Chris@1729 57 public:
Chris@1731 58 typedef SvId<T> Id;
Chris@1731 59
Chris@1729 60 WithId() :
Chris@1729 61 m_id(getNextId()) {
Chris@1729 62 }
Chris@1729 63
Chris@1731 64 /**
Chris@1731 65 * Return an id for this object. The id is a unique identifier for
Chris@1731 66 * this object among all objects that implement WithId within this
Chris@1731 67 * single run of the application.
Chris@1731 68 */
Chris@1729 69 Id getId() const {
Chris@1731 70 Id id;
Chris@1731 71 id.id = m_id;
Chris@1731 72 return id;
Chris@1729 73 }
Chris@1729 74
Chris@1729 75 private:
Chris@1731 76 int m_id;
Chris@1731 77
Chris@1731 78 static int getNextId() {
Chris@1731 79 static int nextId = 0;
Chris@1731 80 static QMutex mutex;
Chris@1731 81 QMutexLocker locker(&mutex);
Chris@1731 82 int i = nextId;
Chris@1731 83 if (nextId == INT_MAX) {
Chris@1731 84 nextId = INT_MIN;
Chris@1735 85 } else {
Chris@1735 86 ++nextId;
Chris@1735 87 if (nextId == 0 || nextId == Id::NO_ID) {
Chris@1735 88 throw std::runtime_error("Internal ID limit exceeded!");
Chris@1735 89 }
Chris@1731 90 }
Chris@1731 91 return i;
Chris@1731 92 }
Chris@1729 93 };
Chris@1729 94
Chris@1731 95 template <typename Item, typename Id>
Chris@1729 96 class ById
Chris@1729 97 {
Chris@1729 98 public:
Chris@1731 99 ~ById() {
Chris@1731 100 QMutexLocker locker(&m_mutex);
Chris@1731 101 for (const auto &p: m_items) {
Chris@1731 102 if (p.second && p.second.use_count() > 0) {
Chris@1734 103 SVCERR << "WARNING: ById map destroyed with use count of "
Chris@1734 104 << p.second.use_count() << " for item with type "
Chris@1734 105 << typeid(*p.second.get()).name()
Chris@1734 106 << " and id " << p.first.id << endl;
Chris@1731 107 }
Chris@1731 108 }
Chris@1731 109 }
Chris@1731 110
Chris@1729 111 void add(std::shared_ptr<Item> item) {
Chris@1729 112 QMutexLocker locker(&m_mutex);
Chris@1734 113 auto id = item->getId();
Chris@1734 114 if (m_items.find(id) != m_items.end()) {
Chris@1734 115 SVCERR << "WARNING: ById::add: item with id " << id
Chris@1734 116 << " is already recorded, replacing it (item type is "
Chris@1734 117 << typeid(*item.get()).name() << ")" << endl;
Chris@1734 118 }
Chris@1734 119 m_items[id] = item;
Chris@1729 120 }
Chris@1729 121
Chris@1729 122 void
Chris@1729 123 release(Id id) {
Chris@1729 124 QMutexLocker locker(&m_mutex);
Chris@1729 125 m_items.erase(id);
Chris@1729 126 }
Chris@1729 127
Chris@1729 128 std::shared_ptr<Item> get(Id id) const {
Chris@1729 129 QMutexLocker locker(&m_mutex);
Chris@1729 130 const auto &itr = m_items.find(id);
Chris@1729 131 if (itr != m_items.end()) {
Chris@1729 132 return itr->second;
Chris@1729 133 } else {
Chris@1729 134 return std::shared_ptr<Item>();
Chris@1729 135 }
Chris@1729 136 }
Chris@1729 137
Chris@1729 138 template <typename Derived>
Chris@1729 139 std::shared_ptr<Derived> getAs(Id id) const {
Chris@1729 140 return std::dynamic_pointer_cast<Derived>(get(id));
Chris@1729 141 }
Chris@1729 142
Chris@1729 143 private:
Chris@1729 144 mutable QMutex m_mutex;
Chris@1729 145 std::map<Id, std::shared_ptr<Item>> m_items;
Chris@1729 146 };
Chris@1729 147
Chris@1731 148 template <typename Item, typename Id>
Chris@1731 149 class StaticById
Chris@1729 150 {
Chris@1729 151 public:
Chris@1731 152 static void add(std::shared_ptr<Item> imagined) {
Chris@1731 153 byId().add(imagined);
Chris@1729 154 }
Chris@1729 155
Chris@1729 156 static void release(Id id) {
Chris@1731 157 byId().release(id);
Chris@1729 158 }
Chris@1729 159
Chris@1731 160 static std::shared_ptr<Item> get(Id id) {
Chris@1731 161 return byId().get(id);
Chris@1729 162 }
Chris@1729 163
Chris@1729 164 template <typename Derived>
Chris@1729 165 static
Chris@1729 166 std::shared_ptr<Derived> getAs(Id id) {
Chris@1731 167 return std::dynamic_pointer_cast<Derived>(get(id));
Chris@1729 168 }
Chris@1729 169
Chris@1729 170 private:
Chris@1731 171 static
Chris@1731 172 ById<Item, Id> &byId() {
Chris@1731 173 static ById<Item, Id> b;
Chris@1731 174 return b;
Chris@1731 175 }
Chris@1729 176 };
Chris@1731 177
Chris@1729 178 #endif
Chris@1729 179