comparison data/model/SparseModel.h @ 1456:904e031c9c76

Fix hangs due to nested mutex lockers (as a result of emitting signals from within a locked section)
author Chris Cannam
date Tue, 24 Apr 2018 10:01:34 +0100
parents 6e9615bde1f9
children 0fb5d4e6edeb
comparison
equal deleted inserted replaced
1455:ec9e65fcf749 1456:904e031c9c76
753 753
754 template <typename PointType> 754 template <typename PointType>
755 void 755 void
756 SparseModel<PointType>::addPoint(const PointType &point) 756 SparseModel<PointType>::addPoint(const PointType &point)
757 { 757 {
758 QMutexLocker locker(&m_mutex); 758 {
759 759 QMutexLocker locker(&m_mutex);
760 m_points.insert(point); 760
761 m_pointCount++; 761 m_points.insert(point);
762 if (point.getLabel() != "") m_hasTextLabels = true; 762 m_pointCount++;
763 763 if (point.getLabel() != "") m_hasTextLabels = true;
764 // Even though this model is nominally sparse, there may still be 764
765 // too many signals going on here (especially as they'll probably 765 // Even though this model is nominally sparse, there may still
766 // be queued from one thread to another), which is why we need the 766 // be too many signals going on here (especially as they'll
767 // notifyOnAdd as an option rather than a necessity (the 767 // probably be queued from one thread to another), which is
768 // alternative is to notify on setCompletion). 768 // why we need the notifyOnAdd as an option rather than a
769 // necessity (the alternative is to notify on setCompletion).
770
771 if (m_notifyOnAdd) {
772 m_rows.clear(); //!!! inefficient
773 } else {
774 if (m_sinceLastNotifyMin == -1 ||
775 point.frame < m_sinceLastNotifyMin) {
776 m_sinceLastNotifyMin = point.frame;
777 }
778 if (m_sinceLastNotifyMax == -1 ||
779 point.frame > m_sinceLastNotifyMax) {
780 m_sinceLastNotifyMax = point.frame;
781 }
782 }
783 }
769 784
770 if (m_notifyOnAdd) { 785 if (m_notifyOnAdd) {
771 m_rows.clear(); //!!! inefficient
772 emit modelChangedWithin(point.frame, point.frame + m_resolution); 786 emit modelChangedWithin(point.frame, point.frame + m_resolution);
773 } else {
774 if (m_sinceLastNotifyMin == -1 ||
775 point.frame < m_sinceLastNotifyMin) {
776 m_sinceLastNotifyMin = point.frame;
777 }
778 if (m_sinceLastNotifyMax == -1 ||
779 point.frame > m_sinceLastNotifyMax) {
780 m_sinceLastNotifyMax = point.frame;
781 }
782 } 787 }
783 } 788 }
784 789
785 template <typename PointType> 790 template <typename PointType>
786 bool 791 bool
803 808
804 template <typename PointType> 809 template <typename PointType>
805 void 810 void
806 SparseModel<PointType>::deletePoint(const PointType &point) 811 SparseModel<PointType>::deletePoint(const PointType &point)
807 { 812 {
808 QMutexLocker locker(&m_mutex); 813 {
809 814 QMutexLocker locker(&m_mutex);
810 PointListIterator i = m_points.lower_bound(point); 815
811 typename PointType::Comparator comparator; 816 PointListIterator i = m_points.lower_bound(point);
812 while (i != m_points.end()) { 817 typename PointType::Comparator comparator;
813 if (i->frame > point.frame) break; 818 while (i != m_points.end()) {
814 if (!comparator(*i, point) && !comparator(point, *i)) { 819 if (i->frame > point.frame) break;
815 m_points.erase(i); 820 if (!comparator(*i, point) && !comparator(point, *i)) {
816 m_pointCount--; 821 m_points.erase(i);
817 break; 822 m_pointCount--;
823 break;
818 } 824 }
819 ++i; 825 ++i;
820 } 826 }
821 827
822 // std::cout << "SparseOneDimensionalModel: emit modelChanged(" 828 // std::cout << "SparseOneDimensionalModel: emit modelChanged("
823 // << point.frame << ")" << std::endl; 829 // << point.frame << ")" << std::endl;
824 m_rows.clear(); //!!! inefficient 830 m_rows.clear(); //!!! inefficient
831 }
832
825 emit modelChangedWithin(point.frame, point.frame + m_resolution); 833 emit modelChangedWithin(point.frame, point.frame + m_resolution);
826 } 834 }
827 835
828 template <typename PointType> 836 template <typename PointType>
829 void 837 void
830 SparseModel<PointType>::setCompletion(int completion, bool update) 838 SparseModel<PointType>::setCompletion(int completion, bool update)
831 { 839 {
832 // std::cerr << "SparseModel::setCompletion(" << completion << ")" << std::endl; 840 // std::cerr << "SparseModel::setCompletion(" << completion << ")" << std::endl;
833 841 bool emitCompletionChanged = true;
834 QMutexLocker locker(&m_mutex); 842 bool emitGeneralModelChanged = false;
835 843 bool emitRegionChanged = false;
836 if (m_completion != completion) { 844
837 m_completion = completion; 845 {
838 846 QMutexLocker locker(&m_mutex);
839 if (completion == 100) { 847
840 848 if (m_completion != completion) {
841 if (!m_notifyOnAdd) { 849 m_completion = completion;
842 emit completionChanged(); 850
851 if (completion == 100) {
852
853 if (m_notifyOnAdd) {
854 emitCompletionChanged = false;
855 }
856
857 m_notifyOnAdd = true; // henceforth
858 m_rows.clear(); //!!! inefficient
859 emitGeneralModelChanged = true;
860
861 } else if (!m_notifyOnAdd) {
862
863 if (update &&
864 m_sinceLastNotifyMin >= 0 &&
865 m_sinceLastNotifyMax >= 0) {
866 m_rows.clear(); //!!! inefficient
867 emitRegionChanged = true;
868 }
843 } 869 }
844 870 }
845 m_notifyOnAdd = true; // henceforth 871 }
846 m_rows.clear(); //!!! inefficient 872
847 emit modelChanged(); 873 if (emitCompletionChanged) {
848 874 emit completionChanged();
849 } else if (!m_notifyOnAdd) { 875 }
850 876 if (emitGeneralModelChanged) {
851 if (update && 877 emit modelChanged();
852 m_sinceLastNotifyMin >= 0 && 878 }
853 m_sinceLastNotifyMax >= 0) { 879 if (emitRegionChanged) {
854 m_rows.clear(); //!!! inefficient 880 emit modelChangedWithin(m_sinceLastNotifyMin, m_sinceLastNotifyMax);
855 emit modelChangedWithin(m_sinceLastNotifyMin, m_sinceLastNotifyMax); 881 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
856 m_sinceLastNotifyMin = m_sinceLastNotifyMax = -1;
857 } else {
858 emit completionChanged();
859 }
860 } else {
861 emit completionChanged();
862 }
863 } 882 }
864 } 883 }
865 884
866 template <typename PointType> 885 template <typename PointType>
867 void 886 void