summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2019-10-17 15:19:05 -0600
committerPaul Davis <paul@linuxaudiosystems.com>2019-11-02 16:32:18 -0600
commit5cd9c86d580d6419400e67f5890d583c606c8a10 (patch)
treea245b803e266d8a9204cbfaf386dd3e1f832cc08
parentc55e23e7aadca4ebe3b9ee8029abce939b4403ec (diff)
add RAII-style write protection while rendering MIDI playlist into RTMidiBuffer
-rw-r--r--libs/ardour/ardour/rt_midibuffer.h13
-rw-r--r--libs/ardour/midi_playlist.cc11
-rw-r--r--libs/ardour/rt_midibuffer.cc8
3 files changed, 28 insertions, 4 deletions
diff --git a/libs/ardour/ardour/rt_midibuffer.h b/libs/ardour/ardour/rt_midibuffer.h
index 5bb12afef9..ff17fd66e2 100644
--- a/libs/ardour/ardour/rt_midibuffer.h
+++ b/libs/ardour/ardour/rt_midibuffer.h
@@ -63,6 +63,7 @@ class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink<samplepos_t>
};
private:
+ friend struct WriteProtectRender;
struct Blob {
uint32_t size;
@@ -85,7 +86,17 @@ class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink<samplepos_t>
uint32_t _pool_capacity;
uint8_t* _pool;
- mutable Glib::Threads::RWLock _lock;
+ Glib::Threads::RWLock _lock;
+
+ public:
+ class WriteProtectRender {
+ public:
+ WriteProtectRender (RTMidiBuffer& rtm) : lm (rtm._lock, Glib::Threads::NOT_LOCK) {}
+ void acquire () { lm.acquire(); }
+
+ private:
+ Glib::Threads::RWLock::WriterLock lm;
+ };
};
} // namespace ARDOUR
diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc
index 61d114f67f..881641d32a 100644
--- a/libs/ardour/midi_playlist.cc
+++ b/libs/ardour/midi_playlist.cc
@@ -519,8 +519,12 @@ MidiPlaylist::render (RTMidiBuffer& dst, MidiChannelFilter* filter)
Evoral::EventList<samplepos_t> evlist;
Evoral::EventSink<samplepos_t>* tgt;
+ /* RAII */
+ RTMidiBuffer::WriteProtectRender wpr (dst);
+
if (regs.size() == 1) {
tgt = &dst;
+ wpr.acquire ();
} else {
tgt = &evlist;
}
@@ -545,6 +549,9 @@ MidiPlaylist::render (RTMidiBuffer& dst, MidiChannelFilter* filter)
evlist.sort (cmp);
/* Copy ordered events from event list to dst. */
+
+ wpr.acquire ();
+
for (Evoral::EventList<samplepos_t>::iterator e = evlist.begin(); e != evlist.end(); ++e) {
Evoral::Event<samplepos_t>* ev (*e);
dst.write (ev->time(), ev->event_type(), ev->size(), ev->buffer());
@@ -552,6 +559,8 @@ MidiPlaylist::render (RTMidiBuffer& dst, MidiChannelFilter* filter)
}
}
- DEBUG_TRACE (DEBUG::MidiPlaylistIO, "---- End MidiPlaylist::dump ----\n");
+ /* no need to release - RAII with WriteProtectRender takes care of it */
+
+ DEBUG_TRACE (DEBUG::MidiPlaylistIO, "---- End MidiPlaylist::dump ----\n");
}
diff --git a/libs/ardour/rt_midibuffer.cc b/libs/ardour/rt_midibuffer.cc
index 29ac4c6fb9..7c1b1f5330 100644
--- a/libs/ardour/rt_midibuffer.cc
+++ b/libs/ardour/rt_midibuffer.cc
@@ -167,11 +167,15 @@ item_timestamp_earlier (ARDOUR::RTMidiBuffer::Item const & item, samplepos_t tim
return item.timestamp < time;
}
-
-
uint32_t
RTMidiBuffer::read (MidiBuffer& dst, samplepos_t start, samplepos_t end, MidiStateTracker& tracker, samplecnt_t offset)
{
+ Glib::Threads::RWLock::ReaderLock lm (_lock, Glib::Threads::TRY_LOCK);
+
+ if (!lm.locked()) {
+ return 0;
+ }
+
Item* iend = _data+_size;
Item* item = lower_bound (_data, iend, start, item_timestamp_earlier);
uint32_t count = 0;