# HG changeset patch # User Chris Cannam # Date 1233835528 0 # Node ID 1469caaa8e670ed507e24871c07c2315705b82b7 # Parent 806e3c72b5df5b9c7172fa56936a18f1b9aadda7 * Finer locking in fft caches; fix displayed bin ranges in spectrogram diff -r 806e3c72b5df -r 1469caaa8e67 base/ResizeableBitset.h --- a/base/ResizeableBitset.h Wed Feb 04 20:39:11 2009 +0000 +++ b/base/ResizeableBitset.h Thu Feb 05 12:05:28 2009 +0000 @@ -40,13 +40,19 @@ delete m_bits; } - void resize(size_t bits) { // losing all data - if (!m_bits || bits < m_bits->size()) { + void resize(size_t size) { // retaining existing data; not thread safe + size_t bytes = (size >> 3) + 1; + if (m_bits && bytes == m_bits->size()) return; + std::vector *newbits = new std::vector(bytes); + newbits->assign(bytes, 0); + if (m_bits) { + for (size_t i = 0; i < bytes && i < m_bits->size(); ++i) { + (*newbits)[i] = (*m_bits)[i]; + } delete m_bits; - m_bits = new std::vector; } - m_bits->assign((bits >> 3) + 1, 0); - m_size = bits; + m_bits = newbits; + m_size = size; } bool get(size_t column) const { diff -r 806e3c72b5df -r 1469caaa8e67 data/fft/FFTDataServer.cpp --- a/data/fft/FFTDataServer.cpp Wed Feb 04 20:39:11 2009 +0000 +++ b/data/fft/FFTDataServer.cpp Thu Feb 05 12:05:28 2009 +0000 @@ -738,13 +738,25 @@ bool FFTDataServer::makeCache(int c) { - QWriteLocker locker(&m_cacheVectorLock); + // Creating the cache could take a significant amount of time. We + // don't want to block readers on m_cacheVectorLock while this is + // happening, but we do want to block any further calls to + // makeCache. So we use this lock solely to serialise this + // particular function -- it isn't used anywhere else. + QMutexLocker locker(&m_cacheCreationMutex); + + m_cacheVectorLock.lockForRead(); if (m_caches[c]) { // someone else must have created the cache between our - // testing for it and taking the write lock + // testing for it and taking the mutex + m_cacheVectorLock.unlock(); return true; } + m_cacheVectorLock.unlock(); + + // Now m_cacheCreationMutex is held, but m_cacheVectorLock is not + // -- readers can proceed, but callers to this function will block CacheBlock *cb = new CacheBlock; @@ -811,8 +823,12 @@ } } + m_cacheVectorLock.lockForWrite(); + m_caches[c] = cb; + m_cacheVectorLock.unlock(); + return success; } diff -r 806e3c72b5df -r 1469caaa8e67 data/fft/FFTDataServer.h --- a/data/fft/FFTDataServer.h Wed Feb 04 20:39:11 2009 +0000 +++ b/data/fft/FFTDataServer.h Thu Feb 05 12:05:28 2009 +0000 @@ -163,6 +163,7 @@ typedef std::vector CacheVector; CacheVector m_caches; QReadWriteLock m_cacheVectorLock; // locks cache lookup, not use + QMutex m_cacheCreationMutex; // solely to serialise makeCache() calls FFTCacheReader *getCacheReader(size_t x, size_t &col) { Profiler profiler("FFTDataServer::getCacheReader"); @@ -217,7 +218,7 @@ bool haveCache(size_t x) { int c = x >> m_cacheWidthPower; - return (m_caches[c] != 0); + return (m_caches.at(c) != 0); } bool makeCache(int c); diff -r 806e3c72b5df -r 1469caaa8e67 data/fft/FFTMemoryCache.cpp --- a/data/fft/FFTMemoryCache.cpp Wed Feb 04 20:39:11 2009 +0000 +++ b/data/fft/FFTMemoryCache.cpp Thu Feb 05 12:05:28 2009 +0000 @@ -148,9 +148,9 @@ } } - m_colsetMutex.lock(); + m_colsetLock.lockForWrite(); m_colset.set(x); - m_colsetMutex.unlock(); + m_colsetLock.unlock(); } void @@ -188,9 +188,9 @@ if (m_storageType == FFTCache::Rectangular) { m_factor[x] = max; - m_colsetMutex.lock(); + m_colsetLock.lockForWrite(); m_colset.set(x); - m_colsetMutex.unlock(); + m_colsetLock.unlock(); } else { setColumnAt(x, reals, imags, max); } diff -r 806e3c72b5df -r 1469caaa8e67 data/fft/FFTMemoryCache.h --- a/data/fft/FFTMemoryCache.h Wed Feb 04 20:39:11 2009 +0000 +++ b/data/fft/FFTMemoryCache.h Thu Feb 05 12:05:28 2009 +0000 @@ -22,7 +22,7 @@ #include "base/ResizeableBitset.h" #include "base/Profiler.h" -#include +#include /** * In-memory FFT cache. For this we want to cache magnitude with @@ -120,9 +120,9 @@ } bool haveSetColumnAt(size_t x) const { - m_colsetMutex.lock(); + m_colsetLock.lockForRead(); bool have = m_colset.get(x); - m_colsetMutex.unlock(); + m_colsetLock.unlock(); return have; } @@ -149,7 +149,7 @@ float *m_factor; FFTCache::StorageType m_storageType; ResizeableBitset m_colset; - mutable QMutex m_colsetMutex; + mutable QReadWriteLock m_colsetLock; void initialise(); diff -r 806e3c72b5df -r 1469caaa8e67 data/fileio/MatrixFile.cpp --- a/data/fileio/MatrixFile.cpp Wed Feb 04 20:39:11 2009 +0000 +++ b/data/fileio/MatrixFile.cpp Thu Feb 05 12:05:28 2009 +0000 @@ -68,7 +68,7 @@ std::cerr << "MatrixFile::MatrixFile(" << fileBase.toStdString() << ", " << int(mode) << ", " << cellSize << ", " << width << ", " << height << ")" << std::endl; #endif - QMutexLocker locker(&m_createMutex); + m_createMutex.lock(); QDir tempDir(TempDirectory::getInstance()->getPath()); QString fileName(tempDir.filePath(QString("%1.mfc").arg(fileBase))); @@ -113,6 +113,8 @@ throw FailedToOpenFile(fileName); } + m_createMutex.unlock(); + #ifdef DEBUG_MATRIX_FILE std::cerr << "MatrixFile(" << this << ")::MatrixFile: fd is " << m_fd << std::endl; #endif diff -r 806e3c72b5df -r 1469caaa8e67 data/model/Dense3DModelPeakCache.cpp --- a/data/model/Dense3DModelPeakCache.cpp Wed Feb 04 20:39:11 2009 +0000 +++ b/data/model/Dense3DModelPeakCache.cpp Thu Feb 05 12:05:28 2009 +0000 @@ -79,9 +79,7 @@ // may since have been filled, so reset it m_coverage.reset(m_coverage.size()-1); } - if (getWidth() > m_coverage.size()) { - m_coverage.resize(getWidth()); // clears all bits, which is OK with us - } + m_coverage.resize(getWidth()); // retaining data } void