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]) { |
