annotate base/ById.h @ 1735:d91ff235e69d by-id

Some messing with Model and AlignmentModel
author Chris Cannam
date Tue, 25 Jun 2019 15:29:34 +0100
parents 601851995f4b
children d9082ed16931
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@1729 18 #include <memory>
Chris@1729 19 #include <map>
Chris@1731 20 #include <typeinfo>
Chris@1731 21 #include <iostream>
Chris@1731 22 #include <climits>
Chris@1729 23
Chris@1729 24 #include <QMutex>
Chris@1731 25 #include <QString>
Chris@1729 26
Chris@1731 27 template <typename T>
Chris@1731 28 struct SvId {
Chris@1735 29
Chris@1731 30 int id;
Chris@1729 31
Chris@1735 32 enum {
Chris@1735 33 // The value NO_ID (-1) is never allocated by WithId
Chris@1735 34 NO_ID = -1
Chris@1735 35 };
Chris@1735 36
Chris@1735 37 SvId() : id(NO_ID) {}
Chris@1735 38
Chris@1735 39 SvId(const SvId &) =default;
Chris@1735 40 SvId &operator=(const SvId &) =default;
Chris@1735 41
Chris@1735 42 bool operator==(const SvId &other) const { return id == other.id; }
Chris@1731 43 bool operator<(const SvId &other) const { return id < other.id; }
Chris@1731 44
Chris@1735 45 bool isNone() const { return id == NO_ID; }
Chris@1735 46
Chris@1731 47 QString toString() const {
Chris@1731 48 return QString("%1").arg(id);
Chris@1731 49 }
Chris@1731 50 };
Chris@1731 51
Chris@1731 52 template <typename T>
Chris@1729 53 class WithId
Chris@1729 54 {
Chris@1729 55 public:
Chris@1731 56 typedef SvId<T> Id;
Chris@1731 57
Chris@1729 58 WithId() :
Chris@1729 59 m_id(getNextId()) {
Chris@1729 60 }
Chris@1729 61
Chris@1731 62 /**
Chris@1731 63 * Return an id for this object. The id is a unique identifier for
Chris@1731 64 * this object among all objects that implement WithId within this
Chris@1731 65 * single run of the application.
Chris@1731 66 */
Chris@1729 67 Id getId() const {
Chris@1731 68 Id id;
Chris@1731 69 id.id = m_id;
Chris@1731 70 return id;
Chris@1729 71 }
Chris@1729 72
Chris@1729 73 private:
Chris@1731 74 int m_id;
Chris@1731 75
Chris@1731 76 static int getNextId() {
Chris@1731 77 static int nextId = 0;
Chris@1731 78 static QMutex mutex;
Chris@1731 79 QMutexLocker locker(&mutex);
Chris@1731 80 int i = nextId;
Chris@1731 81 if (nextId == INT_MAX) {
Chris@1731 82 nextId = INT_MIN;
Chris@1735 83 } else {
Chris@1735 84 ++nextId;
Chris@1735 85 if (nextId == 0 || nextId == Id::NO_ID) {
Chris@1735 86 throw std::runtime_error("Internal ID limit exceeded!");
Chris@1735 87 }
Chris@1731 88 }
Chris@1731 89 return i;
Chris@1731 90 }
Chris@1729 91 };
Chris@1729 92
Chris@1731 93 template <typename Item, typename Id>
Chris@1729 94 class ById
Chris@1729 95 {
Chris@1729 96 public:
Chris@1731 97 ~ById() {
Chris@1731 98 QMutexLocker locker(&m_mutex);
Chris@1731 99 for (const auto &p: m_items) {
Chris@1731 100 if (p.second && p.second.use_count() > 0) {
Chris@1731 101 std::cerr << "WARNING: ById map destroyed with use count of "
Chris@1731 102 << p.second.use_count() << " for item with type "
Chris@1731 103 << typeid(*p.second.get()).name()
Chris@1731 104 << " and id " << p.first.id << std::endl;
Chris@1731 105 }
Chris@1731 106 }
Chris@1731 107 }
Chris@1731 108
Chris@1729 109 void add(std::shared_ptr<Item> item) {
Chris@1729 110 QMutexLocker locker(&m_mutex);
Chris@1729 111 m_items[item->getId()] = item;
Chris@1729 112 }
Chris@1729 113
Chris@1729 114 void
Chris@1729 115 release(Id id) {
Chris@1729 116 QMutexLocker locker(&m_mutex);
Chris@1729 117 m_items.erase(id);
Chris@1729 118 }
Chris@1729 119
Chris@1729 120 std::shared_ptr<Item> get(Id id) const {
Chris@1729 121 QMutexLocker locker(&m_mutex);
Chris@1729 122 const auto &itr = m_items.find(id);
Chris@1729 123 if (itr != m_items.end()) {
Chris@1729 124 return itr->second;
Chris@1729 125 } else {
Chris@1729 126 return std::shared_ptr<Item>();
Chris@1729 127 }
Chris@1729 128 }
Chris@1729 129
Chris@1729 130 template <typename Derived>
Chris@1729 131 std::shared_ptr<Derived> getAs(Id id) const {
Chris@1729 132 return std::dynamic_pointer_cast<Derived>(get(id));
Chris@1729 133 }
Chris@1729 134
Chris@1729 135 private:
Chris@1729 136 mutable QMutex m_mutex;
Chris@1729 137 std::map<Id, std::shared_ptr<Item>> m_items;
Chris@1729 138 };
Chris@1729 139
Chris@1731 140 template <typename Item, typename Id>
Chris@1731 141 class StaticById
Chris@1729 142 {
Chris@1729 143 public:
Chris@1731 144 static void add(std::shared_ptr<Item> imagined) {
Chris@1731 145 byId().add(imagined);
Chris@1729 146 }
Chris@1729 147
Chris@1729 148 static void release(Id id) {
Chris@1731 149 byId().release(id);
Chris@1729 150 }
Chris@1729 151
Chris@1731 152 static std::shared_ptr<Item> get(Id id) {
Chris@1731 153 return byId().get(id);
Chris@1729 154 }
Chris@1729 155
Chris@1729 156 template <typename Derived>
Chris@1729 157 static
Chris@1729 158 std::shared_ptr<Derived> getAs(Id id) {
Chris@1731 159 return std::dynamic_pointer_cast<Derived>(get(id));
Chris@1729 160 }
Chris@1729 161
Chris@1729 162 private:
Chris@1731 163 static
Chris@1731 164 ById<Item, Id> &byId() {
Chris@1731 165 static ById<Item, Id> b;
Chris@1731 166 return b;
Chris@1731 167 }
Chris@1729 168 };
Chris@1731 169
Chris@1729 170 #endif
Chris@1729 171