From 3c7bfbac643ade723b2edb3b8206da50468a39f6 Mon Sep 17 00:00:00 2001 From: Fastigium Date: Fri, 11 Mar 2016 16:35:48 +0100 Subject: [PATCH] Replace every use of the foreach macro with a C++11 range-based for loop This prevents a race condition with Qt5. A foreach loop makes a copy of its Qt container, increasing the reference count to the container's internal data. Qt5 often asserts isDetached(), which requires the reference count to be <= 1. This assertion fails when the foreach loop increases the reference count at exactly the wrong moment. Using a range-based for loop prevents an unnecessary copy from being made and ensures this race condition isn't triggered. --- include/InstrumentPlayHandle.h | 8 ++++---- plugins/MidiExport/MidiExport.cpp | 4 ++-- plugins/zynaddsubfx/ZynAddSubFx.cpp | 2 +- src/core/AutomatableModel.cpp | 2 +- src/core/ComboBoxModel.cpp | 2 +- src/core/FxMixer.cpp | 14 +++++++------- src/core/NotePlayHandle.cpp | 13 +------------ src/core/audio/AudioPort.cpp | 2 +- src/core/fft_helpers.cpp | 2 +- src/gui/EffectSelectDialog.cpp | 2 +- src/gui/FxMixerView.cpp | 2 +- src/gui/MainWindow.cpp | 4 ++-- src/gui/editors/BBEditor.cpp | 2 +- src/gui/widgets/AutomatableButton.cpp | 4 ++-- src/tracks/BBTrack.cpp | 12 ------------ src/tracks/InstrumentTrack.cpp | 2 +- 16 files changed, 27 insertions(+), 50 deletions(-) diff --git a/include/InstrumentPlayHandle.h b/include/InstrumentPlayHandle.h index ffbfbce73..74ceebbf2 100644 --- a/include/InstrumentPlayHandle.h +++ b/include/InstrumentPlayHandle.h @@ -56,13 +56,13 @@ public: do { nphsLeft = false; - foreach( const NotePlayHandle * cnph, nphv ) + for( const NotePlayHandle * constNotePlayHandle : nphv ) { - NotePlayHandle * nph = const_cast( cnph ); - if( nph->state() != ThreadableJob::Done && ! nph->isFinished() ) + NotePlayHandle * notePlayHandle = const_cast( constNotePlayHandle ); + if( notePlayHandle->state() != ThreadableJob::Done && ! notePlayHandle->isFinished() ) { nphsLeft = true; - nph->process(); + notePlayHandle->process(); } } } diff --git a/plugins/MidiExport/MidiExport.cpp b/plugins/MidiExport/MidiExport.cpp index 03ef3a496..4cb0b356b 100644 --- a/plugins/MidiExport/MidiExport.cpp +++ b/plugins/MidiExport/MidiExport.cpp @@ -83,7 +83,7 @@ bool MidiExport::tryExport( const TrackContainer::TrackList &tracks, int tempo, uint8_t buffer[BUFFER_SIZE]; uint32_t size; - foreach( Track* track, tracks ) if( track->type() == Track::InstrumentTrack ) nTracks++; + for( const Track* track : tracks ) if( track->type() == Track::InstrumentTrack ) nTracks++; // midi header MidiFile::MIDIHeader header(nTracks); @@ -91,7 +91,7 @@ bool MidiExport::tryExport( const TrackContainer::TrackList &tracks, int tempo, midiout.writeRawData((char *)buffer, size); // midi tracks - foreach( Track* track, tracks ) + for( Track* track : tracks ) { DataFile dataFile( DataFile::SongProject ); MidiFile::MIDITrack mtrack; diff --git a/plugins/zynaddsubfx/ZynAddSubFx.cpp b/plugins/zynaddsubfx/ZynAddSubFx.cpp index ad1e8ff90..14080f3be 100644 --- a/plugins/zynaddsubfx/ZynAddSubFx.cpp +++ b/plugins/zynaddsubfx/ZynAddSubFx.cpp @@ -262,7 +262,7 @@ void ZynAddSubFxInstrument::loadSettings( const QDomElement & _this ) m_pluginMutex.unlock(); m_modifiedControllers.clear(); - foreach( const QString & c, _this.attribute( "modifiedcontrollers" ).split( ',' ) ) + for( const QString & c : _this.attribute( "modifiedcontrollers" ).split( ',' ) ) { if( !c.isEmpty() ) { diff --git a/src/core/AutomatableModel.cpp b/src/core/AutomatableModel.cpp index bf56285e5..20b7b7d09 100644 --- a/src/core/AutomatableModel.cpp +++ b/src/core/AutomatableModel.cpp @@ -450,7 +450,7 @@ void AutomatableModel::unlinkModels( AutomatableModel* model1, AutomatableModel* void AutomatableModel::unlinkAllModels() { - foreach( AutomatableModel* model, m_linkedModels ) + for( AutomatableModel* model : m_linkedModels ) { unlinkModels( this, model ); } diff --git a/src/core/ComboBoxModel.cpp b/src/core/ComboBoxModel.cpp index e5df419a8..a669cb3d7 100644 --- a/src/core/ComboBoxModel.cpp +++ b/src/core/ComboBoxModel.cpp @@ -39,7 +39,7 @@ void ComboBoxModel::addItem( const QString& item, PixmapLoader* loader ) void ComboBoxModel::clear() { setRange( 0, 0 ); - foreach( const Item& i, m_items ) + for( const Item& i : m_items ) { delete i.second; } diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 877755556..be4378bd8 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -87,7 +87,7 @@ FxChannel::~FxChannel() inline void FxChannel::processed() { - foreach( FxRoute * receiverRoute, m_sends ) + for( const FxRoute * receiverRoute : m_sends ) { if( receiverRoute->receiver()->m_muted == false ) { @@ -121,7 +121,7 @@ void FxChannel::doProcessing() if( m_muted == false ) { - foreach( FxRoute * senderRoute, m_receives ) + for( FxRoute * senderRoute : m_receives ) { FxChannel * sender = senderRoute->sender(); FloatModel * sendModel = senderRoute->amount(); @@ -293,7 +293,7 @@ void FxMixer::deleteChannel( int index ) tracks += Engine::getSong()->tracks(); tracks += Engine::getBBTrackContainer()->tracks(); - foreach( Track* t, tracks ) + for( Track* t : tracks ) { if( t->type() == Track::InstrumentTrack ) { @@ -335,11 +335,11 @@ void FxMixer::deleteChannel( int index ) m_fxChannels[i]->m_channelIndex = i; // now check all routes and update names of the send models - foreach( FxRoute * r, m_fxChannels[i]->m_sends ) + for( FxRoute * r : m_fxChannels[i]->m_sends ) { r->updateName(); } - foreach( FxRoute * r, m_fxChannels[i]->m_receives ) + for( FxRoute * r : m_fxChannels[i]->m_receives ) { r->updateName(); } @@ -528,7 +528,7 @@ FloatModel * FxMixer::channelSendModel( fx_ch_t fromChannel, fx_ch_t toChannel ) const FxChannel * from = m_fxChannels[fromChannel]; const FxChannel * to = m_fxChannels[toChannel]; - foreach( FxRoute * route, from->m_sends ) + for( FxRoute * route : from->m_sends ) { if( route->receiver() == to ) { @@ -578,7 +578,7 @@ void FxMixer::masterMix( sampleFrame * _buf ) // also instantly add all muted channels as they don't need to care about their senders, and can just increment the deps of // their recipients right away. MixerWorkerThread::resetJobQueue( MixerWorkerThread::JobQueue::Dynamic ); - foreach( FxChannel * ch, m_fxChannels ) + for( FxChannel * ch : m_fxChannels ) { ch->m_muted = ch->m_muteModel.value(); if( ch->m_muted ) // instantly "process" muted channels diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index d0fadece3..d027fef1a 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -301,17 +301,6 @@ void NotePlayHandle::play( sampleFrame * _working_buffer ) } } - // play sub-notes (e.g. chords) - // handled by mixer now -/* foreach( NotePlayHandle * n, m_subNotes ) - { - n->play( _working_buffer ); - if( n->isFinished() ) - { - NotePlayHandleManager::release( n ); - } - }*/ - // update internal data m_totalFramesPlayed += framesThisPeriod; unlock(); @@ -369,7 +358,7 @@ void NotePlayHandle::noteOff( const f_cnt_t _s ) m_released = true; // first note-off all sub-notes - foreach( NotePlayHandle * n, m_subNotes ) + for( NotePlayHandle * n : m_subNotes ) { n->lock(); n->noteOff( _s ); diff --git a/src/core/audio/AudioPort.cpp b/src/core/audio/AudioPort.cpp index bbec65a38..7d26bd367 100644 --- a/src/core/audio/AudioPort.cpp +++ b/src/core/audio/AudioPort.cpp @@ -116,7 +116,7 @@ void AudioPort::doProcessing() BufferManager::clear( m_portBuffer, fpp ); //qDebug( "Playhandles: %d", m_playHandles.size() ); - foreach( PlayHandle * ph, m_playHandles ) // now we mix all playhandle buffers into the audioport buffer + for( PlayHandle * ph : m_playHandles ) // now we mix all playhandle buffers into the audioport buffer { if( ph->buffer() ) { diff --git a/src/core/fft_helpers.cpp b/src/core/fft_helpers.cpp index 11f619c4a..4924403c5 100644 --- a/src/core/fft_helpers.cpp +++ b/src/core/fft_helpers.cpp @@ -134,7 +134,7 @@ int compressbands(float *absspec_buffer, float *compressedband, int num_old, int ratio=(float)usefromold/(float)num_new; - // foreach new subband + // for each new subband for ( i=0; isetSpacing( 0 ); m_currentSelection.desc->subPluginFeatures-> fillDescriptionWidget( subWidget, &m_currentSelection ); - foreach( QWidget * w, subWidget->findChildren() ) + for( QWidget * w : subWidget->findChildren() ) { if( w->parent() == subWidget ) { diff --git a/src/gui/FxMixerView.cpp b/src/gui/FxMixerView.cpp index 380fec099..5826ed9d4 100644 --- a/src/gui/FxMixerView.cpp +++ b/src/gui/FxMixerView.cpp @@ -420,7 +420,7 @@ void FxMixerView::deleteUnusedChannels() { // check if an instrument references to the current channel bool empty=true; - foreach( Track* t, tracks ) + for( Track* t : tracks ) { if( t->type() == Track::InstrumentTrack ) { diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 3a95a2df6..f6f2ef663 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -145,7 +145,7 @@ MainWindow::MainWindow() : #if ! defined(LMMS_BUILD_APPLE) QFileInfoList drives = QDir::drives(); - foreach( const QFileInfo & drive, drives ) + for( const QFileInfo & drive : drives ) { root_paths += drive.absolutePath(); } @@ -602,7 +602,7 @@ void MainWindow::finalize() gui->songEditor()->parentWidget()->show(); // reset window title every time we change the state of a subwindow to show the correct title - foreach( QMdiSubWindow * subWindow, workspace()->subWindowList() ) + for( const QMdiSubWindow * subWindow : workspace()->subWindowList() ) { connect( subWindow, SIGNAL( windowStateChanged(Qt::WindowStates,Qt::WindowStates) ), this, SLOT( resetWindowTitle() ) ); } diff --git a/src/gui/editors/BBEditor.cpp b/src/gui/editors/BBEditor.cpp index 097b2c2a5..569759562 100644 --- a/src/gui/editors/BBEditor.cpp +++ b/src/gui/editors/BBEditor.cpp @@ -220,7 +220,7 @@ void BBTrackContainerView::addAutomationTrack() void BBTrackContainerView::removeBBView(int bb) { - foreach( TrackView* view, trackViews() ) + for( TrackView* view : trackViews() ) { view->getTrackContentWidget()->removeTCOView( bb ); } diff --git a/src/gui/widgets/AutomatableButton.cpp b/src/gui/widgets/AutomatableButton.cpp index 1e482d7f7..4e31d6447 100644 --- a/src/gui/widgets/AutomatableButton.cpp +++ b/src/gui/widgets/AutomatableButton.cpp @@ -236,7 +236,7 @@ void automatableButtonGroup::activateButton( AutomatableButton * _btn ) m_buttons.indexOf( _btn ) != -1 ) { model()->setValue( m_buttons.indexOf( _btn ) ); - foreach( AutomatableButton * btn, m_buttons ) + for( AutomatableButton * btn : m_buttons ) { btn->update(); } @@ -261,7 +261,7 @@ void automatableButtonGroup::updateButtons() { model()->setRange( 0, m_buttons.size() - 1 ); int i = 0; - foreach( AutomatableButton * btn, m_buttons ) + for( AutomatableButton * btn : m_buttons ) { btn->model()->setValue( i == model()->value() ); ++i; diff --git a/src/tracks/BBTrack.cpp b/src/tracks/BBTrack.cpp index cf9a9292f..b8ae5968a 100644 --- a/src/tracks/BBTrack.cpp +++ b/src/tracks/BBTrack.cpp @@ -664,17 +664,5 @@ void BBTrackView::clickedTrackLabel() { Engine::getBBTrackContainer()->setCurrentBB( m_bbTrack->index() ); gui->getBBEditor()->show(); -/* foreach( bbTrackView * tv, - trackContainerView()->findChildren() ) - { - tv->m_trackLabel->update(); - }*/ - } - - - - - - diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index e1f7f4b41..d1eb5bc1e 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -949,7 +949,7 @@ InstrumentTrackView::~InstrumentTrackView() InstrumentTrackWindow * InstrumentTrackView::topLevelInstrumentTrackWindow() { InstrumentTrackWindow * w = NULL; - foreach( QMdiSubWindow * sw, + for( const QMdiSubWindow * sw : gui->mainWindow()->workspace()->subWindowList( QMdiArea::ActivationHistoryOrder ) ) {