From 11f448917f622be991782b1d72b801359034ffa8 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 22 Oct 2009 20:37:24 +0000 Subject: Fix deadlocks on MIDI record. More locking than is strictly necessary, but the assertion in MidiModel::write_lock is a nice check, at least for now... git-svn-id: svn://localhost/ardour2/branches/3.0@5868 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/midi_model.h | 1 + libs/ardour/midi_model.cc | 23 ++++++++++++++++++----- libs/ardour/smf_source.cc | 2 ++ 3 files changed, 21 insertions(+), 5 deletions(-) (limited to 'libs/ardour') diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index cebc435435..b099f575a1 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -178,6 +178,7 @@ private: }; public: + virtual WriteLock edit_lock(); virtual WriteLock write_lock(); private: diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index 2b63533537..688e766668 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -135,7 +135,7 @@ MidiModel::DeltaCommand::operator()() // This could be made much faster by using a priority_queue for added and // removed notes (or sort here), and doing a single iteration over _model - MidiModel::WriteLock lock(_model->write_lock()); + MidiModel::WriteLock lock(_model->edit_lock()); for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i) { _model->add_note_unlocked(*i); @@ -155,7 +155,7 @@ MidiModel::DeltaCommand::undo() // This could be made much faster by using a priority_queue for added and // removed notes (or sort here), and doing a single iteration over _model - MidiModel::WriteLock lock(_model->write_lock());; + MidiModel::WriteLock lock(_model->edit_lock());; for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i) { _model->remove_note_unlocked(*i); @@ -383,7 +383,7 @@ MidiModel::DiffCommand::change(const boost::shared_ptr< Evoral::Note > void MidiModel::DiffCommand::operator()() { - MidiModel::WriteLock lock(_model->write_lock()); + MidiModel::WriteLock lock(_model->edit_lock()); for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) { Property prop = i->property; @@ -413,7 +413,7 @@ MidiModel::DiffCommand::operator()() void MidiModel::DiffCommand::undo() { - MidiModel::WriteLock lock(_model->write_lock()); + MidiModel::WriteLock lock(_model->edit_lock()); for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) { Property prop = i->property; @@ -723,10 +723,23 @@ MidiModel::find_note (boost::shared_ptr > other) return boost::shared_ptr >(); } +/** Lock and invalidate the source. + * This should be used by commands and editing things + */ MidiModel::WriteLock -MidiModel::write_lock() +MidiModel::edit_lock() { Glib::Mutex::Lock* source_lock = new Glib::Mutex::Lock(_midi_source->mutex()); _midi_source->invalidate(); // Release cached iterator's read lock on model return WriteLock(new WriteLockImpl(source_lock, _lock, _control_lock)); } + +/** Lock just the model, the source lock must already be held. + * This should only be called from libardour/evoral places + */ +MidiModel::WriteLock +MidiModel::write_lock() +{ + assert(!_midi_source->mutex().trylock()); + return WriteLock(new WriteLockImpl(NULL, _lock, _control_lock)); +} diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index c8b9e254fb..f69b1788a0 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -362,6 +362,7 @@ SMFSource::set_state (const XMLNode& node, int version) void SMFSource::mark_streaming_midi_write_started (NoteMode mode, sframes_t start_frame) { + Glib::Mutex::Lock lm (_lock); MidiSource::mark_streaming_midi_write_started (mode, start_frame); Evoral::SMF::begin_write (); _last_ev_time_beats = 0.0; @@ -371,6 +372,7 @@ SMFSource::mark_streaming_midi_write_started (NoteMode mode, sframes_t start_fra void SMFSource::mark_streaming_write_completed () { + Glib::Mutex::Lock lm (_lock); MidiSource::mark_streaming_write_completed(); if (!writable()) { -- cgit v1.2.3