1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-03 17:37:18 +00:00
OpenMW/components/detournavigator/navmeshtilescache.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

122 lines
3.9 KiB
C++
Raw Normal View History

#include "navmeshtilescache.hpp"
#include "stats.hpp"
2019-03-17 17:18:53 +00:00
#include <cstring>
namespace DetourNavigator
{
NavMeshTilesCache::NavMeshTilesCache(const std::size_t maxNavMeshDataSize)
2021-02-03 23:18:25 +00:00
: mMaxNavMeshDataSize(maxNavMeshDataSize)
, mUsedNavMeshDataSize(0)
, mFreeNavMeshDataSize(0)
, mHitCount(0)
, mGetCount(0)
{
}
NavMeshTilesCache::Value NavMeshTilesCache::get(
const AgentBounds& agentBounds, const TilePosition& changedTile, const RecastMesh& recastMesh)
{
const std::lock_guard<std::mutex> lock(mMutex);
2021-02-03 23:18:25 +00:00
++mGetCount;
const auto tile = mValues.find(std::tie(agentBounds, changedTile, recastMesh));
2021-03-05 00:56:44 +00:00
if (tile == mValues.end())
return Value();
acquireItemUnsafe(tile->second);
2021-02-03 23:18:25 +00:00
++mHitCount;
return Value(*this, tile->second);
}
NavMeshTilesCache::Value NavMeshTilesCache::set(const AgentBounds& agentBounds, const TilePosition& changedTile,
const RecastMesh& recastMesh, std::unique_ptr<PreparedNavMeshData>&& value)
{
const auto itemSize = sizeof(RecastMesh) + getSize(recastMesh)
+ (value == nullptr ? 0 : sizeof(PreparedNavMeshData) + getSize(*value));
const std::lock_guard<std::mutex> lock(mMutex);
if (itemSize > mFreeNavMeshDataSize + (mMaxNavMeshDataSize - mUsedNavMeshDataSize))
return Value();
while (!mFreeItems.empty() && mUsedNavMeshDataSize + itemSize > mMaxNavMeshDataSize)
removeLeastRecentlyUsed();
RecastMeshData key{ recastMesh.getMesh(), recastMesh.getWater(), recastMesh.getHeightfields(),
recastMesh.getFlatHeightfields() };
const auto iterator = mFreeItems.emplace(mFreeItems.end(), agentBounds, changedTile, std::move(key), itemSize);
const auto emplaced = mValues.emplace(
std::make_tuple(agentBounds, changedTile, std::cref(iterator->mRecastMeshData)), iterator);
if (!emplaced.second)
{
mFreeItems.erase(iterator);
acquireItemUnsafe(emplaced.first->second);
++mGetCount;
++mHitCount;
return Value(*this, emplaced.first->second);
}
iterator->mPreparedNavMeshData = std::move(value);
++iterator->mUseCount;
mUsedNavMeshDataSize += itemSize;
mBusyItems.splice(mBusyItems.end(), mFreeItems, iterator);
return Value(*this, iterator);
}
NavMeshTilesCacheStats NavMeshTilesCache::getStats() const
2019-03-17 17:18:53 +00:00
{
NavMeshTilesCacheStats result;
2019-03-17 17:18:53 +00:00
{
const std::lock_guard<std::mutex> lock(mMutex);
2021-03-24 23:59:44 +00:00
result.mNavMeshCacheSize = mUsedNavMeshDataSize;
result.mUsedNavMeshTiles = mBusyItems.size();
result.mCachedNavMeshTiles = mFreeItems.size();
result.mHitCount = mHitCount;
result.mGetCount = mGetCount;
2019-03-17 17:18:53 +00:00
}
2021-03-24 23:59:44 +00:00
return result;
}
2019-03-17 17:18:53 +00:00
void NavMeshTilesCache::removeLeastRecentlyUsed()
{
const auto& item = mFreeItems.back();
const auto value = mValues.find(std::tie(item.mAgentBounds, item.mChangedTile, item.mRecastMeshData));
2021-03-05 00:56:44 +00:00
if (value == mValues.end())
return;
mUsedNavMeshDataSize -= item.mSize;
mFreeNavMeshDataSize -= item.mSize;
2021-03-05 00:56:44 +00:00
mValues.erase(value);
2019-03-10 17:28:33 +00:00
mFreeItems.pop_back();
}
void NavMeshTilesCache::acquireItemUnsafe(ItemIterator iterator)
{
if (++iterator->mUseCount > 1)
return;
mBusyItems.splice(mBusyItems.end(), mFreeItems, iterator);
mFreeNavMeshDataSize -= iterator->mSize;
}
void NavMeshTilesCache::releaseItem(ItemIterator iterator)
{
if (--iterator->mUseCount > 0)
return;
const std::lock_guard<std::mutex> lock(mMutex);
mFreeItems.splice(mFreeItems.begin(), mBusyItems, iterator);
mFreeNavMeshDataSize += iterator->mSize;
}
}