java-topology/defects/ogre/patch/ogre-0002-resourcegroupmanager-unordered-set-erase.patch

42 lines
1.9 KiB
Diff

--- a/OgreMain/src/OgreResourceGroupManager.cpp
+++ b/OgreMain/src/OgreResourceGroupManager.cpp
@@ -963,6 +963,7 @@ namespace Ogre {
void ResourceGroupManager::_notifyAllResourcesRemoved(ResourceManager* manager) const
{
OGRE_LOCK_AUTO_MUTEX;
+ #include <unordered_set> // ensure header present at TU level in real patch
// Iterate over all groups
for (const auto & grpi : mResourceGroupMap)
@@ -975,14 +976,22 @@ namespace Ogre {
// Iterate over all resources and collect which should be removed
std::vector<ResourcePtr> arDel;
arDel.reserve(oi.second.size());
for (const auto& iter : oi.second) {
if (iter->getCreator() == manager)
arDel.emplace_back(iter);
}
- // Remove the items here (not above) to avoid iterator invalidation.
- for (const auto& iter : arDel)
- {
- auto iFind = std::find(oi.second.begin(), oi.second.end(), iter); // O(N)
- if (iFind != oi.second.end())
- oi.second.erase(iFind);
+ // Build O(1) membership set from raw pointers, then single-pass erase.
+ // Two-phase approach preserved to avoid iterator invalidation during
+ // resource destructor callbacks (see original comment).
+ std::unordered_set<Resource*> toRemove;
+ toRemove.reserve(arDel.size());
+ for (const auto& r : arDel)
+ toRemove.insert(r.get());
+
+ for (auto l = oi.second.begin(); l != oi.second.end(); )
+ {
+ if (toRemove.count(l->get()))
+ l = oi.second.erase(l); // O(1) per erase on std::list
+ else
+ ++l;
}
}
}