add RAII-style write protection while rendering MIDI playlist into RTMidiBuffer

This commit is contained in:
Paul Davis 2019-10-17 15:19:05 -06:00
parent c55e23e7aa
commit 5cd9c86d58
3 changed files with 28 additions and 4 deletions

View file

@ -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

View file

@ -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");
}

View file

@ -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;