comparison data/fft/FFTDataServer.cpp @ 847:2d53205f70cd tonioni

Merge from default branch
author Chris Cannam
date Tue, 26 Nov 2013 14:37:01 +0000
parents 97c53dfaf798 e802e550a1f2
children 166e3fc1e962
comparison
equal deleted inserted replaced
841:226733f3cf3f 847:2d53205f70cd
290 290
291 return; 291 return;
292 } 292 }
293 } 293 }
294 294
295 std::cerr << "ERROR: FFTDataServer::claimInstance: instance " 295 cerr << "ERROR: FFTDataServer::claimInstance: instance "
296 << server << " unknown!" << std::endl; 296 << server << " unknown!" << endl;
297 } 297 }
298 298
299 void 299 void
300 FFTDataServer::releaseInstance(FFTDataServer *server) 300 FFTDataServer::releaseInstance(FFTDataServer *server)
301 { 301 {
324 // destroyed, so that we can delete all of its fft server instances 324 // destroyed, so that we can delete all of its fft server instances
325 325
326 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { 326 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) {
327 if (i->second.first == server) { 327 if (i->second.first == server) {
328 if (i->second.second == 0) { 328 if (i->second.second == 0) {
329 std::cerr << "ERROR: FFTDataServer::releaseInstance(" 329 cerr << "ERROR: FFTDataServer::releaseInstance("
330 << server << "): instance not allocated" << std::endl; 330 << server << "): instance not allocated" << endl;
331 } else if (--i->second.second == 0) { 331 } else if (--i->second.second == 0) {
332 /*!!! 332 /*!!!
333 if (server->m_lastUsedCache == -1) { // never used 333 if (server->m_lastUsedCache == -1) { // never used
334 #ifdef DEBUG_FFT_SERVER 334 #ifdef DEBUG_FFT_SERVER
335 std::cerr << "FFTDataServer::releaseInstance: instance " 335 std::cerr << "FFTDataServer::releaseInstance: instance "
347 #endif 347 #endif
348 bool found = false; 348 bool found = false;
349 for (ServerQueue::iterator j = m_releasedServers.begin(); 349 for (ServerQueue::iterator j = m_releasedServers.begin();
350 j != m_releasedServers.end(); ++j) { 350 j != m_releasedServers.end(); ++j) {
351 if (*j == server) { 351 if (*j == server) {
352 std::cerr << "ERROR: FFTDataServer::releaseInstance(" 352 cerr << "ERROR: FFTDataServer::releaseInstance("
353 << server << "): server is already in " 353 << server << "): server is already in "
354 << "released servers list" << std::endl; 354 << "released servers list" << endl;
355 found = true; 355 found = true;
356 } 356 }
357 } 357 }
358 if (!found) m_releasedServers.push_back(server); 358 if (!found) m_releasedServers.push_back(server);
359 server->suspend(); 359 server->suspend();
368 } 368 }
369 return; 369 return;
370 } 370 }
371 } 371 }
372 372
373 std::cerr << "ERROR: FFTDataServer::releaseInstance(" << server << "): " 373 cerr << "ERROR: FFTDataServer::releaseInstance(" << server << "): "
374 << "instance not found" << std::endl; 374 << "instance not found" << endl;
375 } 375 }
376 376
377 void 377 void
378 FFTDataServer::purgeLimbo(int maxSize) 378 FFTDataServer::purgeLimbo(int maxSize)
379 { 379 {
396 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) { 396 for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) {
397 397
398 if (i->second.first == server) { 398 if (i->second.first == server) {
399 found = true; 399 found = true;
400 if (i->second.second > 0) { 400 if (i->second.second > 0) {
401 std::cerr << "ERROR: FFTDataServer::purgeLimbo: Server " 401 cerr << "ERROR: FFTDataServer::purgeLimbo: Server "
402 << server << " is in released queue, but still has non-zero refcount " 402 << server << " is in released queue, but still has non-zero refcount "
403 << i->second.second << std::endl; 403 << i->second.second << endl;
404 // ... so don't delete it 404 // ... so don't delete it
405 break; 405 break;
406 } 406 }
407 #ifdef DEBUG_FFT_SERVER 407 #ifdef DEBUG_FFT_SERVER
408 std::cerr << "FFTDataServer::purgeLimbo: looks OK, erasing it" 408 std::cerr << "FFTDataServer::purgeLimbo: looks OK, erasing it"
414 break; 414 break;
415 } 415 }
416 } 416 }
417 417
418 if (!found) { 418 if (!found) {
419 std::cerr << "ERROR: FFTDataServer::purgeLimbo: Server " 419 cerr << "ERROR: FFTDataServer::purgeLimbo: Server "
420 << server << " is in released queue, but not in server map!" 420 << server << " is in released queue, but not in server map!"
421 << std::endl; 421 << endl;
422 delete server; 422 delete server;
423 } 423 }
424 424
425 m_releasedServers.pop_front(); 425 m_releasedServers.pop_front();
426 } 426 }
453 std::cerr << "FFTDataServer::modelAboutToBeDeleted: server is " 453 std::cerr << "FFTDataServer::modelAboutToBeDeleted: server is "
454 << server << std::endl; 454 << server << std::endl;
455 #endif 455 #endif
456 456
457 if (i->second.second > 0) { 457 if (i->second.second > 0) {
458 std::cerr << "WARNING: FFTDataServer::modelAboutToBeDeleted: Model " << model << " (\"" << model->objectName() << "\") is about to be deleted, but is still being referred to by FFT server " << server << " with non-zero refcount " << i->second.second << std::endl; 458 cerr << "WARNING: FFTDataServer::modelAboutToBeDeleted: Model " << model << " (\"" << model->objectName() << "\") is about to be deleted, but is still being referred to by FFT server " << server << " with non-zero refcount " << i->second.second << endl;
459 server->suspendWrites(); 459 server->suspendWrites();
460 return; 460 return;
461 } 461 }
462 for (ServerQueue::iterator j = m_releasedServers.begin(); 462 for (ServerQueue::iterator j = m_releasedServers.begin();
463 j != m_releasedServers.end(); ++j) { 463 j != m_releasedServers.end(); ++j) {
507 m_exiting(false), 507 m_exiting(false),
508 m_suspended(true), //!!! or false? 508 m_suspended(true), //!!! or false?
509 m_fillThread(0) 509 m_fillThread(0)
510 { 510 {
511 #ifdef DEBUG_FFT_SERVER 511 #ifdef DEBUG_FFT_SERVER
512 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "])::FFTDataServer" << std::endl; 512 cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "])::FFTDataServer" << endl;
513 #endif 513 #endif
514 514
515 //!!! end is not correct until model finished reading -- what to do??? 515 //!!! end is not correct until model finished reading -- what to do???
516 516
517 size_t start = m_model->getStartFrame(); 517 size_t start = m_model->getStartFrame();
519 519
520 m_width = (end - start) / m_windowIncrement + 1; 520 m_width = (end - start) / m_windowIncrement + 1;
521 m_height = m_fftSize / 2 + 1; // DC == 0, Nyquist == fftsize/2 521 m_height = m_fftSize / 2 + 1; // DC == 0, Nyquist == fftsize/2
522 522
523 #ifdef DEBUG_FFT_SERVER 523 #ifdef DEBUG_FFT_SERVER
524 std::cerr << "FFTDataServer(" << this << "): dimensions are " 524 cerr << "FFTDataServer(" << this << "): dimensions are "
525 << m_width << "x" << m_height << std::endl; 525 << m_width << "x" << m_height << endl;
526 #endif 526 #endif
527 527
528 size_t maxCacheSize = 20 * 1024 * 1024; 528 size_t maxCacheSize = 20 * 1024 * 1024;
529 size_t columnSize = m_height * sizeof(fftsample) * 2 + sizeof(fftsample); 529 size_t columnSize = m_height * sizeof(fftsample) * 2 + sizeof(fftsample);
530 if (m_width * columnSize < maxCacheSize * 2) m_cacheWidth = m_width; 530 if (m_width * columnSize < maxCacheSize * 2) m_cacheWidth = m_width;
531 else m_cacheWidth = maxCacheSize / columnSize; 531 else m_cacheWidth = maxCacheSize / columnSize;
532 532
533 #ifdef DEBUG_FFT_SERVER 533 #ifdef DEBUG_FFT_SERVER
534 std::cerr << "FFTDataServer(" << this << "): cache width nominal " 534 cerr << "FFTDataServer(" << this << "): cache width nominal "
535 << m_cacheWidth << ", actual "; 535 << m_cacheWidth << ", actual ";
536 #endif 536 #endif
537 537
538 int bits = 0; 538 int bits = 0;
539 while (m_cacheWidth > 1) { m_cacheWidth >>= 1; ++bits; } 539 while (m_cacheWidth > 1) { m_cacheWidth >>= 1; ++bits; }
541 m_cacheWidth = 2; 541 m_cacheWidth = 2;
542 while (bits) { m_cacheWidth <<= 1; --bits; } 542 while (bits) { m_cacheWidth <<= 1; --bits; }
543 m_cacheWidthMask = m_cacheWidth - 1; 543 m_cacheWidthMask = m_cacheWidth - 1;
544 544
545 #ifdef DEBUG_FFT_SERVER 545 #ifdef DEBUG_FFT_SERVER
546 std::cerr << m_cacheWidth << " (power " << m_cacheWidthPower << ", mask " 546 cerr << m_cacheWidth << " (power " << m_cacheWidthPower << ", mask "
547 << m_cacheWidthMask << ")" << std::endl; 547 << m_cacheWidthMask << ")" << endl;
548 #endif 548 #endif
549 549
550 if (m_criteria == StorageAdviser::NoCriteria) { 550 if (m_criteria == StorageAdviser::NoCriteria) {
551 551
552 // assume "spectrogram" criteria for polar ffts, and "feature 552 // assume "spectrogram" criteria for polar ffts, and "feature
579 m_fftInput, 579 m_fftInput,
580 m_fftOutput, 580 m_fftOutput,
581 FFTW_MEASURE); 581 FFTW_MEASURE);
582 582
583 if (!m_fftPlan) { 583 if (!m_fftPlan) {
584 std::cerr << "ERROR: fftf_plan_dft_r2c_1d(" << m_windowSize << ") failed!" << std::endl; 584 cerr << "ERROR: fftf_plan_dft_r2c_1d(" << m_windowSize << ") failed!" << endl;
585 throw(0); 585 throw(0);
586 } 586 }
587 587
588 m_fillThread = new FillThread(*this, fillFromColumn); 588 m_fillThread = new FillThread(*this, fillFromColumn);
589 } 589 }
590 590
591 FFTDataServer::~FFTDataServer() 591 FFTDataServer::~FFTDataServer()
592 { 592 {
593 #ifdef DEBUG_FFT_SERVER 593 #ifdef DEBUG_FFT_SERVER
594 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "])::~FFTDataServer()" << std::endl; 594 cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "])::~FFTDataServer()" << endl;
595 #endif 595 #endif
596 596
597 m_suspended = false; 597 m_suspended = false;
598 m_exiting = true; 598 m_exiting = true;
599 m_condition.wakeAll(); 599 m_condition.wakeAll();
619 619
620 void 620 void
621 FFTDataServer::deleteProcessingData() 621 FFTDataServer::deleteProcessingData()
622 { 622 {
623 #ifdef DEBUG_FFT_SERVER 623 #ifdef DEBUG_FFT_SERVER
624 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): deleteProcessingData" << std::endl; 624 cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): deleteProcessingData" << endl;
625 #endif 625 #endif
626 if (m_fftInput) { 626 if (m_fftInput) {
627 fftf_destroy_plan(m_fftPlan); 627 fftf_destroy_plan(m_fftPlan);
628 fftf_free(m_fftInput); 628 fftf_free(m_fftInput);
629 fftf_free(m_fftOutput); 629 fftf_free(m_fftOutput);
634 634
635 void 635 void
636 FFTDataServer::suspend() 636 FFTDataServer::suspend()
637 { 637 {
638 #ifdef DEBUG_FFT_SERVER 638 #ifdef DEBUG_FFT_SERVER
639 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspend" << std::endl; 639 cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspend" << endl;
640 #endif 640 #endif
641 Profiler profiler("FFTDataServer::suspend", false); 641 Profiler profiler("FFTDataServer::suspend", false);
642 642
643 QMutexLocker locker(&m_fftBuffersLock); 643 QMutexLocker locker(&m_fftBuffersLock);
644 m_suspended = true; 644 m_suspended = true;
646 646
647 void 647 void
648 FFTDataServer::suspendWrites() 648 FFTDataServer::suspendWrites()
649 { 649 {
650 #ifdef DEBUG_FFT_SERVER 650 #ifdef DEBUG_FFT_SERVER
651 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspendWrites" << std::endl; 651 cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspendWrites" << endl;
652 #endif 652 #endif
653 Profiler profiler("FFTDataServer::suspendWrites", false); 653 Profiler profiler("FFTDataServer::suspendWrites", false);
654 654
655 m_suspended = true; 655 m_suspended = true;
656 } 656 }
657 657
658 void 658 void
659 FFTDataServer::resume() 659 FFTDataServer::resume()
660 { 660 {
661 #ifdef DEBUG_FFT_SERVER 661 #ifdef DEBUG_FFT_SERVER
662 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): resume" << std::endl; 662 cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): resume" << endl;
663 #endif 663 #endif
664 Profiler profiler("FFTDataServer::resume", false); 664 Profiler profiler("FFTDataServer::resume", false);
665 665
666 m_suspended = false; 666 m_suspended = false;
667 if (m_fillThread) { 667 if (m_fillThread) {
715 715
716 recommendation = 716 recommendation =
717 StorageAdviser::recommend(m_criteria, minimumSize, maximumSize); 717 StorageAdviser::recommend(m_criteria, minimumSize, maximumSize);
718 } 718 }
719 719
720 // std::cerr << "Recommendation was: " << recommendation << std::endl; 720 // cerr << "Recommendation was: " << recommendation << endl;
721 721
722 memoryCache = false; 722 memoryCache = false;
723 723
724 if ((recommendation & StorageAdviser::UseMemory) || 724 if ((recommendation & StorageAdviser::UseMemory) ||
725 (recommendation & StorageAdviser::PreferMemory)) { 725 (recommendation & StorageAdviser::PreferMemory)) {
728 728
729 compactCache = canCompact && 729 compactCache = canCompact &&
730 (recommendation & StorageAdviser::ConserveSpace); 730 (recommendation & StorageAdviser::ConserveSpace);
731 731
732 #ifdef DEBUG_FFT_SERVER 732 #ifdef DEBUG_FFT_SERVER
733 std::cerr << "FFTDataServer: memory cache = " << memoryCache << ", compact cache = " << compactCache << std::endl; 733 cerr << "FFTDataServer: memory cache = " << memoryCache << ", compact cache = " << compactCache << endl;
734 734
735 std::cerr << "Width " << w << " of " << m_width << ", height " << h << ", size " << w * h << std::endl; 735 cerr << "Width " << w << " of " << m_width << ", height " << h << ", size " << w * h << endl;
736 #endif 736 #endif
737 } 737 }
738 738
739 bool 739 bool
740 FFTDataServer::makeCache(int c) 740 FFTDataServer::makeCache(int c)
790 } catch (std::bad_alloc) { 790 } catch (std::bad_alloc) {
791 791
792 delete cb->memoryCache; 792 delete cb->memoryCache;
793 cb->memoryCache = 0; 793 cb->memoryCache = 0;
794 794
795 std::cerr << "WARNING: Memory allocation failed when creating" 795 cerr << "WARNING: Memory allocation failed when creating"
796 << " FFT memory cache no. " << c << " of " << width 796 << " FFT memory cache no. " << c << " of " << width
797 << "x" << m_height << " (of total width " << m_width 797 << "x" << m_height << " (of total width " << m_width
798 << "): falling back to disc cache" << std::endl; 798 << "): falling back to disc cache" << endl;
799 799
800 memoryCache = false; 800 memoryCache = false;
801 } 801 }
802 } 802 }
803 803
817 } catch (std::exception &e) { 817 } catch (std::exception &e) {
818 818
819 delete cb->fileCacheWriter; 819 delete cb->fileCacheWriter;
820 cb->fileCacheWriter = 0; 820 cb->fileCacheWriter = 0;
821 821
822 std::cerr << "ERROR: Failed to construct disc cache for FFT data: " 822 cerr << "ERROR: Failed to construct disc cache for FFT data: "
823 << e.what() << std::endl; 823 << e.what() << endl;
824 824
825 throw; 825 throw;
826 } 826 }
827 } 827 }
828 828
856 } catch (std::exception &e) { 856 } catch (std::exception &e) {
857 857
858 delete cb->fileCacheReader[me]; 858 delete cb->fileCacheReader[me];
859 cb->fileCacheReader.erase(me); 859 cb->fileCacheReader.erase(me);
860 860
861 std::cerr << "ERROR: Failed to construct disc cache reader for FFT data: " 861 cerr << "ERROR: Failed to construct disc cache reader for FFT data: "
862 << e.what() << std::endl; 862 << e.what() << endl;
863 return false; 863 return false;
864 } 864 }
865 865
866 // erase a reader that looks like it may no longer going to be 866 // erase a reader that looks like it may no longer going to be
867 // used by this thread for a while (leaving alone the current 867 // used by this thread for a while (leaving alone the current
1216 FFTDataServer::fillColumn(size_t x) 1216 FFTDataServer::fillColumn(size_t x)
1217 { 1217 {
1218 Profiler profiler("FFTDataServer::fillColumn", false); 1218 Profiler profiler("FFTDataServer::fillColumn", false);
1219 1219
1220 if (!m_model->isReady()) { 1220 if (!m_model->isReady()) {
1221 std::cerr << "WARNING: FFTDataServer::fillColumn(" 1221 cerr << "WARNING: FFTDataServer::fillColumn("
1222 << x << "): model not yet ready" << std::endl; 1222 << x << "): model not yet ready" << endl;
1223 return; 1223 return;
1224 } 1224 }
1225 /* 1225 /*
1226 if (!m_fftInput) { 1226 if (!m_fftInput) {
1227 std::cerr << "WARNING: FFTDataServer::fillColumn(" << x << "): " 1227 cerr << "WARNING: FFTDataServer::fillColumn(" << x << "): "
1228 << "input has already been completed and discarded?" 1228 << "input has already been completed and discarded?"
1229 << std::endl; 1229 << endl;
1230 return; 1230 return;
1231 } 1231 }
1232 */ 1232 */
1233 if (x >= m_width) { 1233 if (x >= m_width) {
1234 std::cerr << "WARNING: FFTDataServer::fillColumn(" << x << "): " 1234 cerr << "WARNING: FFTDataServer::fillColumn(" << x << "): "
1235 << "x > width (" << x << " > " << m_width << ")" 1235 << "x > width (" << x << " > " << m_width << ")"
1236 << std::endl; 1236 << endl;
1237 return; 1237 return;
1238 } 1238 }
1239 1239
1240 size_t col; 1240 size_t col;
1241 #ifdef DEBUG_FFT_SERVER_FILL 1241 #ifdef DEBUG_FFT_SERVER_FILL
1242 std::cout << "FFTDataServer::fillColumn(" << x << ")" << std::endl; 1242 cout << "FFTDataServer::fillColumn(" << x << ")" << endl;
1243 #endif 1243 #endif
1244 FFTCacheWriter *cache = getCacheWriter(x, col); 1244 FFTCacheWriter *cache = getCacheWriter(x, col);
1245 if (!cache) return; 1245 if (!cache) return;
1246 1246
1247 int winsize = m_windowSize; 1247 int winsize = m_windowSize;
1277 if (cache->haveSetColumnAt(x & m_cacheWidthMask)) { 1277 if (cache->haveSetColumnAt(x & m_cacheWidthMask)) {
1278 return; 1278 return;
1279 } 1279 }
1280 1280
1281 if (!m_fftInput) { 1281 if (!m_fftInput) {
1282 std::cerr << "WARNING: FFTDataServer::fillColumn(" << x << "): " 1282 cerr << "WARNING: FFTDataServer::fillColumn(" << x << "): "
1283 << "input has already been completed and discarded?" 1283 << "input has already been completed and discarded?"
1284 << std::endl; 1284 << endl;
1285 return; 1285 return;
1286 } 1286 }
1287 1287
1288 for (int i = 0; i < off; ++i) { 1288 for (int i = 0; i < off; ++i) {
1289 m_fftInput[i] = 0.0; 1289 m_fftInput[i] = 0.0;
1486 1486
1487 if (m_server.m_exiting) return; 1487 if (m_server.m_exiting) return;
1488 1488
1489 while (m_server.m_suspended) { 1489 while (m_server.m_suspended) {
1490 #ifdef DEBUG_FFT_SERVER 1490 #ifdef DEBUG_FFT_SERVER
1491 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspended, waiting..." << std::endl; 1491 cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspended, waiting..." << endl;
1492 #endif 1492 #endif
1493 MutexLocker locker(&m_server.m_fftBuffersLock, 1493 MutexLocker locker(&m_server.m_fftBuffersLock,
1494 "FFTDataServer::run::m_fftBuffersLock [1]"); 1494 "FFTDataServer::run::m_fftBuffersLock [1]");
1495 if (m_server.m_suspended && !m_server.m_exiting) { 1495 if (m_server.m_suspended && !m_server.m_exiting) {
1496 m_server.m_condition.wait(&m_server.m_fftBuffersLock, 10000); 1496 m_server.m_condition.wait(&m_server.m_fftBuffersLock, 10000);
1497 } 1497 }
1498 #ifdef DEBUG_FFT_SERVER 1498 #ifdef DEBUG_FFT_SERVER
1499 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): waited" << std::endl; 1499 cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): waited" << endl;
1500 #endif 1500 #endif
1501 if (m_server.m_exiting) return; 1501 if (m_server.m_exiting) return;
1502 } 1502 }
1503 1503
1504 if (++counter == updateAt) { 1504 if (++counter == updateAt) {
1535 1535
1536 if (m_server.m_exiting) return; 1536 if (m_server.m_exiting) return;
1537 1537
1538 while (m_server.m_suspended) { 1538 while (m_server.m_suspended) {
1539 #ifdef DEBUG_FFT_SERVER 1539 #ifdef DEBUG_FFT_SERVER
1540 std::cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspended, waiting..." << std::endl; 1540 cerr << "FFTDataServer(" << this << " [" << (void *)QThread::currentThreadId() << "]): suspended, waiting..." << endl;
1541 #endif 1541 #endif
1542 { 1542 {
1543 MutexLocker locker(&m_server.m_fftBuffersLock, 1543 MutexLocker locker(&m_server.m_fftBuffersLock,
1544 "FFTDataServer::run::m_fftBuffersLock [2]"); 1544 "FFTDataServer::run::m_fftBuffersLock [2]");
1545 if (m_server.m_suspended && !m_server.m_exiting) { 1545 if (m_server.m_suspended && !m_server.m_exiting) {