1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-10 16:14:26 +00:00

Explicitly bind TileCachedRecastMeshManager with mutex

This commit is contained in:
elsid 2022-02-03 22:24:26 +01:00
parent 3caeda7299
commit 0b644a897e
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40
2 changed files with 54 additions and 49 deletions

View File

@ -43,7 +43,7 @@ namespace DetourNavigator
if (mBounds != infiniteTileBounds)
{
const std::lock_guard lock(mMutex);
const auto locked = mWorldspaceTiles.lock();
for (auto& object : mObjects)
{
const ObjectId id = object.first;
@ -58,7 +58,7 @@ namespace DetourNavigator
if (it == data.mTiles.end())
return;
data.mTiles.erase(it);
if (removeTile(id, position, mTiles))
if (removeTile(id, position, locked->mTiles))
changedTiles.emplace_back(position, ChangeType::remove);
};
getTilesPositions(getIntersection(mRange, objectRange), onOldTilePosition);
@ -67,7 +67,7 @@ namespace DetourNavigator
{
if (data.mTiles.find(position) != data.mTiles.end())
return;
if (addTile(id, data.mShape, data.mTransform, data.mAreaType, position, mTiles))
if (addTile(id, data.mShape, data.mTransform, data.mAreaType, position, locked->mTiles))
{
data.mTiles.insert(position);
changedTiles.emplace_back(position, ChangeType::add);
@ -91,17 +91,16 @@ namespace DetourNavigator
std::string TileCachedRecastMeshManager::getWorldspace() const
{
const std::lock_guard lock(mMutex);
return mWorldspace;
return mWorldspaceTiles.lockConst()->mWorldspace;
}
void TileCachedRecastMeshManager::setWorldspace(std::string_view worldspace)
{
const std::lock_guard lock(mMutex);
if (mWorldspace == worldspace)
const auto locked = mWorldspaceTiles.lock();
if (locked->mWorldspace == worldspace)
return;
mTiles.clear();
mWorldspace = worldspace;
locked->mTiles.clear();
locked->mWorldspace = worldspace;
}
std::optional<RemovedRecastMeshObject> TileCachedRecastMeshManager::removeObject(const ObjectId id)
@ -111,10 +110,10 @@ namespace DetourNavigator
return std::nullopt;
std::optional<RemovedRecastMeshObject> result;
{
const std::lock_guard lock(mMutex);
const auto locked = mWorldspaceTiles.lock();
for (const auto& tilePosition : object->second.mTiles)
{
const auto removed = removeTile(id, tilePosition, mTiles);
const auto removed = removeTile(id, tilePosition, locked->mTiles);
if (removed && !result)
result = removed;
}
@ -138,8 +137,8 @@ namespace DetourNavigator
if (cellSize == std::numeric_limits<int>::max())
{
const std::lock_guard lock(mMutex);
for (auto& tile : mTiles)
const auto locked = mWorldspaceTiles.lock();
for (auto& tile : locked->mTiles)
{
if (tile.second->addWater(cellPosition, cellSize, level))
{
@ -154,12 +153,12 @@ namespace DetourNavigator
getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings),
[&] (const TilePosition& tilePosition)
{
const std::lock_guard lock(mMutex);
auto tile = mTiles.find(tilePosition);
if (tile == mTiles.end())
const auto locked = mWorldspaceTiles.lock();
auto tile = locked->mTiles.find(tilePosition);
if (tile == locked->mTiles.end())
{
const TileBounds tileBounds = makeRealTileBoundsWithBorder(mSettings, tilePosition);
tile = mTiles.emplace_hint(tile, tilePosition,
tile = locked->mTiles.emplace_hint(tile, tilePosition,
std::make_shared<CachedRecastMeshManager>(tileBounds, mTilesGeneration));
}
if (tile->second->addWater(cellPosition, cellSize, level))
@ -184,14 +183,14 @@ namespace DetourNavigator
std::optional<Water> result;
for (const auto& tilePosition : object->second)
{
const std::lock_guard lock(mMutex);
const auto tile = mTiles.find(tilePosition);
if (tile == mTiles.end())
const auto locked = mWorldspaceTiles.lock();
const auto tile = locked->mTiles.find(tilePosition);
if (tile == locked->mTiles.end())
continue;
const auto tileResult = tile->second->removeWater(cellPosition);
if (tile->second->isEmpty())
{
mTiles.erase(tile);
locked->mTiles.erase(tile);
++mTilesGeneration;
}
if (tileResult && !result)
@ -219,12 +218,12 @@ namespace DetourNavigator
getTilesPositions(makeTilesPositionsRange(cellSize, shift, mSettings),
[&] (const TilePosition& tilePosition)
{
const std::lock_guard lock(mMutex);
auto tile = mTiles.find(tilePosition);
if (tile == mTiles.end())
const auto locked = mWorldspaceTiles.lock();
auto tile = locked->mTiles.find(tilePosition);
if (tile == locked->mTiles.end())
{
const TileBounds tileBounds = makeRealTileBoundsWithBorder(mSettings, tilePosition);
tile = mTiles.emplace_hint(tile, tilePosition,
tile = locked->mTiles.emplace_hint(tile, tilePosition,
std::make_shared<CachedRecastMeshManager>(tileBounds, mTilesGeneration));
}
if (tile->second->addHeightfield(cellPosition, cellSize, shape))
@ -248,14 +247,14 @@ namespace DetourNavigator
std::optional<SizedHeightfieldShape> result;
for (const auto& tilePosition : object->second)
{
const std::lock_guard lock(mMutex);
const auto tile = mTiles.find(tilePosition);
if (tile == mTiles.end())
const auto locked = mWorldspaceTiles.lock();
const auto tile = locked->mTiles.find(tilePosition);
if (tile == locked->mTiles.end())
continue;
const auto tileResult = tile->second->removeHeightfield(cellPosition);
if (tile->second->isEmpty())
{
mTiles.erase(tile);
locked->mTiles.erase(tile);
++mTilesGeneration;
}
if (tileResult && !result)
@ -295,9 +294,9 @@ namespace DetourNavigator
void TileCachedRecastMeshManager::reportNavMeshChange(const TilePosition& tilePosition, Version recastMeshVersion, Version navMeshVersion) const
{
const std::lock_guard lock(mMutex);
const auto it = mTiles.find(tilePosition);
if (it == mTiles.end())
const auto locked = mWorldspaceTiles.lockConst();
const auto it = locked->mTiles.find(tilePosition);
if (it == locked->mTiles.end())
return;
it->second->reportNavMeshChange(recastMeshVersion, navMeshVersion);
}
@ -341,11 +340,11 @@ namespace DetourNavigator
std::shared_ptr<CachedRecastMeshManager> TileCachedRecastMeshManager::getManager(std::string_view worldspace,
const TilePosition& tilePosition) const
{
const std::lock_guard lock(mMutex);
if (mWorldspace != worldspace)
const auto locked = mWorldspaceTiles.lockConst();
if (locked->mWorldspace != worldspace)
return nullptr;
const auto it = mTiles.find(tilePosition);
if (it == mTiles.end())
const auto it = locked->mTiles.find(tilePosition);
if (it == locked->mTiles.end())
return nullptr;
return it->second;
}

View File

@ -9,6 +9,8 @@
#include "heightfieldshape.hpp"
#include "changetype.hpp"
#include <components/misc/guarded.hpp>
#include <algorithm>
#include <map>
#include <mutex>
@ -42,11 +44,11 @@ namespace DetourNavigator
std::set<TilePosition> tilesPositions;
if (range.mBegin != range.mEnd)
{
const std::lock_guard lock(mMutex);
const auto locked = mWorldspaceTiles.lock();
getTilesPositions(range,
[&] (const TilePosition& tilePosition)
{
if (addTile(id, shape, transform, areaType, tilePosition, mTiles))
if (addTile(id, shape, transform, areaType, tilePosition, locked->mTiles))
tilesPositions.insert(tilePosition);
});
}
@ -67,31 +69,31 @@ namespace DetourNavigator
bool changed = false;
std::set<TilePosition> newTiles;
{
const TilesPositionsRange objectRange = makeTilesPositionsRange(shape.getShape(), transform, mSettings);
const TilesPositionsRange range = getIntersection(mRange, objectRange);
const auto locked = mWorldspaceTiles.lock();
const auto onTilePosition = [&] (const TilePosition& tilePosition)
{
if (data.mTiles.find(tilePosition) != data.mTiles.end())
{
newTiles.insert(tilePosition);
if (updateTile(id, transform, areaType, tilePosition, mTiles))
if (updateTile(id, transform, areaType, tilePosition, locked->mTiles))
{
onChangedTile(tilePosition, ChangeType::update);
changed = true;
}
}
else if (addTile(id, shape, transform, areaType, tilePosition, mTiles))
else if (addTile(id, shape, transform, areaType, tilePosition, locked->mTiles))
{
newTiles.insert(tilePosition);
onChangedTile(tilePosition, ChangeType::add);
changed = true;
}
};
const TilesPositionsRange objectRange = makeTilesPositionsRange(shape.getShape(), transform, mSettings);
const TilesPositionsRange range = getIntersection(mRange, objectRange);
const std::lock_guard lock(mMutex);
getTilesPositions(range, onTilePosition);
for (const auto& tile : data.mTiles)
{
if (newTiles.find(tile) == newTiles.end() && removeTile(id, tile, mTiles))
if (newTiles.find(tile) == newTiles.end() && removeTile(id, tile, locked->mTiles))
{
onChangedTile(tile, ChangeType::remove);
changed = true;
@ -125,8 +127,8 @@ namespace DetourNavigator
template <class Function>
void forEachTile(Function&& function) const
{
const std::lock_guard lock(mMutex);
for (auto& [tilePosition, recastMeshManager] : mTiles)
const auto& locked = mWorldspaceTiles.lockConst();
for (const auto& [tilePosition, recastMeshManager] : locked->mTiles)
function(tilePosition, *recastMeshManager);
}
@ -145,12 +147,16 @@ namespace DetourNavigator
std::set<TilePosition> mTiles;
};
struct WorldspaceTiles
{
std::string mWorldspace;
TilesMap mTiles;
};
const RecastSettings& mSettings;
mutable std::mutex mMutex;
TileBounds mBounds;
TilesPositionsRange mRange;
std::string mWorldspace;
TilesMap mTiles;
Misc::ScopeGuarded<WorldspaceTiles> mWorldspaceTiles;
std::unordered_map<ObjectId, ObjectData> mObjects;
std::map<osg::Vec2i, std::vector<TilePosition>> mWaterTilesPositions;
std::map<osg::Vec2i, std::vector<TilePosition>> mHeightfieldTilesPositions;