summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-10-22 20:37:24 +0000
committerDavid Robillard <d@drobilla.net>2009-10-22 20:37:24 +0000
commit11f448917f622be991782b1d72b801359034ffa8 (patch)
treeffc2571a6fb8d45b77ab20d976de91ece5f73fc4 /libs/ardour
parent20eb82676410d65ff4beac042339c04de1c3b8ea (diff)
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
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/midi_model.h1
-rw-r--r--libs/ardour/midi_model.cc23
-rw-r--r--libs/ardour/smf_source.cc2
3 files changed, 21 insertions, 5 deletions
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<TimeType> >
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<Evoral::Note<TimeType> > other)
return boost::shared_ptr<Evoral::Note<TimeType> >();
}
+/** 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()) {