comparison data/model/RegionModel.h @ 1798:13bd41bd8a17

Some work on making Model classes thread-safe in typical use - and documenting this. Some of the implementations are simpler now that EventSeries is thread-safe
author Chris Cannam
date Tue, 01 Oct 2019 11:22:48 +0100
parents 6d09d68165a4
children 343ef2a866a4
comparison
equal deleted inserted replaced
1797:e8b552549225 1798:13bd41bd8a17
23 #include "base/RealTime.h" 23 #include "base/RealTime.h"
24 #include "base/EventSeries.h" 24 #include "base/EventSeries.h"
25 #include "base/UnitDatabase.h" 25 #include "base/UnitDatabase.h"
26 26
27 #include "system/System.h" 27 #include "system/System.h"
28
29 #include <QMutex>
30 28
31 /** 29 /**
32 * RegionModel -- a model for intervals associated with a value, which 30 * RegionModel -- a model for intervals associated with a value, which
33 * we call regions for no very compelling reason. 31 * we call regions for no very compelling reason.
34 */ 32 */
111 109
112 int getCompletion() const override { return m_completion; } 110 int getCompletion() const override { return m_completion; }
113 111
114 void setCompletion(int completion, bool update = true) { 112 void setCompletion(int completion, bool update = true) {
115 113
116 { QMutexLocker locker(&m_mutex); 114 { if (m_completion == completion) return;
117 if (m_completion == completion) return;
118 m_completion = completion; 115 m_completion = completion;
119 } 116 }
120 117
121 if (update) { 118 if (update) {
122 m_notifier.makeDeferredNotifications(); 119 m_notifier.makeDeferredNotifications();
174 */ 171 */
175 void add(Event e) override { 172 void add(Event e) override {
176 173
177 bool allChange = false; 174 bool allChange = false;
178 175
179 { 176 m_events.add(e);
180 QMutexLocker locker(&m_mutex); 177
181 m_events.add(e); 178 float v = e.getValue();
182 179 if (!ISNAN(v) && !ISINF(v)) {
183 float v = e.getValue(); 180 if (!m_haveExtents || v < m_valueMinimum) {
184 if (!ISNAN(v) && !ISINF(v)) { 181 m_valueMinimum = v; allChange = true;
185 if (!m_haveExtents || v < m_valueMinimum) {
186 m_valueMinimum = v; allChange = true;
187 }
188 if (!m_haveExtents || v > m_valueMaximum) {
189 m_valueMaximum = v; allChange = true;
190 }
191 m_haveExtents = true;
192 } 182 }
193 183 if (!m_haveExtents || v > m_valueMaximum) {
194 if (e.hasValue() && e.getValue() != 0.f) { 184 m_valueMaximum = v; allChange = true;
195 m_haveDistinctValues = true;
196 } 185 }
186 m_haveExtents = true;
187 }
188
189 if (e.hasValue() && e.getValue() != 0.f) {
190 m_haveDistinctValues = true;
197 } 191 }
198 192
199 m_notifier.update(e.getFrame(), e.getDuration() + m_resolution); 193 m_notifier.update(e.getFrame(), e.getDuration() + m_resolution);
200 194
201 if (allChange) { 195 if (allChange) {
202 emit modelChanged(getId()); 196 emit modelChanged(getId());
203 } 197 }
204 } 198 }
205 199
206 void remove(Event e) override { 200 void remove(Event e) override {
207 { 201 m_events.remove(e);
208 QMutexLocker locker(&m_mutex);
209 m_events.remove(e);
210 }
211 emit modelChangedWithin(getId(), 202 emit modelChangedWithin(getId(),
212 e.getFrame(), 203 e.getFrame(),
213 e.getFrame() + e.getDuration() + m_resolution); 204 e.getFrame() + e.getDuration() + m_resolution);
214 } 205 }
215 206
345 336
346 protected: 337 protected:
347 sv_samplerate_t m_sampleRate; 338 sv_samplerate_t m_sampleRate;
348 int m_resolution; 339 int m_resolution;
349 340
350 float m_valueMinimum; 341 std::atomic<float> m_valueMinimum;
351 float m_valueMaximum; 342 std::atomic<float> m_valueMaximum;
352 bool m_haveExtents; 343 std::atomic<bool> m_haveExtents;
353 float m_valueQuantization; 344 float m_valueQuantization;
354 bool m_haveDistinctValues; 345 bool m_haveDistinctValues;
355 QString m_units; 346 QString m_units;
356 DeferredNotifier m_notifier; 347 DeferredNotifier m_notifier;
357 int m_completion; 348 std::atomic<int> m_completion;
358 349
359 EventSeries m_events; 350 EventSeries m_events;
360
361 mutable QMutex m_mutex;
362 }; 351 };
363 352
364 #endif 353 #endif