42 lines
1.9 KiB
Diff
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;
|
|
}
|
|
}
|
|
}
|