Mercurial > hg > svcore
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 |