diff --git a/components/detournavigator/asyncnavmeshupdater.cpp b/components/detournavigator/asyncnavmeshupdater.cpp index e085aba160..da1ac19a7c 100644 --- a/components/detournavigator/asyncnavmeshupdater.cpp +++ b/components/detournavigator/asyncnavmeshupdater.cpp @@ -7,6 +7,8 @@ #include +#include + namespace { using DetourNavigator::ChangeType; @@ -101,7 +103,7 @@ namespace DetourNavigator void AsyncNavMeshUpdater::wait() { std::unique_lock lock(mMutex); - mDone.wait(lock, [&] { return mJobs.empty(); }); + mDone.wait(lock, [&] { return mJobs.empty() && getTotalThreadJobsUnsafe() == 0; }); } void AsyncNavMeshUpdater::reportStats(unsigned int frameNumber, osg::Stats& stats) const @@ -110,7 +112,7 @@ namespace DetourNavigator { const std::lock_guard lock(mMutex); - jobs = mJobs.size(); + jobs = mJobs.size() + getTotalThreadJobsUnsafe(); } stats.setAttribute(frameNumber, "NavMesh UpdateJobs", jobs); @@ -188,12 +190,13 @@ namespace DetourNavigator while (true) { - const auto hasJob = [&] { return !mJobs.empty() || !threadQueue.mPushed.empty(); }; + const auto hasJob = [&] { return !mJobs.empty() || !threadQueue.mJobs.empty(); }; if (!mHasJob.wait_for(lock, std::chrono::milliseconds(10), hasJob)) { mFirstStart.lock()->reset(); - mDone.notify_all(); + if (getTotalThreadJobsUnsafe() == 0) + mDone.notify_all(); return boost::none; } @@ -327,4 +330,10 @@ namespace DetourNavigator if (agent->second.empty()) locked->erase(agent); } + + std::size_t AsyncNavMeshUpdater::getTotalThreadJobsUnsafe() const + { + return std::accumulate(mThreadsQueues.begin(), mThreadsQueues.end(), std::size_t(0), + [] (auto r, const auto& v) { return r + v.second.mJobs.size(); }); + } } diff --git a/components/detournavigator/asyncnavmeshupdater.hpp b/components/detournavigator/asyncnavmeshupdater.hpp index 3f17d5ca0f..c833d617c0 100644 --- a/components/detournavigator/asyncnavmeshupdater.hpp +++ b/components/detournavigator/asyncnavmeshupdater.hpp @@ -114,6 +114,8 @@ namespace DetourNavigator std::thread::id lockTile(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile); void unlockTile(const osg::Vec3f& agentHalfExtents, const TilePosition& changedTile); + + inline std::size_t getTotalThreadJobsUnsafe() const; }; }