|
|
|
@ -89,6 +89,9 @@ namespace DetourNavigator
|
|
|
|
|
job.mChangeType = changedTile.second;
|
|
|
|
|
job.mDistanceToPlayer = getManhattanDistance(changedTile.first, playerTile);
|
|
|
|
|
job.mDistanceToOrigin = getManhattanDistance(changedTile.first, TilePosition {0, 0});
|
|
|
|
|
job.mProcessTime = job.mChangeType == ChangeType::update
|
|
|
|
|
? mLastUpdates[job.mAgentHalfExtents][job.mChangedTile] + mSettings.get().mMinUpdateInterval
|
|
|
|
|
: std::chrono::steady_clock::time_point();
|
|
|
|
|
|
|
|
|
|
mJobs.push(std::move(job));
|
|
|
|
|
}
|
|
|
|
@ -137,6 +140,8 @@ namespace DetourNavigator
|
|
|
|
|
if (!processed)
|
|
|
|
|
repost(std::move(*job));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
cleanupLastUpdates();
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
@ -176,6 +181,7 @@ namespace DetourNavigator
|
|
|
|
|
const auto locked = navMeshCacheItem->lockConst();
|
|
|
|
|
Log(Debug::Debug) << std::fixed << std::setprecision(2) <<
|
|
|
|
|
"Cache updated for agent=(" << job.mAgentHalfExtents << ")" <<
|
|
|
|
|
" tile=" << job.mChangedTile <<
|
|
|
|
|
" status=" << status <<
|
|
|
|
|
" generation=" << locked->getGeneration() <<
|
|
|
|
|
" revision=" << locked->getNavMeshRevision() <<
|
|
|
|
@ -195,12 +201,15 @@ namespace DetourNavigator
|
|
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
const auto hasJob = [&] { return !mJobs.empty() || !threadQueue.mJobs.empty(); };
|
|
|
|
|
const auto hasJob = [&] {
|
|
|
|
|
return (!mJobs.empty() && mJobs.top().mProcessTime <= std::chrono::steady_clock::now())
|
|
|
|
|
|| !threadQueue.mJobs.empty();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!mHasJob.wait_for(lock, std::chrono::milliseconds(10), hasJob))
|
|
|
|
|
{
|
|
|
|
|
mFirstStart.lock()->reset();
|
|
|
|
|
if (getTotalThreadJobsUnsafe() == 0)
|
|
|
|
|
if (mJobs.empty() && getTotalThreadJobsUnsafe() == 0)
|
|
|
|
|
mDone.notify_all();
|
|
|
|
|
return boost::none;
|
|
|
|
|
}
|
|
|
|
@ -209,29 +218,40 @@ namespace DetourNavigator
|
|
|
|
|
<< threadQueue.mJobs.size() << " thread jobs by thread=" << std::this_thread::get_id();
|
|
|
|
|
|
|
|
|
|
auto job = threadQueue.mJobs.empty()
|
|
|
|
|
? getJob(mJobs, mPushed)
|
|
|
|
|
: getJob(threadQueue.mJobs, threadQueue.mPushed);
|
|
|
|
|
? getJob(mJobs, mPushed, true)
|
|
|
|
|
: getJob(threadQueue.mJobs, threadQueue.mPushed, false);
|
|
|
|
|
|
|
|
|
|
const auto owner = lockTile(job.mAgentHalfExtents, job.mChangedTile);
|
|
|
|
|
if (!job)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
const auto owner = lockTile(job->mAgentHalfExtents, job->mChangedTile);
|
|
|
|
|
|
|
|
|
|
if (owner == threadId)
|
|
|
|
|
return job;
|
|
|
|
|
|
|
|
|
|
postThreadJob(std::move(job), mThreadsQueues[owner]);
|
|
|
|
|
postThreadJob(std::move(*job), mThreadsQueues[owner]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AsyncNavMeshUpdater::Job AsyncNavMeshUpdater::getJob(Jobs& jobs, Pushed& pushed)
|
|
|
|
|
boost::optional<AsyncNavMeshUpdater::Job> AsyncNavMeshUpdater::getJob(Jobs& jobs, Pushed& pushed, bool changeLastUpdate)
|
|
|
|
|
{
|
|
|
|
|
auto job = jobs.top();
|
|
|
|
|
const auto now = std::chrono::steady_clock::now();
|
|
|
|
|
|
|
|
|
|
if (jobs.top().mProcessTime > now)
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
|
|
Job job = std::move(jobs.top());
|
|
|
|
|
jobs.pop();
|
|
|
|
|
|
|
|
|
|
if (changeLastUpdate && job.mChangeType == ChangeType::update)
|
|
|
|
|
mLastUpdates[job.mAgentHalfExtents][job.mChangedTile] = now;
|
|
|
|
|
|
|
|
|
|
const auto it = pushed.find(job.mAgentHalfExtents);
|
|
|
|
|
it->second.erase(job.mChangedTile);
|
|
|
|
|
if (it->second.empty())
|
|
|
|
|
pushed.erase(it);
|
|
|
|
|
|
|
|
|
|
return job;
|
|
|
|
|
return {std::move(job)};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AsyncNavMeshUpdater::writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const
|
|
|
|
@ -344,4 +364,27 @@ namespace DetourNavigator
|
|
|
|
|
return std::accumulate(mThreadsQueues.begin(), mThreadsQueues.end(), std::size_t(0),
|
|
|
|
|
[] (auto r, const auto& v) { return r + v.second.mJobs.size(); });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AsyncNavMeshUpdater::cleanupLastUpdates()
|
|
|
|
|
{
|
|
|
|
|
const auto now = std::chrono::steady_clock::now();
|
|
|
|
|
|
|
|
|
|
const std::lock_guard<std::mutex> lock(mMutex);
|
|
|
|
|
|
|
|
|
|
for (auto agent = mLastUpdates.begin(); agent != mLastUpdates.end();)
|
|
|
|
|
{
|
|
|
|
|
for (auto tile = agent->second.begin(); tile != agent->second.end();)
|
|
|
|
|
{
|
|
|
|
|
if (now - tile->second > mSettings.get().mMinUpdateInterval)
|
|
|
|
|
tile = agent->second.erase(tile);
|
|
|
|
|
else
|
|
|
|
|
++tile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (agent->second.empty())
|
|
|
|
|
agent = mLastUpdates.erase(agent);
|
|
|
|
|
else
|
|
|
|
|
++agent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|