# HG changeset patch # User Chris Cannam # Date 1224072482 0 # Node ID f60360209e5cb476ade8cddd9b10fdd72d219a80 # Parent ef14acd6d1023b469364d1d486f79487ec345fd3 * Fix race condition in FFTFileCache when reading from the same FFT model from multiple threads (e.g. when applying more than one plugin at once) diff -r ef14acd6d102 -r f60360209e5c data/fft/FFTFileCache.cpp --- a/data/fft/FFTFileCache.cpp Tue Oct 14 16:36:35 2008 +0000 +++ b/data/fft/FFTFileCache.cpp Wed Oct 15 12:08:02 2008 +0000 @@ -72,16 +72,21 @@ MutexLocker locker(&m_writeMutex, "FFTFileCache::resize::m_writeMutex"); m_mfc->resize(width, height * 2 + m_factorSize); - if (m_readbuf) { - delete[] m_readbuf; - m_readbuf = 0; + + { + MutexLocker locker(&m_readbufMutex, "FFTFileCache::resize::m_readMutex"); + if (m_readbuf) { + delete[] m_readbuf; + m_readbuf = 0; + } } + if (m_writebuf) { delete[] m_writebuf; } m_writebuf = new char[(height * 2 + m_factorSize) * m_mfc->getCellSize()]; } - + void FFTFileCache::reset() { @@ -302,7 +307,7 @@ } void -FFTFileCache::populateReadBuf(size_t x) const +FFTFileCache::populateReadBuf(size_t x) const // m_readbufMutex already held { Profiler profiler("FFTFileCache::populateReadBuf", false); diff -r ef14acd6d102 -r f60360209e5c data/fft/FFTFileCache.h --- a/data/fft/FFTFileCache.h Tue Oct 14 16:36:35 2008 +0000 +++ b/data/fft/FFTFileCache.h Wed Oct 15 12:08:02 2008 +0000 @@ -62,31 +62,43 @@ mutable size_t m_readbufWidth; float getFromReadBufStandard(size_t x, size_t y) const { + m_readbufMutex.lock(); if (m_readbuf && (m_readbufCol == x || (m_readbufWidth > 1 && m_readbufCol+1 == x))) { - return ((float *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y]; + float v = ((float *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y]; + m_readbufMutex.unlock(); + return v; } else { populateReadBuf(x); + m_readbufMutex.unlock(); return getFromReadBufStandard(x, y); } } float getFromReadBufCompactUnsigned(size_t x, size_t y) const { + m_readbufMutex.lock(); if (m_readbuf && (m_readbufCol == x || (m_readbufWidth > 1 && m_readbufCol+1 == x))) { - return ((uint16_t *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y]; + float v = ((uint16_t *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y]; + m_readbufMutex.unlock(); + return v; } else { populateReadBuf(x); + m_readbufMutex.unlock(); return getFromReadBufCompactUnsigned(x, y); } } float getFromReadBufCompactSigned(size_t x, size_t y) const { + m_readbufMutex.lock(); if (m_readbuf && (m_readbufCol == x || (m_readbufWidth > 1 && m_readbufCol+1 == x))) { - return ((int16_t *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y]; + float v = ((int16_t *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y]; + m_readbufMutex.unlock(); + return v; } else { populateReadBuf(x); + m_readbufMutex.unlock(); return getFromReadBufCompactSigned(x, y); } } @@ -99,6 +111,7 @@ if (m_storageType != Compact) { return getFromReadBufStandard(col, h - 1); } else { + m_readbufMutex.lock(); union { float f; uint16_t u[2]; @@ -111,6 +124,7 @@ size_t ix = (col - m_readbufCol) * m_mfc->getHeight() + h; factor.u[0] = ((uint16_t *)m_readbuf)[ix - 2]; factor.u[1] = ((uint16_t *)m_readbuf)[ix - 1]; + m_readbufMutex.unlock(); return factor.f; } } @@ -133,6 +147,7 @@ MatrixFile *m_mfc; QMutex m_writeMutex; + mutable QMutex m_readbufMutex; StorageType m_storageType; size_t m_factorSize; };