From 5cd9c86d580d6419400e67f5890d583c606c8a10 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 17 Oct 2019 15:19:05 -0600 Subject: add RAII-style write protection while rendering MIDI playlist into RTMidiBuffer --- libs/ardour/ardour/rt_midibuffer.h | 13 ++++++++++++- libs/ardour/midi_playlist.cc | 11 ++++++++++- libs/ardour/rt_midibuffer.cc | 8 ++++++-- 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 }; private: + friend struct WriteProtectRender; struct Blob { uint32_t size; @@ -85,7 +86,17 @@ class LIBARDOUR_API RTMidiBuffer : public Evoral::EventSink 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 evlist; Evoral::EventSink* 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::iterator e = evlist.begin(); e != evlist.end(); ++e) { Evoral::Event* 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; -- cgit v1.2.3