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 {