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.
This commit is contained in:
Fastigium
2016-03-11 16:35:48 +01:00
parent ac67f2adb8
commit 3c7bfbac64
16 changed files with 27 additions and 50 deletions

View File

@@ -56,13 +56,13 @@ public:
do
{
nphsLeft = false;
foreach( const NotePlayHandle * cnph, nphv )
for( const NotePlayHandle * constNotePlayHandle : nphv )
{
NotePlayHandle * nph = const_cast<NotePlayHandle *>( cnph );
if( nph->state() != ThreadableJob::Done && ! nph->isFinished() )
NotePlayHandle * notePlayHandle = const_cast<NotePlayHandle *>( constNotePlayHandle );
if( notePlayHandle->state() != ThreadableJob::Done && ! notePlayHandle->isFinished() )
{
nphsLeft = true;
nph->process();
notePlayHandle->process();
}
}
}

View File

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

View File

@@ -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() )
{

View File

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

View File

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

View File

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

View File

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

View File

@@ -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() )
{

View File

@@ -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; i<num_new; i++ )
{
compressedband[i]=0;

View File

@@ -216,7 +216,7 @@ void EffectSelectDialog::rowChanged( const QModelIndex & _idx,
subLayout->setSpacing( 0 );
m_currentSelection.desc->subPluginFeatures->
fillDescriptionWidget( subWidget, &m_currentSelection );
foreach( QWidget * w, subWidget->findChildren<QWidget *>() )
for( QWidget * w : subWidget->findChildren<QWidget *>() )
{
if( w->parent() == subWidget )
{

View File

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

View File

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

View File

@@ -220,7 +220,7 @@ void BBTrackContainerView::addAutomationTrack()
void BBTrackContainerView::removeBBView(int bb)
{
foreach( TrackView* view, trackViews() )
for( TrackView* view : trackViews() )
{
view->getTrackContentWidget()->removeTCOView( bb );
}

View File

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

View File

@@ -664,17 +664,5 @@ void BBTrackView::clickedTrackLabel()
{
Engine::getBBTrackContainer()->setCurrentBB( m_bbTrack->index() );
gui->getBBEditor()->show();
/* foreach( bbTrackView * tv,
trackContainerView()->findChildren<bbTrackView *>() )
{
tv->m_trackLabel->update();
}*/
}

View File

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