comparison data/fft/FFTDataServer.cpp @ 408:115f60df1e4d

* Speed up spectrogram painting by releasing mutex in FFTDataServer while calculating data prior to writing it, and by adding whole-column value query methods to FFT objects * Add paint cache to Thumbwheel -- repaints of this widget were slowing down the whole spectrogram repaint * More uses of MutexLocker (named and with debug) and more profile points * Make startup much quicker some of the time, with OSC server in place
author Chris Cannam
date Thu, 08 May 2008 14:46:22 +0000
parents 7aa1de571880
children 52303ec15cd2
comparison
equal deleted inserted replaced
407:88ad01799040 408:115f60df1e4d
60 fftSize, 60 fftSize,
61 polar); 61 polar);
62 62
63 FFTDataServer *server = 0; 63 FFTDataServer *server = 0;
64 64
65 MutexLocker locker(&m_serverMapMutex, "FFTDataServer::m_serverMapMutex[getInstance]"); 65 MutexLocker locker(&m_serverMapMutex, "FFTDataServer::getInstance::m_serverMapMutex");
66 66
67 if ((server = findServer(n))) { 67 if ((server = findServer(n))) {
68 return server; 68 return server;
69 } 69 }
70 70
137 // multiple of the smaller (e.g. even though in principle you can 137 // multiple of the smaller (e.g. even though in principle you can
138 // draw the results at increment 256 from those at increment 768 138 // draw the results at increment 256 from those at increment 768
139 // or 1536, the model doesn't support this). 139 // or 1536, the model doesn't support this).
140 140
141 { 141 {
142 MutexLocker locker(&m_serverMapMutex, "FFTDataServer::m_serverMapMutex[getFuzzyInstance]"); 142 MutexLocker locker(&m_serverMapMutex, "FFTDataServer::getFuzzyInstance::m_serverMapMutex");
143 143
144 ServerMap::iterator best = m_servers.end(); 144 ServerMap::iterator best = m_servers.end();
145 int bestdist = -1; 145 int bestdist = -1;
146 146
147 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { 147 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) {
256 256
257 void 257 void
258 FFTDataServer::claimInstance(FFTDataServer *server, bool needLock) 258 FFTDataServer::claimInstance(FFTDataServer *server, bool needLock)
259 { 259 {
260 MutexLocker locker(needLock ? &m_serverMapMutex : 0, 260 MutexLocker locker(needLock ? &m_serverMapMutex : 0,
261 "FFTDataServer::m_serverMapMutex[claimInstance]"); 261 "FFTDataServer::claimInstance::m_serverMapMutex");
262 262
263 #ifdef DEBUG_FFT_SERVER 263 #ifdef DEBUG_FFT_SERVER
264 std::cerr << "FFTDataServer::claimInstance(" << server << ")" << std::endl; 264 std::cerr << "FFTDataServer::claimInstance(" << server << ")" << std::endl;
265 #endif 265 #endif
266 266
301 301
302 void 302 void
303 FFTDataServer::releaseInstance(FFTDataServer *server, bool needLock) 303 FFTDataServer::releaseInstance(FFTDataServer *server, bool needLock)
304 { 304 {
305 MutexLocker locker(needLock ? &m_serverMapMutex : 0, 305 MutexLocker locker(needLock ? &m_serverMapMutex : 0,
306 "FFTDataServer::m_serverMapMutex[releaseInstance]"); 306 "FFTDataServer::releaseInstance::m_serverMapMutex");
307 307
308 #ifdef DEBUG_FFT_SERVER 308 #ifdef DEBUG_FFT_SERVER
309 std::cerr << "FFTDataServer::releaseInstance(" << server << ")" << std::endl; 309 std::cerr << "FFTDataServer::releaseInstance(" << server << ")" << std::endl;
310 #endif 310 #endif
311 311
429 429
430 void 430 void
431 FFTDataServer::modelAboutToBeDeleted(Model *model) 431 FFTDataServer::modelAboutToBeDeleted(Model *model)
432 { 432 {
433 MutexLocker locker(&m_serverMapMutex, 433 MutexLocker locker(&m_serverMapMutex,
434 "FFTDataServer::m_serverMapMutex[modelAboutToBeDeleted]"); 434 "FFTDataServer::modelAboutToBeDeleted::m_serverMapMutex");
435 435
436 #ifdef DEBUG_FFT_SERVER 436 #ifdef DEBUG_FFT_SERVER
437 std::cerr << "FFTDataServer::modelAboutToBeDeleted(" << model << ")" 437 std::cerr << "FFTDataServer::modelAboutToBeDeleted(" << model << ")"
438 << std::endl; 438 << std::endl;
439 #endif 439 #endif
596 m_fillThread->wait(); 596 m_fillThread->wait();
597 delete m_fillThread; 597 delete m_fillThread;
598 } 598 }
599 599
600 MutexLocker locker(&m_writeMutex, 600 MutexLocker locker(&m_writeMutex,
601 "FFTDataServer::m_writeMutex[~FFTDataServer]"); 601 "FFTDataServer::~FFTDataServer::m_writeMutex");
602 602
603 for (CacheVector::iterator i = m_caches.begin(); i != m_caches.end(); ++i) { 603 for (CacheVector::iterator i = m_caches.begin(); i != m_caches.end(); ++i) {
604 604
605 if (*i) { 605 if (*i) {
606 delete *i; 606 delete *i;
632 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspend" << std::endl; 632 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspend" << std::endl;
633 #endif 633 #endif
634 Profiler profiler("FFTDataServer::suspend", false); 634 Profiler profiler("FFTDataServer::suspend", false);
635 635
636 MutexLocker locker(&m_writeMutex, 636 MutexLocker locker(&m_writeMutex,
637 "FFTDataServer::m_writeMutex[suspend]"); 637 "FFTDataServer::suspend::m_writeMutex");
638 m_suspended = true; 638 m_suspended = true;
639 for (CacheVector::iterator i = m_caches.begin(); i != m_caches.end(); ++i) { 639 for (CacheVector::iterator i = m_caches.begin(); i != m_caches.end(); ++i) {
640 if (*i) (*i)->suspend(); 640 if (*i) (*i)->suspend();
641 } 641 }
642 } 642 }
738 #ifdef DEBUG_FFT_SERVER 738 #ifdef DEBUG_FFT_SERVER
739 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "])::getCacheAux" << std::endl; 739 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "])::getCacheAux" << std::endl;
740 #endif 740 #endif
741 741
742 MutexLocker locker(&m_writeMutex, 742 MutexLocker locker(&m_writeMutex,
743 "FFTDataServer::m_writeMutex[getCacheAux]"); 743 "FFTDataServer::getCacheAux::m_writeMutex");
744 744
745 if (m_lastUsedCache == -1) { 745 if (m_lastUsedCache == -1) {
746 m_fillThread->start(); 746 m_fillThread->start();
747 } 747 }
748 748
873 size_t col; 873 size_t col;
874 FFTCache *cache = getCache(x, col); 874 FFTCache *cache = getCache(x, col);
875 if (!cache) return 0; 875 if (!cache) return 0;
876 876
877 if (!cache->haveSetColumnAt(col)) { 877 if (!cache->haveSetColumnAt(col)) {
878 Profiler profiler("FFTDataServer::getMagnitudeAt: filling");
878 #ifdef DEBUG_FFT_SERVER 879 #ifdef DEBUG_FFT_SERVER
879 std::cerr << "FFTDataServer::getMagnitudeAt: calling fillColumn(" 880 std::cerr << "FFTDataServer::getMagnitudeAt: calling fillColumn("
880 << x << ")" << std::endl; 881 << x << ")" << std::endl;
881 #endif 882 #endif
882 fillColumn(x); 883 // hold mutex so that write thread doesn't mess with class
884 // member data in fillColumn
885 MutexLocker locker(&m_writeMutex,
886 "FFTDataServer::getMagnitudeAt: m_writeMutex");
887 fillColumn(x, true);
883 } 888 }
884 return cache->getMagnitudeAt(col, y); 889 return cache->getMagnitudeAt(col, y);
890 }
891
892 bool
893 FFTDataServer::getMagnitudesAt(size_t x, float *values, size_t minbin, size_t count, size_t step)
894 {
895 Profiler profiler("FFTDataServer::getMagnitudesAt", false);
896
897 if (x >= m_width) return false;
898
899 if (minbin >= m_height) minbin = m_height - 1;
900 if (count == 0) count = (m_height - minbin) / step;
901 else if (minbin + count * step > m_height) {
902 count = (m_height - minbin) / step;
903 }
904
905 size_t col;
906 FFTCache *cache = getCache(x, col);
907 if (!cache) return false;
908
909 if (!cache->haveSetColumnAt(col)) {
910 Profiler profiler("FFTDataServer::getMagnitudesAt: filling");
911 MutexLocker locker(&m_writeMutex,
912 "FFTDataServer::getMagnitudesAt: m_writeMutex");
913 fillColumn(x, true);
914 }
915
916 for (size_t i = 0; i < count; ++i) {
917 values[i] = cache->getMagnitudeAt(col, i * step + minbin);
918 }
919
920 return true;
885 } 921 }
886 922
887 float 923 float
888 FFTDataServer::getNormalizedMagnitudeAt(size_t x, size_t y) 924 FFTDataServer::getNormalizedMagnitudeAt(size_t x, size_t y)
889 { 925 {
894 size_t col; 930 size_t col;
895 FFTCache *cache = getCache(x, col); 931 FFTCache *cache = getCache(x, col);
896 if (!cache) return 0; 932 if (!cache) return 0;
897 933
898 if (!cache->haveSetColumnAt(col)) { 934 if (!cache->haveSetColumnAt(col)) {
899 fillColumn(x); 935 Profiler profiler("FFTDataServer::getNormalizedMagnitudeAt: filling");
936 // hold mutex so that write thread doesn't mess with class
937 // member data in fillColumn
938 MutexLocker locker(&m_writeMutex,
939 "FFTDataServer::getNormalizedMagnitudeAt: m_writeMutex");
940 fillColumn(x, true);
900 } 941 }
901 return cache->getNormalizedMagnitudeAt(col, y); 942 return cache->getNormalizedMagnitudeAt(col, y);
943 }
944
945 bool
946 FFTDataServer::getNormalizedMagnitudesAt(size_t x, float *values, size_t minbin, size_t count, size_t step)
947 {
948 Profiler profiler("FFTDataServer::getNormalizedMagnitudesAt", false);
949
950 if (x >= m_width) return false;
951
952 if (minbin >= m_height) minbin = m_height - 1;
953 if (count == 0) count = (m_height - minbin) / step;
954 else if (minbin + count * step > m_height) {
955 count = (m_height - minbin) / step;
956 }
957
958 size_t col;
959 FFTCache *cache = getCache(x, col);
960 if (!cache) return false;
961
962 if (!cache->haveSetColumnAt(col)) {
963 Profiler profiler("FFTDataServer::getNormalizedMagnitudesAt: filling");
964 MutexLocker locker(&m_writeMutex,
965 "FFTDataServer::getNormalizedMagnitudesAt: m_writeMutex");
966 fillColumn(x, true);
967 }
968
969 for (size_t i = 0; i < count; ++i) {
970 values[i] = cache->getNormalizedMagnitudeAt(col, i * step + minbin);
971 }
972
973 return true;
902 } 974 }
903 975
904 float 976 float
905 FFTDataServer::getMaximumMagnitudeAt(size_t x) 977 FFTDataServer::getMaximumMagnitudeAt(size_t x)
906 { 978 {
911 size_t col; 983 size_t col;
912 FFTCache *cache = getCache(x, col); 984 FFTCache *cache = getCache(x, col);
913 if (!cache) return 0; 985 if (!cache) return 0;
914 986
915 if (!cache->haveSetColumnAt(col)) { 987 if (!cache->haveSetColumnAt(col)) {
916 fillColumn(x); 988 Profiler profiler("FFTDataServer::getMaximumMagnitudeAt: filling");
989 // hold mutex so that write thread doesn't mess with class
990 // member data in fillColumn
991 MutexLocker locker(&m_writeMutex,
992 "FFTDataServer::getMaximumMagnitudeAt: m_writeMutex");
993 fillColumn(x, true);
917 } 994 }
918 return cache->getMaximumMagnitudeAt(col); 995 return cache->getMaximumMagnitudeAt(col);
919 } 996 }
920 997
921 float 998 float
928 size_t col; 1005 size_t col;
929 FFTCache *cache = getCache(x, col); 1006 FFTCache *cache = getCache(x, col);
930 if (!cache) return 0; 1007 if (!cache) return 0;
931 1008
932 if (!cache->haveSetColumnAt(col)) { 1009 if (!cache->haveSetColumnAt(col)) {
933 fillColumn(x); 1010 Profiler profiler("FFTDataServer::getPhaseAt: filling");
1011 // hold mutex so that write thread doesn't mess with class
1012 // member data in fillColumn
1013 MutexLocker locker(&m_writeMutex,
1014 "FFTDataServer::getPhaseAt: m_writeMutex");
1015 fillColumn(x, true);
934 } 1016 }
935 return cache->getPhaseAt(col, y); 1017 return cache->getPhaseAt(col, y);
1018 }
1019
1020 bool
1021 FFTDataServer::getPhasesAt(size_t x, float *values, size_t minbin, size_t count, size_t step)
1022 {
1023 Profiler profiler("FFTDataServer::getPhasesAt", false);
1024
1025 if (x >= m_width) return false;
1026
1027 if (minbin >= m_height) minbin = m_height - 1;
1028 if (count == 0) count = (m_height - minbin) / step;
1029 else if (minbin + count * step > m_height) {
1030 count = (m_height - minbin) / step;
1031 }
1032
1033 size_t col;
1034 FFTCache *cache = getCache(x, col);
1035 if (!cache) return false;
1036
1037 if (!cache->haveSetColumnAt(col)) {
1038 Profiler profiler("FFTDataServer::getPhasesAt: filling");
1039 MutexLocker locker(&m_writeMutex,
1040 "FFTDataServer::getPhasesAt: m_writeMutex");
1041 fillColumn(x, true);
1042 }
1043
1044 for (size_t i = 0; i < count; ++i) {
1045 values[i] = cache->getPhaseAt(col, i * step + minbin);
1046 }
1047
1048 return true;
936 } 1049 }
937 1050
938 void 1051 void
939 FFTDataServer::getValuesAt(size_t x, size_t y, float &real, float &imaginary) 1052 FFTDataServer::getValuesAt(size_t x, size_t y, float &real, float &imaginary)
940 { 1053 {
954 imaginary = 0; 1067 imaginary = 0;
955 return; 1068 return;
956 } 1069 }
957 1070
958 if (!cache->haveSetColumnAt(col)) { 1071 if (!cache->haveSetColumnAt(col)) {
1072 Profiler profiler("FFTDataServer::getValuesAt: filling");
959 #ifdef DEBUG_FFT_SERVER 1073 #ifdef DEBUG_FFT_SERVER
960 std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl; 1074 std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl;
961 #endif 1075 #endif
962 fillColumn(x); 1076 // hold mutex so that write thread doesn't mess with class
1077 // member data in fillColumn
1078 MutexLocker locker(&m_writeMutex,
1079 "FFTDataServer::getValuesAt: m_writeMutex");
1080 fillColumn(x, true);
963 } 1081 }
964 1082
965 cache->getValuesAt(col, y, real, imaginary); 1083 cache->getValuesAt(col, y, real, imaginary);
966 } 1084 }
967 1085
989 1107
990 return cache->haveSetColumnAt(col); 1108 return cache->haveSetColumnAt(col);
991 } 1109 }
992 1110
993 void 1111 void
994 FFTDataServer::fillColumn(size_t x) 1112 FFTDataServer::fillColumn(size_t x, bool lockHeld)
995 { 1113 {
996 Profiler profiler("FFTDataServer::fillColumn", false); 1114 Profiler profiler("FFTDataServer::fillColumn", false);
997 1115
998 if (!m_model->isReady()) { 1116 if (!m_model->isReady()) {
999 std::cerr << "WARNING: FFTDataServer::fillColumn(" 1117 std::cerr << "WARNING: FFTDataServer::fillColumn("
1020 std::cout << "FFTDataServer::fillColumn(" << x << ")" << std::endl; 1138 std::cout << "FFTDataServer::fillColumn(" << x << ")" << std::endl;
1021 #endif 1139 #endif
1022 FFTCache *cache = getCache(x, col); 1140 FFTCache *cache = getCache(x, col);
1023 if (!cache) return; 1141 if (!cache) return;
1024 1142
1025 MutexLocker locker(&m_writeMutex, 1143 {
1026 "FFTDataServer::m_writeMutex[fillColumn]"); 1144 MutexLocker locker(lockHeld ? 0 : &m_writeMutex,
1027 1145 "FFTDataServer::fillColumn::m_writeMutex [1]");
1028 if (cache->haveSetColumnAt(col)) return; 1146
1147 if (cache->haveSetColumnAt(col)) return;
1148 }
1149
1150 int winsize = m_windowSize;
1151 int fftsize = m_fftSize;
1152 int hs = fftsize/2;
1153
1154 int pfx = 0;
1155 int off = (fftsize - winsize) / 2;
1029 1156
1030 int startFrame = m_windowIncrement * x; 1157 int startFrame = m_windowIncrement * x;
1031 int endFrame = startFrame + m_windowSize; 1158 int endFrame = startFrame + m_windowSize;
1032 1159
1033 startFrame -= int(m_windowSize) / 2; 1160 startFrame -= winsize / 2;
1034 endFrame -= int(m_windowSize) / 2; 1161 endFrame -= winsize / 2;
1035 size_t pfx = 0; 1162
1036 1163 for (int i = 0; i < off; ++i) {
1037 size_t off = (m_fftSize - m_windowSize) / 2;
1038
1039 for (size_t i = 0; i < off; ++i) {
1040 m_fftInput[i] = 0.0; 1164 m_fftInput[i] = 0.0;
1041 m_fftInput[m_fftSize - i - 1] = 0.0; 1165 }
1166
1167 for (int i = 0; i < off; ++i) {
1168 m_fftInput[fftsize - i - 1] = 0.0;
1042 } 1169 }
1043 1170
1044 if (startFrame < 0) { 1171 if (startFrame < 0) {
1045 pfx = size_t(-startFrame); 1172 pfx = -startFrame;
1046 for (size_t i = 0; i < pfx; ++i) { 1173 for (int i = 0; i < pfx; ++i) {
1047 m_fftInput[off + i] = 0.0; 1174 m_fftInput[off + i] = 0.0;
1048 } 1175 }
1049 } 1176 }
1050 1177
1051 #ifdef DEBUG_FFT_SERVER_FILL 1178 #ifdef DEBUG_FFT_SERVER_FILL
1055 << off + pfx << " in buffer of size " << m_fftSize 1182 << off + pfx << " in buffer of size " << m_fftSize
1056 << " with window size " << m_windowSize 1183 << " with window size " << m_windowSize
1057 << " from channel " << m_channel << std::endl; 1184 << " from channel " << m_channel << std::endl;
1058 #endif 1185 #endif
1059 1186
1060 size_t count = 0; 1187 int count = 0;
1061 if (endFrame > startFrame + pfx) count = endFrame - (startFrame + pfx); 1188 if (endFrame > startFrame + pfx) count = endFrame - (startFrame + pfx);
1062 1189
1063 size_t got = m_model->getData(m_channel, startFrame + pfx, 1190 int got = m_model->getData(m_channel, startFrame + pfx,
1064 count, m_fftInput + off + pfx); 1191 count, m_fftInput + off + pfx);
1065 1192
1066 while (got + pfx < m_windowSize) { 1193 while (got + pfx < winsize) {
1067 m_fftInput[off + got + pfx] = 0.0; 1194 m_fftInput[off + got + pfx] = 0.0;
1068 ++got; 1195 ++got;
1069 } 1196 }
1070 1197
1071 if (m_channel == -1) { 1198 if (m_channel == -1) {
1072 int channels = m_model->getChannelCount(); 1199 int channels = m_model->getChannelCount();
1073 if (channels > 1) { 1200 if (channels > 1) {
1074 for (size_t i = 0; i < m_windowSize; ++i) { 1201 for (int i = 0; i < winsize; ++i) {
1075 m_fftInput[off + i] /= channels; 1202 m_fftInput[off + i] /= channels;
1076 } 1203 }
1077 } 1204 }
1078 } 1205 }
1079 1206
1080 m_windower.cut(m_fftInput + off); 1207 m_windower.cut(m_fftInput + off);
1081 1208
1082 for (size_t i = 0; i < m_fftSize/2; ++i) { 1209 for (int i = 0; i < hs; ++i) {
1083 fftsample temp = m_fftInput[i]; 1210 fftsample temp = m_fftInput[i];
1084 m_fftInput[i] = m_fftInput[i + m_fftSize/2]; 1211 m_fftInput[i] = m_fftInput[i + hs];
1085 m_fftInput[i + m_fftSize/2] = temp; 1212 m_fftInput[i + hs] = temp;
1086 } 1213 }
1087 1214
1088 fftf_execute(m_fftPlan); 1215 fftf_execute(m_fftPlan);
1089 1216
1090 fftsample factor = 0.0; 1217 // If our cache uses polar storage, it's more friendly for us to
1091 1218 // do the conversion before taking the write mutex
1092 for (size_t i = 0; i <= m_fftSize/2; ++i) { 1219
1093 1220 float factor = 0.f;
1094 m_workbuffer[i] = m_fftOutput[i][0]; 1221
1095 m_workbuffer[i + m_fftSize/2 + 1] = m_fftOutput[i][1]; 1222 if (cache->getStorageType() == FFTCache::Compact ||
1096 } 1223 cache->getStorageType() == FFTCache::Polar) {
1097 1224
1098 cache->setColumnAt(col, 1225 for (int i = 0; i <= hs; ++i) {
1099 m_workbuffer, 1226 fftsample real = m_fftOutput[i][0];
1100 m_workbuffer + m_fftSize/2+1); 1227 fftsample imag = m_fftOutput[i][1];
1228 float mag = sqrtf(real * real + imag * imag);
1229 m_workbuffer[i] = mag;
1230 m_workbuffer[i + hs + 1] = atan2f(imag, real);
1231 if (mag > factor) factor = mag;
1232 }
1233
1234 } else {
1235
1236 for (int i = 0; i <= hs; ++i) {
1237 m_workbuffer[i] = m_fftOutput[i][0];
1238 m_workbuffer[i + hs + 1] = m_fftOutput[i][1];
1239 }
1240 }
1241
1242 Profiler subprof("FFTDataServer::fillColumn: set to cache");
1243
1244 {
1245 MutexLocker locker(lockHeld ? 0 : &m_writeMutex,
1246 "FFTDataServer::fillColumn: m_writeMutex [2]");
1247
1248 if (cache->getStorageType() == FFTCache::Compact ||
1249 cache->getStorageType() == FFTCache::Polar) {
1250
1251 cache->setColumnAt(col,
1252 m_workbuffer,
1253 m_workbuffer + hs + 1,
1254 factor);
1255
1256 } else {
1257
1258 cache->setColumnAt(col,
1259 m_workbuffer,
1260 m_workbuffer + hs + 1);
1261 }
1262 }
1101 1263
1102 if (m_suspended) { 1264 if (m_suspended) {
1103 // std::cerr << "FFTDataServer::fillColumn(" << x << "): calling resume" << std::endl; 1265 // std::cerr << "FFTDataServer::fillColumn(" << x << "): calling resume" << std::endl;
1104 // resume(); 1266 // resume();
1105 } 1267 }
1172 1334
1173 if (m_fillFrom > start) { 1335 if (m_fillFrom > start) {
1174 1336
1175 for (size_t f = m_fillFrom; f < end; f += m_server.m_windowIncrement) { 1337 for (size_t f = m_fillFrom; f < end; f += m_server.m_windowIncrement) {
1176 1338
1177 m_server.fillColumn(int((f - start) / m_server.m_windowIncrement)); 1339 m_server.fillColumn(int((f - start) / m_server.m_windowIncrement),
1340 false);
1178 1341
1179 if (m_server.m_exiting) return; 1342 if (m_server.m_exiting) return;
1180 1343
1181 while (m_server.m_suspended) { 1344 while (m_server.m_suspended) {
1182 #ifdef DEBUG_FFT_SERVER 1345 #ifdef DEBUG_FFT_SERVER
1183 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspended, waiting..." << std::endl; 1346 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspended, waiting..." << std::endl;
1184 #endif 1347 #endif
1185 { 1348 {
1186 MutexLocker locker(&m_server.m_writeMutex, 1349 MutexLocker locker(&m_server.m_writeMutex,
1187 "FFTDataServer::m_writeMutex[run/1]"); 1350 "FFTDataServer::run::m_writeMutex [1]");
1188 m_server.m_condition.wait(&m_server.m_writeMutex, 10000); 1351 m_server.m_condition.wait(&m_server.m_writeMutex, 10000);
1189 } 1352 }
1190 #ifdef DEBUG_FFT_SERVER 1353 #ifdef DEBUG_FFT_SERVER
1191 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): waited" << std::endl; 1354 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): waited" << std::endl;
1192 #endif 1355 #endif
1212 1375
1213 size_t baseCompletion = m_completion; 1376 size_t baseCompletion = m_completion;
1214 1377
1215 for (size_t f = start; f < remainingEnd; f += m_server.m_windowIncrement) { 1378 for (size_t f = start; f < remainingEnd; f += m_server.m_windowIncrement) {
1216 1379
1217 m_server.fillColumn(int((f - start) / m_server.m_windowIncrement)); 1380 m_server.fillColumn(int((f - start) / m_server.m_windowIncrement),
1381 false);
1218 1382
1219 if (m_server.m_exiting) return; 1383 if (m_server.m_exiting) return;
1220 1384
1221 while (m_server.m_suspended) { 1385 while (m_server.m_suspended) {
1222 #ifdef DEBUG_FFT_SERVER 1386 #ifdef DEBUG_FFT_SERVER
1223 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspended, waiting..." << std::endl; 1387 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspended, waiting..." << std::endl;
1224 #endif 1388 #endif
1225 { 1389 {
1226 MutexLocker locker(&m_server.m_writeMutex, 1390 MutexLocker locker(&m_server.m_writeMutex,
1227 "FFTDataServer::m_writeMutex[run/2]"); 1391 "FFTDataServer::run::m_writeMutex [2]");
1228 m_server.m_condition.wait(&m_server.m_writeMutex, 10000); 1392 m_server.m_condition.wait(&m_server.m_writeMutex, 10000);
1229 } 1393 }
1230 if (m_server.m_exiting) return; 1394 if (m_server.m_exiting) return;
1231 } 1395 }
1232 1396