1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-04 12:39:55 +00:00

Remove and add tile in single critical section

This commit is contained in:
elsid 2018-06-03 15:27:10 +03:00
parent 144e1a063b
commit 84949bedb1
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40

View File

@ -216,23 +216,6 @@ namespace
return NavMeshData(navMeshData, navMeshDataSize); return NavMeshData(navMeshData, navMeshDataSize);
} }
struct AutoIncrementRevision
{
std::atomic_size_t& mNavMeshRevision;
bool mNavMeshChanged;
AutoIncrementRevision(std::atomic_size_t& navMeshRevision)
: mNavMeshRevision(navMeshRevision)
, mNavMeshChanged(false)
{}
~AutoIncrementRevision()
{
if (mNavMeshChanged)
++mNavMeshRevision;
}
};
UpdateNavMeshStatus makeUpdateNavMeshStatus(bool removed, bool add) UpdateNavMeshStatus makeUpdateNavMeshStatus(bool removed, bool add)
{ {
if (removed && add) if (removed && add)
@ -292,20 +275,17 @@ namespace DetourNavigator
const auto x = changedTile.x(); const auto x = changedTile.x();
const auto y = changedTile.y(); const auto y = changedTile.y();
AutoIncrementRevision incRev(navMeshCacheItem.mNavMeshRevision); const auto removeTile = [&] {
bool removed = false;
{
const auto locked = navMesh.lock(); const auto locked = navMesh.lock();
removed = dtStatusSucceed(locked->removeTile(locked->getTileRefAt(x, y, 0), nullptr, nullptr)); const auto removed = dtStatusSucceed(locked->removeTile(locked->getTileRefAt(x, y, 0), nullptr, nullptr));
} navMeshCacheItem.mNavMeshRevision += removed;
return makeUpdateNavMeshStatus(removed, false);
incRev.mNavMeshChanged = removed; };
if (!recastMesh) if (!recastMesh)
{ {
log("ignore add tile: recastMesh is null"); log("ignore add tile: recastMesh is null");
return makeUpdateNavMeshStatus(removed, false); return removeTile();
} }
const auto& boundsMin = recastMesh->getBoundsMin(); const auto& boundsMin = recastMesh->getBoundsMin();
@ -314,14 +294,14 @@ namespace DetourNavigator
if (boundsMin == boundsMax) if (boundsMin == boundsMax)
{ {
log("ignore add tile: recastMesh is empty"); log("ignore add tile: recastMesh is empty");
return makeUpdateNavMeshStatus(removed, false); return removeTile();
} }
const auto maxTiles = navMesh.lock()->getParams()->maxTiles; const auto maxTiles = navMesh.lock()->getParams()->maxTiles;
if (!shouldAddTile(changedTile, playerTile, maxTiles)) if (!shouldAddTile(changedTile, playerTile, maxTiles))
{ {
log("ignore add tile: too far from player"); log("ignore add tile: too far from player");
return makeUpdateNavMeshStatus(removed, false); return removeTile();
} }
const auto tileBounds = makeTileBounds(settings, changedTile); const auto tileBounds = makeTileBounds(settings, changedTile);
@ -334,17 +314,27 @@ namespace DetourNavigator
if (!navMeshData.mValue) if (!navMeshData.mValue)
{ {
log("ignore add tile: NavMeshData is null"); log("ignore add tile: NavMeshData is null");
return makeUpdateNavMeshStatus(removed, false); return removeTile();
} }
const auto status = navMesh.lock()->addTile(navMeshData.mValue.get(), navMeshData.mSize, dtStatus addStatus;
DT_TILE_FREE_DATA, 0, 0); bool removed;
if (dtStatusSucceed(status)) {
incRev.mNavMeshChanged = true; const auto locked = navMesh.lock();
else removed = dtStatusSucceed(locked->removeTile(locked->getTileRefAt(x, y, 0), nullptr, nullptr));
log("failed to add tile with status=", WriteDtStatus {status}); addStatus = locked->addTile(navMeshData.mValue.get(), navMeshData.mSize, DT_TILE_FREE_DATA, 0, 0);
navMeshData.mValue.release(); }
return makeUpdateNavMeshStatus(removed, dtStatusSucceed(status)); if (dtStatusSucceed(addStatus))
{
++navMeshCacheItem.mNavMeshRevision;
navMeshData.mValue.release();
return makeUpdateNavMeshStatus(removed, true);
}
else
{
log("failed to add tile with status=", WriteDtStatus {addStatus});
return makeUpdateNavMeshStatus(removed, false);
}
} }
} }