2018-09-30 22:33:25 +00:00
|
|
|
#include "navmeshtilescache.hpp"
|
2022-08-28 12:52:12 +00:00
|
|
|
#include "stats.hpp"
|
2019-03-17 17:18:53 +00:00
|
|
|
|
2019-03-10 19:04:41 +00:00
|
|
|
#include <cstring>
|
|
|
|
|
2018-09-30 22:33:25 +00:00
|
|
|
namespace DetourNavigator
|
|
|
|
{
|
|
|
|
NavMeshTilesCache::NavMeshTilesCache(const std::size_t maxNavMeshDataSize)
|
2021-02-03 23:18:25 +00:00
|
|
|
: mMaxNavMeshDataSize(maxNavMeshDataSize)
|
|
|
|
, mUsedNavMeshDataSize(0)
|
|
|
|
, mFreeNavMeshDataSize(0)
|
2021-02-03 23:15:54 +00:00
|
|
|
, mHitCount(0)
|
|
|
|
, mGetCount(0)
|
|
|
|
{
|
|
|
|
}
|
2018-09-30 22:33:25 +00:00
|
|
|
|
2022-06-16 22:28:44 +00:00
|
|
|
NavMeshTilesCache::Value NavMeshTilesCache::get(
|
|
|
|
const AgentBounds& agentBounds, const TilePosition& changedTile, const RecastMesh& recastMesh)
|
2018-09-30 22:33:25 +00:00
|
|
|
{
|
|
|
|
const std::lock_guard<std::mutex> lock(mMutex);
|
|
|
|
|
2021-02-03 23:18:25 +00:00
|
|
|
++mGetCount;
|
|
|
|
|
2022-07-06 12:21:53 +00:00
|
|
|
const auto tile = mValues.find(std::tie(agentBounds, changedTile, recastMesh));
|
2021-03-05 00:56:44 +00:00
|
|
|
if (tile == mValues.end())
|
2018-09-30 22:33:25 +00:00
|
|
|
return Value();
|
|
|
|
|
|
|
|
acquireItemUnsafe(tile->second);
|
|
|
|
|
2021-02-03 23:18:25 +00:00
|
|
|
++mHitCount;
|
|
|
|
|
2018-09-30 22:33:25 +00:00
|
|
|
return Value(*this, tile->second);
|
|
|
|
}
|
|
|
|
|
2022-06-16 22:28:44 +00:00
|
|
|
NavMeshTilesCache::Value NavMeshTilesCache::set(const AgentBounds& agentBounds, const TilePosition& changedTile,
|
2021-07-13 22:03:10 +00:00
|
|
|
const RecastMesh& recastMesh, std::unique_ptr<PreparedNavMeshData>&& value)
|
2018-09-30 22:33:25 +00:00
|
|
|
{
|
2021-07-13 22:03:10 +00:00
|
|
|
const auto itemSize = sizeof(RecastMesh) + getSize(recastMesh)
|
|
|
|
+ (value == nullptr ? 0 : sizeof(PreparedNavMeshData) + getSize(*value));
|
2018-09-30 22:33:25 +00:00
|
|
|
|
|
|
|
const std::lock_guard<std::mutex> lock(mMutex);
|
|
|
|
|
2021-02-04 00:12:52 +00:00
|
|
|
if (itemSize > mFreeNavMeshDataSize + (mMaxNavMeshDataSize - mUsedNavMeshDataSize))
|
2018-09-30 22:33:25 +00:00
|
|
|
return Value();
|
|
|
|
|
2021-02-04 00:12:52 +00:00
|
|
|
while (!mFreeItems.empty() && mUsedNavMeshDataSize + itemSize > mMaxNavMeshDataSize)
|
|
|
|
removeLeastRecentlyUsed();
|
2018-09-30 22:33:25 +00:00
|
|
|
|
2021-07-14 18:57:52 +00:00
|
|
|
RecastMeshData key{ recastMesh.getMesh(), recastMesh.getWater(), recastMesh.getHeightfields(),
|
|
|
|
recastMesh.getFlatHeightfields() };
|
2018-09-30 22:33:25 +00:00
|
|
|
|
2022-06-16 22:28:44 +00:00
|
|
|
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);
|
2018-09-30 22:33:25 +00:00
|
|
|
|
|
|
|
if (!emplaced.second)
|
|
|
|
{
|
|
|
|
mFreeItems.erase(iterator);
|
2021-03-06 00:49:15 +00:00
|
|
|
acquireItemUnsafe(emplaced.first->second);
|
|
|
|
++mGetCount;
|
|
|
|
++mHitCount;
|
|
|
|
return Value(*this, emplaced.first->second);
|
2018-09-30 22:33:25 +00:00
|
|
|
}
|
|
|
|
|
2021-07-13 22:03:10 +00:00
|
|
|
iterator->mPreparedNavMeshData = std::move(value);
|
2021-03-06 00:50:58 +00:00
|
|
|
++iterator->mUseCount;
|
2018-11-03 13:05:14 +00:00
|
|
|
mUsedNavMeshDataSize += itemSize;
|
2021-03-06 00:50:58 +00:00
|
|
|
mBusyItems.splice(mBusyItems.end(), mFreeItems, iterator);
|
2018-09-30 22:33:25 +00:00
|
|
|
|
|
|
|
return Value(*this, iterator);
|
|
|
|
}
|
|
|
|
|
2022-08-28 12:52:12 +00:00
|
|
|
NavMeshTilesCacheStats NavMeshTilesCache::getStats() const
|
2019-03-17 17:18:53 +00:00
|
|
|
{
|
2022-08-28 12:52:12 +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
|
|
|
|
2018-09-30 22:33:25 +00:00
|
|
|
void NavMeshTilesCache::removeLeastRecentlyUsed()
|
|
|
|
{
|
|
|
|
const auto& item = mFreeItems.back();
|
|
|
|
|
2022-07-06 12:21:53 +00:00
|
|
|
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())
|
2018-09-30 22:33:25 +00:00
|
|
|
return;
|
|
|
|
|
2021-02-03 23:15:54 +00:00
|
|
|
mUsedNavMeshDataSize -= item.mSize;
|
|
|
|
mFreeNavMeshDataSize -= item.mSize;
|
2018-09-30 22:33:25 +00:00
|
|
|
|
2021-03-05 00:56:44 +00:00
|
|
|
mValues.erase(value);
|
2019-03-10 17:28:33 +00:00
|
|
|
mFreeItems.pop_back();
|
2018-09-30 22:33:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NavMeshTilesCache::acquireItemUnsafe(ItemIterator iterator)
|
|
|
|
{
|
|
|
|
if (++iterator->mUseCount > 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
mBusyItems.splice(mBusyItems.end(), mFreeItems, iterator);
|
2021-02-03 23:15:54 +00:00
|
|
|
mFreeNavMeshDataSize -= iterator->mSize;
|
2018-09-30 22:33:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void NavMeshTilesCache::releaseItem(ItemIterator iterator)
|
|
|
|
{
|
|
|
|
if (--iterator->mUseCount > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const std::lock_guard<std::mutex> lock(mMutex);
|
|
|
|
|
|
|
|
mFreeItems.splice(mFreeItems.begin(), mBusyItems, iterator);
|
2021-02-03 23:15:54 +00:00
|
|
|
mFreeNavMeshDataSize += iterator->mSize;
|
2019-03-10 19:04:41 +00:00
|
|
|
}
|
2018-09-30 22:33:25 +00:00
|
|
|
}
|