Mercurial > hg > svcore
comparison base/EventSeries.h @ 1796:ff8c57c364a0
Make EventSeries threadsafe
author | Chris Cannam |
---|---|
date | Mon, 30 Sep 2019 20:28:03 +0100 |
parents | 94b488d4b299 |
children | e8b552549225 |
comparison
equal
deleted
inserted
replaced
1795:94b488d4b299 | 1796:ff8c57c364a0 |
---|---|
18 #include "Event.h" | 18 #include "Event.h" |
19 #include "XmlExportable.h" | 19 #include "XmlExportable.h" |
20 | 20 |
21 #include <set> | 21 #include <set> |
22 #include <functional> | 22 #include <functional> |
23 | |
24 #include <QMutex> | |
23 | 25 |
24 //#define DEBUG_EVENT_SERIES 1 | 26 //#define DEBUG_EVENT_SERIES 1 |
25 | 27 |
26 /** | 28 /** |
27 * Container storing a series of events, with or without durations, | 29 * Container storing a series of events, with or without durations, |
38 * This class is highly optimised for inserting events in increasing | 40 * This class is highly optimised for inserting events in increasing |
39 * order of start frame. Inserting (or deleting) events in the middle | 41 * order of start frame. Inserting (or deleting) events in the middle |
40 * does work, and should be acceptable in interactive use, but it is | 42 * does work, and should be acceptable in interactive use, but it is |
41 * very slow in bulk. | 43 * very slow in bulk. |
42 * | 44 * |
43 * EventSeries is not thread-safe. | 45 * EventSeries is thread-safe. |
44 */ | 46 */ |
45 class EventSeries : public XmlExportable | 47 class EventSeries : public XmlExportable |
46 { | 48 { |
47 public: | 49 public: |
48 EventSeries() : m_finalDurationlessEventFrame(0) { } | 50 EventSeries() : m_finalDurationlessEventFrame(0) { } |
49 ~EventSeries() =default; | 51 ~EventSeries() =default; |
50 | 52 |
51 EventSeries(const EventSeries &) =default; | 53 EventSeries(const EventSeries &); |
52 | 54 |
53 EventSeries &operator=(const EventSeries &) =delete; | 55 EventSeries &operator=(const EventSeries &); |
54 EventSeries &operator=(EventSeries &&) =delete; | 56 EventSeries &operator=(EventSeries &&); |
55 | 57 |
56 bool operator==(const EventSeries &other) const { | 58 bool operator==(const EventSeries &other) const; |
57 return m_events == other.m_events; | |
58 } | |
59 | 59 |
60 static EventSeries fromEvents(const EventVector &ee); | 60 static EventSeries fromEvents(const EventVector &ee); |
61 | 61 |
62 void clear(); | 62 void clear(); |
63 void add(const Event &e); | 63 void add(const Event &e); |
231 sv_samplerate_t sampleRate, | 231 sv_samplerate_t sampleRate, |
232 sv_frame_t resolution, | 232 sv_frame_t resolution, |
233 Event fillEvent) const; | 233 Event fillEvent) const; |
234 | 234 |
235 private: | 235 private: |
236 mutable QMutex m_mutex; | |
237 | |
238 EventSeries::EventSeries(const EventSeries &other, const QMutexLocker &); | |
239 | |
236 /** | 240 /** |
237 * This vector contains all events in the series, in the normal | 241 * This vector contains all events in the series, in the normal |
238 * sort order. For backward compatibility we must support series | 242 * sort order. For backward compatibility we must support series |
239 * containing multiple instances of identical events, so | 243 * containing multiple instances of identical events, so |
240 * consecutive events in this vector will not always be distinct. | 244 * consecutive events in this vector will not always be distinct. |
276 * overall end frame or to find the last frame of all events | 280 * overall end frame or to find the last frame of all events |
277 * without this. | 281 * without this. |
278 */ | 282 */ |
279 sv_frame_t m_finalDurationlessEventFrame; | 283 sv_frame_t m_finalDurationlessEventFrame; |
280 | 284 |
281 /** Create a seam at the given frame, copying from the prior seam | 285 /** |
282 * if there is one. If a seam already exists at the given frame, | 286 * Create a seam at the given frame, copying from the prior seam |
283 * leave it untouched. | 287 * if there is one. If a seam already exists at the given frame, |
288 * leave it untouched. | |
289 * | |
290 * Call with m_mutex locked. | |
284 */ | 291 */ |
285 void createSeam(sv_frame_t frame) { | 292 void createSeam(sv_frame_t frame) { |
286 auto itr = m_seams.lower_bound(frame); | 293 auto itr = m_seams.lower_bound(frame); |
287 if (itr == m_seams.end() || itr->first > frame) { | 294 if (itr == m_seams.end() || itr->first > frame) { |
288 if (itr != m_seams.begin()) { | 295 if (itr != m_seams.begin()) { |
296 } else if (itr->first > frame) { // itr must be begin() | 303 } else if (itr->first > frame) { // itr must be begin() |
297 m_seams[frame] = {}; | 304 m_seams[frame] = {}; |
298 } | 305 } |
299 } | 306 } |
300 | 307 |
308 /** | |
309 * Return true if the two seam map entries contain the same set of | |
310 * events. | |
311 * | |
312 * Precondition: no duplicates, i.e. no event appears more than | |
313 * once in s1 or more than once in s2. | |
314 * | |
315 * Call with m_mutex locked. | |
316 */ | |
301 bool seamsEqual(const std::vector<Event> &s1, | 317 bool seamsEqual(const std::vector<Event> &s1, |
302 const std::vector<Event> &s2) const { | 318 const std::vector<Event> &s2) const { |
303 | 319 |
304 if (s1.size() != s2.size()) { | 320 if (s1.size() != s2.size()) { |
305 return false; | 321 return false; |
306 } | 322 } |
307 | |
308 // precondition: no event appears more than once in s1 or more | |
309 // than once in s2 | |
310 | 323 |
311 #ifdef DEBUG_EVENT_SERIES | 324 #ifdef DEBUG_EVENT_SERIES |
312 for (int i = 0; in_range_for(s1, i); ++i) { | 325 for (int i = 0; in_range_for(s1, i); ++i) { |
313 for (int j = i + 1; in_range_for(s1, j); ++j) { | 326 for (int j = i + 1; in_range_for(s1, j); ++j) { |
314 if (s1[i] == s1[j] || s2[i] == s2[j]) { | 327 if (s1[i] == s1[j] || s2[i] == s2[j]) { |