mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-20 21:56:30 +01:00
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
This commit is contained in:
parent
20eb826764
commit
11f448917f
3 changed files with 21 additions and 5 deletions
|
|
@ -178,6 +178,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual WriteLock edit_lock();
|
||||||
virtual WriteLock write_lock();
|
virtual WriteLock write_lock();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ MidiModel::DeltaCommand::operator()()
|
||||||
// This could be made much faster by using a priority_queue for added and
|
// 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
|
// 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) {
|
for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i) {
|
||||||
_model->add_note_unlocked(*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
|
// 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
|
// 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) {
|
for (NoteList::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i) {
|
||||||
_model->remove_note_unlocked(*i);
|
_model->remove_note_unlocked(*i);
|
||||||
|
|
@ -383,7 +383,7 @@ MidiModel::DiffCommand::change(const boost::shared_ptr< Evoral::Note<TimeType> >
|
||||||
void
|
void
|
||||||
MidiModel::DiffCommand::operator()()
|
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) {
|
for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
|
||||||
Property prop = i->property;
|
Property prop = i->property;
|
||||||
|
|
@ -413,7 +413,7 @@ MidiModel::DiffCommand::operator()()
|
||||||
void
|
void
|
||||||
MidiModel::DiffCommand::undo()
|
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) {
|
for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
|
||||||
Property prop = i->property;
|
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> >();
|
return boost::shared_ptr<Evoral::Note<TimeType> >();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Lock and invalidate the source.
|
||||||
|
* This should be used by commands and editing things
|
||||||
|
*/
|
||||||
MidiModel::WriteLock
|
MidiModel::WriteLock
|
||||||
MidiModel::write_lock()
|
MidiModel::edit_lock()
|
||||||
{
|
{
|
||||||
Glib::Mutex::Lock* source_lock = new Glib::Mutex::Lock(_midi_source->mutex());
|
Glib::Mutex::Lock* source_lock = new Glib::Mutex::Lock(_midi_source->mutex());
|
||||||
_midi_source->invalidate(); // Release cached iterator's read lock on model
|
_midi_source->invalidate(); // Release cached iterator's read lock on model
|
||||||
return WriteLock(new WriteLockImpl(source_lock, _lock, _control_lock));
|
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));
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -362,6 +362,7 @@ SMFSource::set_state (const XMLNode& node, int version)
|
||||||
void
|
void
|
||||||
SMFSource::mark_streaming_midi_write_started (NoteMode mode, sframes_t start_frame)
|
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);
|
MidiSource::mark_streaming_midi_write_started (mode, start_frame);
|
||||||
Evoral::SMF::begin_write ();
|
Evoral::SMF::begin_write ();
|
||||||
_last_ev_time_beats = 0.0;
|
_last_ev_time_beats = 0.0;
|
||||||
|
|
@ -371,6 +372,7 @@ SMFSource::mark_streaming_midi_write_started (NoteMode mode, sframes_t start_fra
|
||||||
void
|
void
|
||||||
SMFSource::mark_streaming_write_completed ()
|
SMFSource::mark_streaming_write_completed ()
|
||||||
{
|
{
|
||||||
|
Glib::Mutex::Lock lm (_lock);
|
||||||
MidiSource::mark_streaming_write_completed();
|
MidiSource::mark_streaming_write_completed();
|
||||||
|
|
||||||
if (!writable()) {
|
if (!writable()) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue