Mercurial > hg > svcore
comparison data/fft/FFTDataServer.cpp @ 200:2f2d282d45d0
* Somewhat better handling of running out of memory or disc space
author | Chris Cannam |
---|---|
date | Mon, 13 Nov 2006 14:48:57 +0000 |
parents | c92a605f6b59 |
children | 91fdc752e540 |
comparison
equal
deleted
inserted
replaced
199:1d789d688f59 | 200:2f2d282d45d0 |
---|---|
21 #include "model/DenseTimeValueModel.h" | 21 #include "model/DenseTimeValueModel.h" |
22 | 22 |
23 #include "system/System.h" | 23 #include "system/System.h" |
24 | 24 |
25 #include "base/StorageAdviser.h" | 25 #include "base/StorageAdviser.h" |
26 #include "base/Exceptions.h" | |
26 #include "base/Profiler.h" | 27 #include "base/Profiler.h" |
28 | |
29 #include <QMessageBox> | |
30 #include <QApplication> | |
27 | 31 |
28 | 32 |
29 //#define DEBUG_FFT_SERVER 1 | 33 //#define DEBUG_FFT_SERVER 1 |
30 //#define DEBUG_FFT_SERVER_FILL 1 | 34 //#define DEBUG_FFT_SERVER_FILL 1 |
31 | 35 |
74 | 78 |
75 if ((server = findServer(npn))) { | 79 if ((server = findServer(npn))) { |
76 return server; | 80 return server; |
77 } | 81 } |
78 | 82 |
79 m_servers[n] = ServerCountPair | 83 try { |
80 (new FFTDataServer(n, | 84 server = new FFTDataServer(n, |
81 model, | 85 model, |
82 channel, | 86 channel, |
83 windowType, | 87 windowType, |
84 windowSize, | 88 windowSize, |
85 windowIncrement, | 89 windowIncrement, |
86 fftSize, | 90 fftSize, |
87 polar, | 91 polar, |
88 fillFromColumn), | 92 fillFromColumn); |
89 1); | 93 } catch (InsufficientDiscSpace) { |
90 | 94 delete server; |
91 return m_servers[n].first; | 95 server = 0; |
96 } | |
97 | |
98 if (server) { | |
99 m_servers[n] = ServerCountPair(server, 1); | |
100 } | |
101 | |
102 return server; | |
92 } | 103 } |
93 | 104 |
94 FFTDataServer * | 105 FFTDataServer * |
95 FFTDataServer::getFuzzyInstance(const DenseTimeValueModel *model, | 106 FFTDataServer::getFuzzyInstance(const DenseTimeValueModel *model, |
96 int channel, | 107 int channel, |
362 | 373 |
363 int cells = m_width * m_height; | 374 int cells = m_width * m_height; |
364 int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb | 375 int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb |
365 int maximumSize = (cells / 1024) * sizeof(float); // kb | 376 int maximumSize = (cells / 1024) * sizeof(float); // kb |
366 | 377 |
367 //!!! catch InsufficientDiscSpace | 378 // This can throw InsufficientDiscSpace. We don't catch it here -- we |
379 // haven't allocated anything yet and can safely let the exception out. | |
380 // Caller needs to check for it. | |
368 | 381 |
369 StorageAdviser::Recommendation recommendation = | 382 StorageAdviser::Recommendation recommendation = |
370 StorageAdviser::recommend(criteria, minimumSize, maximumSize); | 383 StorageAdviser::recommend(criteria, minimumSize, maximumSize); |
371 | 384 |
372 std::cerr << "Recommendation was: " << recommendation << std::endl; | 385 std::cerr << "Recommendation was: " << recommendation << std::endl; |
373 | 386 |
374 m_memoryCache = ((recommendation & StorageAdviser::UseMemory) || | 387 m_memoryCache = ((recommendation & StorageAdviser::UseMemory) || |
542 | 555 |
543 QString name = QString("%1-%2").arg(m_fileBaseName).arg(c); | 556 QString name = QString("%1-%2").arg(m_fileBaseName).arg(c); |
544 | 557 |
545 FFTCache *cache = 0; | 558 FFTCache *cache = 0; |
546 | 559 |
547 if (m_memoryCache) { | 560 try { |
548 | 561 |
549 cache = new FFTMemoryCache(); | 562 if (m_memoryCache) { |
550 | 563 |
551 } else if (m_compactCache) { | 564 cache = new FFTMemoryCache(); |
552 | 565 |
553 cache = new FFTFileCache(name, MatrixFile::ReadWrite, | 566 } else if (m_compactCache) { |
554 FFTFileCache::Compact); | 567 |
555 | 568 cache = new FFTFileCache(name, MatrixFile::ReadWrite, |
556 } else { | 569 FFTFileCache::Compact); |
557 | 570 |
558 cache = new FFTFileCache(name, MatrixFile::ReadWrite, | 571 } else { |
559 m_polar ? FFTFileCache::Polar : | 572 |
560 FFTFileCache::Rectangular); | 573 cache = new FFTFileCache(name, MatrixFile::ReadWrite, |
561 } | 574 m_polar ? FFTFileCache::Polar : |
562 | 575 FFTFileCache::Rectangular); |
563 // FFTCache *cache = new FFTMemoryCache(); | 576 } |
564 | 577 |
565 size_t width = m_cacheWidth; | 578 size_t width = m_cacheWidth; |
566 if (c * m_cacheWidth + width > m_width) { | 579 if (c * m_cacheWidth + width > m_width) { |
567 width = m_width - c * m_cacheWidth; | 580 width = m_width - c * m_cacheWidth; |
568 } | 581 } |
569 | 582 |
570 cache->resize(width, m_height); | 583 cache->resize(width, m_height); |
571 cache->reset(); | 584 cache->reset(); |
585 | |
586 } catch (std::bad_alloc) { | |
587 std::cerr << "ERROR: Memory allocation failed in FFTFileCache::resize:" | |
588 << " abandoning this cache" << std::endl; | |
589 //!!! Shouldn't be using QtGui here. Need a better way to report this. | |
590 QMessageBox::critical | |
591 (0, QApplication::tr("FFT cache resize failed"), | |
592 QApplication::tr | |
593 ("Failed to create or resize an FFT model slice.\n" | |
594 "There may be insufficient memory or disc space to continue.")); | |
595 delete cache; | |
596 m_caches[c] = 0; | |
597 return 0; | |
598 } | |
572 | 599 |
573 m_caches[c] = cache; | 600 m_caches[c] = cache; |
574 m_lastUsedCache = c; | 601 m_lastUsedCache = c; |
575 | 602 |
576 return cache; | 603 return cache; |
581 { | 608 { |
582 Profiler profiler("FFTDataServer::getMagnitudeAt", false); | 609 Profiler profiler("FFTDataServer::getMagnitudeAt", false); |
583 | 610 |
584 size_t col; | 611 size_t col; |
585 FFTCache *cache = getCache(x, col); | 612 FFTCache *cache = getCache(x, col); |
613 if (!cache) return 0; | |
586 | 614 |
587 if (!cache->haveSetColumnAt(col)) { | 615 if (!cache->haveSetColumnAt(col)) { |
588 std::cerr << "FFTDataServer::getMagnitudeAt: calling fillColumn(" | 616 std::cerr << "FFTDataServer::getMagnitudeAt: calling fillColumn(" |
589 << x << ")" << std::endl; | 617 << x << ")" << std::endl; |
590 fillColumn(x); | 618 fillColumn(x); |
597 { | 625 { |
598 Profiler profiler("FFTDataServer::getNormalizedMagnitudeAt", false); | 626 Profiler profiler("FFTDataServer::getNormalizedMagnitudeAt", false); |
599 | 627 |
600 size_t col; | 628 size_t col; |
601 FFTCache *cache = getCache(x, col); | 629 FFTCache *cache = getCache(x, col); |
630 if (!cache) return 0; | |
602 | 631 |
603 if (!cache->haveSetColumnAt(col)) { | 632 if (!cache->haveSetColumnAt(col)) { |
604 fillColumn(x); | 633 fillColumn(x); |
605 } | 634 } |
606 return cache->getNormalizedMagnitudeAt(col, y); | 635 return cache->getNormalizedMagnitudeAt(col, y); |
611 { | 640 { |
612 Profiler profiler("FFTDataServer::getMaximumMagnitudeAt", false); | 641 Profiler profiler("FFTDataServer::getMaximumMagnitudeAt", false); |
613 | 642 |
614 size_t col; | 643 size_t col; |
615 FFTCache *cache = getCache(x, col); | 644 FFTCache *cache = getCache(x, col); |
645 if (!cache) return 0; | |
616 | 646 |
617 if (!cache->haveSetColumnAt(col)) { | 647 if (!cache->haveSetColumnAt(col)) { |
618 fillColumn(x); | 648 fillColumn(x); |
619 } | 649 } |
620 return cache->getMaximumMagnitudeAt(col); | 650 return cache->getMaximumMagnitudeAt(col); |
625 { | 655 { |
626 Profiler profiler("FFTDataServer::getPhaseAt", false); | 656 Profiler profiler("FFTDataServer::getPhaseAt", false); |
627 | 657 |
628 size_t col; | 658 size_t col; |
629 FFTCache *cache = getCache(x, col); | 659 FFTCache *cache = getCache(x, col); |
660 if (!cache) return 0; | |
630 | 661 |
631 if (!cache->haveSetColumnAt(col)) { | 662 if (!cache->haveSetColumnAt(col)) { |
632 fillColumn(x); | 663 fillColumn(x); |
633 } | 664 } |
634 return cache->getPhaseAt(col, y); | 665 return cache->getPhaseAt(col, y); |
639 { | 670 { |
640 Profiler profiler("FFTDataServer::getValuesAt", false); | 671 Profiler profiler("FFTDataServer::getValuesAt", false); |
641 | 672 |
642 size_t col; | 673 size_t col; |
643 FFTCache *cache = getCache(x, col); | 674 FFTCache *cache = getCache(x, col); |
675 if (!cache) { real = 0; imaginary = 0; return; } | |
644 | 676 |
645 if (!cache->haveSetColumnAt(col)) { | 677 if (!cache->haveSetColumnAt(col)) { |
646 #ifdef DEBUG_FFT_SERVER | 678 #ifdef DEBUG_FFT_SERVER |
647 std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl; | 679 std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl; |
648 #endif | 680 #endif |
670 return false; | 702 return false; |
671 } | 703 } |
672 | 704 |
673 size_t col; | 705 size_t col; |
674 FFTCache *cache = getCache(x, col); | 706 FFTCache *cache = getCache(x, col); |
707 if (!cache) return true; | |
675 | 708 |
676 return cache->haveSetColumnAt(col); | 709 return cache->haveSetColumnAt(col); |
677 } | 710 } |
678 | 711 |
679 void | 712 void |
684 size_t col; | 717 size_t col; |
685 #ifdef DEBUG_FFT_SERVER_FILL | 718 #ifdef DEBUG_FFT_SERVER_FILL |
686 std::cout << "FFTDataServer::fillColumn(" << x << ")" << std::endl; | 719 std::cout << "FFTDataServer::fillColumn(" << x << ")" << std::endl; |
687 #endif | 720 #endif |
688 FFTCache *cache = getCache(x, col); | 721 FFTCache *cache = getCache(x, col); |
722 if (!cache) return; | |
689 | 723 |
690 QMutexLocker locker(&m_writeMutex); | 724 QMutexLocker locker(&m_writeMutex); |
691 | 725 |
692 if (cache->haveSetColumnAt(col)) return; | 726 if (cache->haveSetColumnAt(col)) return; |
693 | 727 |