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 { | 
