Mercurial > hg > svcore
comparison base/ById.cpp @ 1742:52705a328b34 by-id
Rejig ById so as to put everything in a single pool, so that at the core you can go from numeric id (untyped) to anything the object can be dynamic_cast to. Useful for building other abstractions like PlayParameter-type registrations that don't know about e.g. Models. Probably some more tweaking needed. Also add tests
author | Chris Cannam |
---|---|
date | Fri, 28 Jun 2019 17:36:30 +0100 |
parents | |
children | b92bdcd4954b |
comparison
equal
deleted
inserted
replaced
1741:9d82b164f264 | 1742:52705a328b34 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 | |
8 This program is free software; you can redistribute it and/or | |
9 modify it under the terms of the GNU General Public License as | |
10 published by the Free Software Foundation; either version 2 of the | |
11 License, or (at your option) any later version. See the file | |
12 COPYING included with this distribution for more information. | |
13 */ | |
14 | |
15 #include "ById.h" | |
16 | |
17 #include <unordered_map> | |
18 #include <typeinfo> | |
19 | |
20 int IdAlloc::getNextId() | |
21 { | |
22 static int nextId = 0; | |
23 static QMutex mutex; | |
24 QMutexLocker locker(&mutex); | |
25 int i = nextId; | |
26 if (nextId == INT_MAX) { | |
27 nextId = INT_MIN; | |
28 } else { | |
29 ++nextId; | |
30 if (nextId == 0 || nextId == NO_ID) { | |
31 throw std::runtime_error("Internal ID limit exceeded!"); | |
32 } | |
33 } | |
34 return i; | |
35 } | |
36 | |
37 class AnyById::Impl | |
38 { | |
39 public: | |
40 ~Impl() { | |
41 QMutexLocker locker(&m_mutex); | |
42 bool empty = true; | |
43 for (const auto &p: m_items) { | |
44 if (p.second && p.second.use_count() > 0) { | |
45 empty = false; | |
46 break; | |
47 } | |
48 } | |
49 if (!empty) { | |
50 SVCERR << "WARNING: ById map is not empty at close; some items have not been released" << endl; | |
51 SVCERR << " Unreleased items are:" << endl; | |
52 for (const auto &p: m_items) { | |
53 if (p.second && p.second.use_count() > 0) { | |
54 SVCERR << " - id #" << p.first | |
55 << ": type " << typeid(*p.second.get()).name() | |
56 << ", use count " << p.second.use_count() << endl; | |
57 } | |
58 } | |
59 } | |
60 } | |
61 | |
62 void add(int id, std::shared_ptr<WithId> item) { | |
63 QMutexLocker locker(&m_mutex); | |
64 if (m_items.find(id) != m_items.end()) { | |
65 SVCERR << "ById::add: item with id " << id | |
66 << " is already recorded (existing item type is " | |
67 << typeid(*m_items.find(id)->second.get()).name() | |
68 << ", proposed is " | |
69 << typeid(*item.get()).name() << ")" << endl; | |
70 throw std::logic_error("item id is already recorded in add"); | |
71 } | |
72 m_items[id] = item; | |
73 } | |
74 | |
75 void release(int id) { | |
76 QMutexLocker locker(&m_mutex); | |
77 if (m_items.find(id) == m_items.end()) { | |
78 SVCERR << "ById::release: unknown item id " << id << endl; | |
79 throw std::logic_error("unknown item id in release"); | |
80 } | |
81 m_items.erase(id); | |
82 } | |
83 | |
84 std::shared_ptr<WithId> get(int id) const { | |
85 QMutexLocker locker(&m_mutex); | |
86 const auto &itr = m_items.find(id); | |
87 if (itr != m_items.end()) { | |
88 return itr->second; | |
89 } else { | |
90 return {}; | |
91 } | |
92 } | |
93 | |
94 private: | |
95 mutable QMutex m_mutex; | |
96 std::unordered_map<int, std::shared_ptr<WithId>> m_items; | |
97 }; | |
98 | |
99 void | |
100 AnyById::add(int id, std::shared_ptr<WithId> item) | |
101 { | |
102 impl().add(id, item); | |
103 } | |
104 | |
105 void | |
106 AnyById::release(int id) | |
107 { | |
108 impl().release(id); | |
109 } | |
110 | |
111 std::shared_ptr<WithId> | |
112 AnyById::get(int id) | |
113 { | |
114 return impl().get(id); | |
115 } | |
116 | |
117 AnyById::Impl & | |
118 AnyById::impl() | |
119 { | |
120 static Impl impl; | |
121 return impl; | |
122 } |