Mercurial > hg > svapp
comparison framework/Document.cpp @ 690:827a522a5da4 by-id
Re-implement Document::releaseModel
author | Chris Cannam |
---|---|
date | Fri, 12 Jul 2019 09:40:56 +0100 |
parents | e0b0f3e163ca |
children | c8ba09756eff |
comparison
equal
deleted
inserted
replaced
689:e56cc6fe7da2 | 690:827a522a5da4 |
---|---|
744 | 744 |
745 return mm; | 745 return mm; |
746 } | 746 } |
747 | 747 |
748 void | 748 void |
749 Document::releaseModel(ModelId modelId) // Will _not_ release main model! | 749 Document::releaseModel(ModelId modelId) |
750 { | 750 { |
751 //!!! | 751 // This is called when a layer has been deleted or has replaced |
752 | 752 // its model, in order to reclaim storage for the old model. It |
753 SVCERR << "Document::releaseModel(" << modelId << "): STILL TO REVIEW" << endl; | 753 // could be a no-op without making any functional difference, as |
754 | 754 // all the models stored in the ById pool are released when the |
755 #ifdef NOT_DEFINED | 755 // document is deleted. But models can sometimes be large, so if |
756 // we know no other layer is using one, we should release it. If | |
757 // we happen to release one that is being used, the ModelById | |
758 // borrowed-pointer mechanism will at least prevent memory errors, | |
759 // although the other code will have to stop whatever it's doing. | |
760 | |
761 SVCERR << "Document::releaseModel(" << modelId << ")" << endl; | |
756 | 762 |
757 if (modelId.isNone()) { | 763 if (modelId.isNone()) { |
758 return; | 764 return; |
759 } | 765 } |
760 | 766 |
761 auto model = ModelById::get(modelId); | 767 #ifdef DEBUG_DOCUMENT |
762 if (!model) { | 768 SVCERR << "Document::releaseModel(" << modelId << ")" << endl; |
769 #endif | |
770 | |
771 if (modelId == m_mainModel) { | |
772 #ifdef DEBUG_DOCUMENT | |
773 SVCERR << "Document::releaseModel: It's the main model, ignoring" | |
774 << endl; | |
775 #endif | |
763 return; | 776 return; |
764 } | 777 } |
765 | 778 |
766 #ifdef DEBUG_DOCUMENT | 779 if (m_models.find(modelId) == m_models.end()) { |
767 SVDEBUG << "Document::releaseModel(" << modelId << ", type " | 780 // No point in releasing aggregate models and the like, |
768 << model->getTypeName() << ", name \"" | 781 // they're not large |
769 << model->objectName() << "\")" << endl; | 782 #ifdef DEBUG_DOCUMENT |
770 #endif | 783 SVCERR << "Document::releaseModel: It's not a regular layer model, ignoring" << endl; |
771 | 784 #endif |
772 if (modelId == m_mainModel) { | |
773 return; | 785 return; |
774 } | 786 } |
775 | 787 |
776 bool toDelete = false; | 788 for (auto layer: m_layers) { |
777 bool isInModelList = false; // should become true for any "normal" model | 789 if (layer->getModel() == modelId) { |
778 | 790 #ifdef DEBUG_DOCUMENT |
779 if (m_models.find(modelId) != m_models.end()) { | 791 SVCERR << "Document::releaseModel: It's still in use in at least one layer, ignoring" << endl; |
780 | 792 #endif |
781 if (mitr->refcount == 0) { | 793 return; |
782 SVCERR << "WARNING: Document::releaseModel: model " << model | 794 } |
783 << " reference count is zero already!" << endl; | 795 } |
784 } else { | 796 |
785 #ifdef DEBUG_DOCUMENT | 797 #ifdef DEBUG_DOCUMENT |
786 SVDEBUG << "Lowering refcount from " << mitr->refcount << endl; | 798 SVCERR << "Document::releaseModel: Seems to be OK to release this one" |
787 #endif | 799 << endl; |
788 if (--mitr->refcount == 0) { | 800 #endif |
789 toDelete = true; | 801 |
790 } | 802 int sourceCount = 0; |
791 } | 803 |
792 isInModelList = true; | 804 for (auto &m: m_models) { |
793 | 805 if (m.second.source == modelId) { |
794 } else if (m_aggregateModels.find(model) != m_aggregateModels.end()) { | 806 ++sourceCount; |
795 #ifdef DEBUG_DOCUMENT | 807 m.second.source = {}; |
796 SVDEBUG << "Document::releaseModel: is an aggregate model" << endl; | 808 } |
797 #endif | 809 } |
798 toDelete = true; | 810 |
799 } else { | 811 if (sourceCount > 0) { |
800 SVCERR << "WARNING: Document::releaseModel: Unfound model " | 812 SVCERR << "Document::releaseModel: Request to release model " |
801 << model << endl; | 813 << modelId << " even though it was source for " |
802 toDelete = true; | 814 << sourceCount << " other derived model(s) -- have cleared " |
803 } | 815 << "their source fields" << endl; |
804 | 816 } |
805 if (toDelete) { | 817 |
806 | 818 m_models.erase(modelId); |
807 int sourceCount = 0; | 819 ModelById::release(modelId); |
808 | |
809 for (auto &rec: m_models) { | |
810 if (rec.source == model) { | |
811 ++sourceCount; | |
812 rec.source = nullptr; | |
813 } | |
814 } | |
815 | |
816 if (sourceCount > 0) { | |
817 SVDEBUG << "Document::releaseModel: Deleting model " | |
818 << model << " even though it is source for " | |
819 << sourceCount << " other derived model(s) -- resetting " | |
820 << "their source fields appropriately" << endl; | |
821 } | |
822 | |
823 if (isInModelList) { | |
824 deleteModelFromList(model); | |
825 | |
826 #ifdef DEBUG_DOCUMENT | |
827 SVDEBUG << "Document::releaseModel: Deleted model " << model << endl; | |
828 SVDEBUG << "Models now: "; | |
829 for (const auto &r: m_models) { | |
830 SVDEBUG << r.model << " "; | |
831 } | |
832 SVDEBUG << endl; | |
833 #endif | |
834 } else { | |
835 model->aboutToDelete(); | |
836 emit modelAboutToBeDeleted(model); | |
837 delete model; | |
838 | |
839 #ifdef DEBUG_DOCUMENT | |
840 SVDEBUG << "Document::releaseModel: Deleted awkward model " << model << endl; | |
841 #endif | |
842 } | |
843 } | |
844 | |
845 #endif | |
846 } | 820 } |
847 | 821 |
848 void | 822 void |
849 Document::deleteLayer(Layer *layer, bool force) | 823 Document::deleteLayer(Layer *layer, bool force) |
850 { | 824 { |