1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-12 13:13:27 +00:00

Use ScopeGuarded instead of raw mutex

This commit is contained in:
elsid 2018-09-29 22:57:41 +03:00
parent cf4066751c
commit ae7285e960
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40
7 changed files with 112 additions and 112 deletions

View File

@ -72,9 +72,7 @@ namespace DetourNavigator
const std::shared_ptr<NavMeshCacheItem>& navMeshCacheItem, const TilePosition& playerTile, const std::shared_ptr<NavMeshCacheItem>& navMeshCacheItem, const TilePosition& playerTile,
const std::map<TilePosition, ChangeType>& changedTiles) const std::map<TilePosition, ChangeType>& changedTiles)
{ {
log("post jobs playerTile=", playerTile); *mPlayerTile.lock() = playerTile;
setPlayerTile(playerTile);
if (changedTiles.empty()) if (changedTiles.empty())
return; return;
@ -124,10 +122,10 @@ namespace DetourNavigator
const auto start = std::chrono::steady_clock::now(); const auto start = std::chrono::steady_clock::now();
setFirstStart(start); const auto firstStart = setFirstStart(start);
const auto recastMesh = mRecastMeshManager.get().getMesh(job.mChangedTile); const auto recastMesh = mRecastMeshManager.get().getMesh(job.mChangedTile);
const auto playerTile = getPlayerTile(); const auto playerTile = *mPlayerTile.lockConst();
const auto offMeshConnections = mOffMeshConnectionsManager.get().get(job.mChangedTile); const auto offMeshConnections = mOffMeshConnectionsManager.get().get(job.mChangedTile);
const auto status = updateNavMesh(job.mAgentHalfExtents, recastMesh.get(), job.mChangedTile, playerTile, const auto status = updateNavMesh(job.mAgentHalfExtents, recastMesh.get(), job.mChangedTile, playerTile,
@ -143,7 +141,7 @@ namespace DetourNavigator
" generation=", job.mNavMeshCacheItem->mGeneration, " generation=", job.mNavMeshCacheItem->mGeneration,
" revision=", job.mNavMeshCacheItem->mNavMeshRevision, " revision=", job.mNavMeshCacheItem->mNavMeshRevision,
" time=", std::chrono::duration_cast<FloatMs>(finish - start).count(), "ms", " time=", std::chrono::duration_cast<FloatMs>(finish - start).count(), "ms",
" total_time=", std::chrono::duration_cast<FloatMs>(finish - getFirstStart()).count(), "ms"); " total_time=", std::chrono::duration_cast<FloatMs>(finish - firstStart).count(), "ms");
} }
boost::optional<AsyncNavMeshUpdater::Job> AsyncNavMeshUpdater::getNextJob() boost::optional<AsyncNavMeshUpdater::Job> AsyncNavMeshUpdater::getNextJob()
@ -188,28 +186,11 @@ namespace DetourNavigator
writeToFile(*job.mNavMeshCacheItem->mValue.lock(), mSettings.get().mNavMeshPathPrefix, navMeshRevision); writeToFile(*job.mNavMeshCacheItem->mValue.lock(), mSettings.get().mNavMeshPathPrefix, navMeshRevision);
} }
std::chrono::steady_clock::time_point AsyncNavMeshUpdater::getFirstStart() std::chrono::steady_clock::time_point AsyncNavMeshUpdater::setFirstStart(const std::chrono::steady_clock::time_point& value)
{ {
const std::lock_guard<std::mutex> lock(mFirstStartMutex); const auto locked = mFirstStart.lock();
return *mFirstStart; if (!*locked)
} *locked = value;
return *locked.get();
void AsyncNavMeshUpdater::setFirstStart(const std::chrono::steady_clock::time_point& value)
{
const std::lock_guard<std::mutex> lock(mFirstStartMutex);
if (!mFirstStart)
mFirstStart = value;
}
TilePosition AsyncNavMeshUpdater::getPlayerTile()
{
const std::lock_guard<std::mutex> lock(mPlayerTileMutex);
return mPlayerTile;
}
void AsyncNavMeshUpdater::setPlayerTile(const TilePosition& value)
{
const std::lock_guard<std::mutex> lock(mPlayerTileMutex);
mPlayerTile = value;
} }
} }

View File

@ -67,10 +67,8 @@ namespace DetourNavigator
std::condition_variable mDone; std::condition_variable mDone;
Jobs mJobs; Jobs mJobs;
std::map<osg::Vec3f, std::set<TilePosition>> mPushed; std::map<osg::Vec3f, std::set<TilePosition>> mPushed;
std::mutex mPlayerTileMutex; Misc::ScopeGuarded<TilePosition> mPlayerTile;
TilePosition mPlayerTile; Misc::ScopeGuarded<boost::optional<std::chrono::steady_clock::time_point>> mFirstStart;
std::mutex mFirstStartMutex;
boost::optional<std::chrono::steady_clock::time_point> mFirstStart;
std::vector<std::thread> mThreads; std::vector<std::thread> mThreads;
void process() throw(); void process() throw();
@ -79,17 +77,9 @@ namespace DetourNavigator
boost::optional<Job> getNextJob(); boost::optional<Job> getNextJob();
void notifyHasJob();
void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const; void writeDebugFiles(const Job& job, const RecastMesh* recastMesh) const;
std::chrono::steady_clock::time_point getFirstStart(); std::chrono::steady_clock::time_point setFirstStart(const std::chrono::steady_clock::time_point& value);
void setFirstStart(const std::chrono::steady_clock::time_point& value);
TilePosition getPlayerTile();
void setPlayerTile(const TilePosition& value);
}; };
} }

View File

@ -4,6 +4,7 @@
#include "tilebounds.hpp" #include "tilebounds.hpp"
#include <components/bullethelpers/operators.hpp> #include <components/bullethelpers/operators.hpp>
#include <components/misc/guarded.hpp>
#include <components/osghelpers/operators.hpp> #include <components/osghelpers/operators.hpp>
#include <chrono> #include <chrono>
@ -11,7 +12,6 @@
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include <memory> #include <memory>
#include <mutex>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <thread> #include <thread>
@ -77,21 +77,19 @@ namespace DetourNavigator
public: public:
void setSink(std::unique_ptr<Sink> sink) void setSink(std::unique_ptr<Sink> sink)
{ {
const std::lock_guard<std::mutex> guard(mMutex); *mSink.lock() = std::move(sink);
mSink = std::move(sink);
} }
bool isEnabled() const bool isEnabled()
{ {
const std::lock_guard<std::mutex> guard(mMutex); return bool(*mSink.lockConst());
return bool(mSink);
} }
void write(const std::string& text) void write(const std::string& text)
{ {
const std::lock_guard<std::mutex> guard(mMutex); const auto sink = mSink.lock();
if (mSink) if (*sink)
mSink->write(text); sink.get()->write(text);
} }
static Log& instance() static Log& instance()
@ -101,8 +99,7 @@ namespace DetourNavigator
} }
private: private:
mutable std::mutex mMutex; Misc::ScopeGuarded<std::unique_ptr<Sink>> mSink;
std::unique_ptr<Sink> mSink;
}; };
inline void write(std::ostream& stream) inline void write(std::ostream& stream)

View File

@ -6,6 +6,8 @@
#include "tileposition.hpp" #include "tileposition.hpp"
#include "objectid.hpp" #include "objectid.hpp"
#include <components/misc/guarded.hpp>
#include <osg/Vec3f> #include <osg/Vec3f>
#include <boost/optional.hpp> #include <boost/optional.hpp>
@ -33,42 +35,42 @@ namespace DetourNavigator
bool add(const ObjectId id, const OffMeshConnection& value) bool add(const ObjectId id, const OffMeshConnection& value)
{ {
const std::lock_guard<std::mutex> lock(mMutex); const auto values = mValues.lock();
if (!mValuesById.insert(std::make_pair(id, value)).second) if (!values->mById.insert(std::make_pair(id, value)).second)
return false; return false;
const auto startTilePosition = getTilePosition(mSettings, value.mStart); const auto startTilePosition = getTilePosition(mSettings, value.mStart);
const auto endTilePosition = getTilePosition(mSettings, value.mEnd); const auto endTilePosition = getTilePosition(mSettings, value.mEnd);
mValuesByTilePosition[startTilePosition].insert(id); values->mByTilePosition[startTilePosition].insert(id);
if (startTilePosition != endTilePosition) if (startTilePosition != endTilePosition)
mValuesByTilePosition[endTilePosition].insert(id); values->mByTilePosition[endTilePosition].insert(id);
return true; return true;
} }
boost::optional<OffMeshConnection> remove(const ObjectId id) boost::optional<OffMeshConnection> remove(const ObjectId id)
{ {
const std::lock_guard<std::mutex> lock(mMutex); const auto values = mValues.lock();
const auto itById = mValuesById.find(id); const auto itById = values->mById.find(id);
if (itById == mValuesById.end()) if (itById == values->mById.end())
return boost::none; return boost::none;
const auto result = itById->second; const auto result = itById->second;
mValuesById.erase(itById); values->mById.erase(itById);
const auto startTilePosition = getTilePosition(mSettings, result.mStart); const auto startTilePosition = getTilePosition(mSettings, result.mStart);
const auto endTilePosition = getTilePosition(mSettings, result.mEnd); const auto endTilePosition = getTilePosition(mSettings, result.mEnd);
removeByTilePosition(startTilePosition, id); removeByTilePosition(values->mByTilePosition, startTilePosition, id);
if (startTilePosition != endTilePosition) if (startTilePosition != endTilePosition)
removeByTilePosition(endTilePosition, id); removeByTilePosition(values->mByTilePosition, endTilePosition, id);
return result; return result;
} }
@ -77,18 +79,18 @@ namespace DetourNavigator
{ {
std::vector<OffMeshConnection> result; std::vector<OffMeshConnection> result;
const std::lock_guard<std::mutex> lock(mMutex); const auto values = mValues.lock();
const auto itByTilePosition = mValuesByTilePosition.find(tilePosition); const auto itByTilePosition = values->mByTilePosition.find(tilePosition);
if (itByTilePosition == mValuesByTilePosition.end()) if (itByTilePosition == values->mByTilePosition.end())
return result; return result;
std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(), std::for_each(itByTilePosition->second.begin(), itByTilePosition->second.end(),
[&] (const ObjectId v) [&] (const ObjectId v)
{ {
const auto itById = mValuesById.find(v); const auto itById = values->mById.find(v);
if (itById != mValuesById.end()) if (itById != values->mById.end())
result.push_back(itById->second); result.push_back(itById->second);
}); });
@ -96,15 +98,20 @@ namespace DetourNavigator
} }
private: private:
const Settings& mSettings; struct Values
std::mutex mMutex;
std::unordered_map<ObjectId, OffMeshConnection> mValuesById;
std::map<TilePosition, std::unordered_set<ObjectId>> mValuesByTilePosition;
void removeByTilePosition(const TilePosition& tilePosition, const ObjectId id)
{ {
const auto it = mValuesByTilePosition.find(tilePosition); std::unordered_map<ObjectId, OffMeshConnection> mById;
if (it != mValuesByTilePosition.end()) std::map<TilePosition, std::unordered_set<ObjectId>> mByTilePosition;
};
const Settings& mSettings;
Misc::ScopeGuarded<Values> mValues;
void removeByTilePosition(std::map<TilePosition, std::unordered_set<ObjectId>>& valuesByTilePosition,
const TilePosition& tilePosition, const ObjectId id)
{
const auto it = valuesByTilePosition.find(tilePosition);
if (it != valuesByTilePosition.end())
it->second.erase(id); it->second.erase(id);
} }
}; };

View File

@ -17,19 +17,18 @@ namespace DetourNavigator
const auto border = getBorderSize(mSettings); const auto border = getBorderSize(mSettings);
getTilesPositions(shape, transform, mSettings, [&] (const TilePosition& tilePosition) getTilesPositions(shape, transform, mSettings, [&] (const TilePosition& tilePosition)
{ {
std::unique_lock<std::mutex> lock(mTilesMutex); const auto tiles = mTiles.lock();
auto tile = mTiles.find(tilePosition); auto tile = tiles->find(tilePosition);
if (tile == mTiles.end()) if (tile == tiles->end())
{ {
auto tileBounds = makeTileBounds(mSettings, tilePosition); auto tileBounds = makeTileBounds(mSettings, tilePosition);
tileBounds.mMin -= osg::Vec2f(border, border); tileBounds.mMin -= osg::Vec2f(border, border);
tileBounds.mMax += osg::Vec2f(border, border); tileBounds.mMax += osg::Vec2f(border, border);
tile = mTiles.insert(std::make_pair(tilePosition, tile = tiles->insert(std::make_pair(tilePosition,
CachedRecastMeshManager(mSettings, tileBounds))).first; CachedRecastMeshManager(mSettings, tileBounds))).first;
} }
if (tile->second.addObject(id, shape, transform, areaType)) if (tile->second.addObject(id, shape, transform, areaType))
{ {
lock.unlock();
tilesPositions.push_back(tilePosition); tilesPositions.push_back(tilePosition);
result = true; result = true;
} }
@ -46,14 +45,15 @@ namespace DetourNavigator
if (object == mObjectsTilesPositions.end()) if (object == mObjectsTilesPositions.end())
return false; return false;
bool result = false; bool result = false;
std::unique_lock<std::mutex> lock(mTilesMutex); {
const auto tiles = mTiles.lock();
for (const auto& tilePosition : object->second) for (const auto& tilePosition : object->second)
{ {
const auto tile = mTiles.find(tilePosition); const auto tile = tiles->find(tilePosition);
if (tile != mTiles.end()) if (tile != tiles->end())
result = tile->second.updateObject(id, transform, areaType) || result; result = tile->second.updateObject(id, transform, areaType) || result;
} }
lock.unlock(); }
if (result) if (result)
++mRevision; ++mRevision;
return result; return result;
@ -67,14 +67,13 @@ namespace DetourNavigator
boost::optional<RemovedRecastMeshObject> result; boost::optional<RemovedRecastMeshObject> result;
for (const auto& tilePosition : object->second) for (const auto& tilePosition : object->second)
{ {
std::unique_lock<std::mutex> lock(mTilesMutex); const auto tiles = mTiles.lock();
const auto tile = mTiles.find(tilePosition); const auto tile = tiles->find(tilePosition);
if (tile == mTiles.end()) if (tile == tiles->end())
continue; continue;
const auto tileResult = tile->second.removeObject(id); const auto tileResult = tile->second.removeObject(id);
if (tile->second.isEmpty()) if (tile->second.isEmpty())
mTiles.erase(tile); tiles->erase(tile);
lock.unlock();
if (tileResult && !result) if (tileResult && !result)
result = tileResult; result = tileResult;
} }
@ -94,8 +93,8 @@ namespace DetourNavigator
if (cellSize == std::numeric_limits<int>::max()) if (cellSize == std::numeric_limits<int>::max())
{ {
const std::lock_guard<std::mutex> lock(mTilesMutex); const auto tiles = mTiles.lock();
for (auto& tile : mTiles) for (auto& tile : *tiles)
{ {
if (tile.second.addWater(cellPosition, cellSize, transform)) if (tile.second.addWater(cellPosition, cellSize, transform))
{ {
@ -108,19 +107,18 @@ namespace DetourNavigator
{ {
getTilesPositions(cellSize, transform, mSettings, [&] (const TilePosition& tilePosition) getTilesPositions(cellSize, transform, mSettings, [&] (const TilePosition& tilePosition)
{ {
std::unique_lock<std::mutex> lock(mTilesMutex); const auto tiles = mTiles.lock();
auto tile = mTiles.find(tilePosition); auto tile = tiles->find(tilePosition);
if (tile == mTiles.end()) if (tile == tiles->end())
{ {
auto tileBounds = makeTileBounds(mSettings, tilePosition); auto tileBounds = makeTileBounds(mSettings, tilePosition);
tileBounds.mMin -= osg::Vec2f(border, border); tileBounds.mMin -= osg::Vec2f(border, border);
tileBounds.mMax += osg::Vec2f(border, border); tileBounds.mMax += osg::Vec2f(border, border);
tile = mTiles.insert(std::make_pair(tilePosition, tile = tiles->insert(std::make_pair(tilePosition,
CachedRecastMeshManager(mSettings, tileBounds))).first; CachedRecastMeshManager(mSettings, tileBounds))).first;
} }
if (tile->second.addWater(cellPosition, cellSize, transform)) if (tile->second.addWater(cellPosition, cellSize, transform))
{ {
lock.unlock();
tilesPositions.push_back(tilePosition); tilesPositions.push_back(tilePosition);
result = true; result = true;
} }
@ -141,14 +139,13 @@ namespace DetourNavigator
boost::optional<RecastMeshManager::Water> result; boost::optional<RecastMeshManager::Water> result;
for (const auto& tilePosition : object->second) for (const auto& tilePosition : object->second)
{ {
std::unique_lock<std::mutex> lock(mTilesMutex); const auto tiles = mTiles.lock();
const auto tile = mTiles.find(tilePosition); const auto tile = tiles->find(tilePosition);
if (tile == mTiles.end()) if (tile == tiles->end())
continue; continue;
const auto tileResult = tile->second.removeWater(cellPosition); const auto tileResult = tile->second.removeWater(cellPosition);
if (tile->second.isEmpty()) if (tile->second.isEmpty())
mTiles.erase(tile); tiles->erase(tile);
lock.unlock();
if (tileResult && !result) if (tileResult && !result)
result = tileResult; result = tileResult;
} }
@ -159,17 +156,16 @@ namespace DetourNavigator
std::shared_ptr<RecastMesh> TileCachedRecastMeshManager::getMesh(const TilePosition& tilePosition) std::shared_ptr<RecastMesh> TileCachedRecastMeshManager::getMesh(const TilePosition& tilePosition)
{ {
const std::lock_guard<std::mutex> lock(mTilesMutex); const auto tiles = mTiles.lock();
const auto it = mTiles.find(tilePosition); const auto it = tiles->find(tilePosition);
if (it == mTiles.end()) if (it == tiles->end())
return nullptr; return nullptr;
return it->second.getMesh(); return it->second.getMesh();
} }
bool TileCachedRecastMeshManager::hasTile(const TilePosition& tilePosition) bool TileCachedRecastMeshManager::hasTile(const TilePosition& tilePosition)
{ {
const std::lock_guard<std::mutex> lock(mTilesMutex); return mTiles.lockConst()->count(tilePosition);
return mTiles.count(tilePosition);
} }
std::size_t TileCachedRecastMeshManager::getRevision() const std::size_t TileCachedRecastMeshManager::getRevision() const

View File

@ -4,6 +4,8 @@
#include "cachedrecastmeshmanager.hpp" #include "cachedrecastmeshmanager.hpp"
#include "tileposition.hpp" #include "tileposition.hpp"
#include <components/misc/guarded.hpp>
#include <map> #include <map>
#include <mutex> #include <mutex>
@ -32,8 +34,7 @@ namespace DetourNavigator
template <class Function> template <class Function>
void forEachTilePosition(Function&& function) void forEachTilePosition(Function&& function)
{ {
const std::lock_guard<std::mutex> lock(mTilesMutex); for (const auto& tile : *mTiles.lock())
for (const auto& tile : mTiles)
function(tile.first); function(tile.first);
} }
@ -41,8 +42,7 @@ namespace DetourNavigator
private: private:
const Settings& mSettings; const Settings& mSettings;
std::mutex mTilesMutex; Misc::ScopeGuarded<std::map<TilePosition, CachedRecastMeshManager>> mTiles;
std::map<TilePosition, CachedRecastMeshManager> mTiles;
std::unordered_map<ObjectId, std::vector<TilePosition>> mObjectsTilesPositions; std::unordered_map<ObjectId, std::vector<TilePosition>> mObjectsTilesPositions;
std::map<osg::Vec2i, std::vector<TilePosition>> mWaterTilesPositions; std::map<osg::Vec2i, std::vector<TilePosition>> mWaterTilesPositions;
std::size_t mRevision = 0; std::size_t mRevision = 0;

View File

@ -34,6 +34,35 @@ namespace Misc
std::reference_wrapper<T> mValue; std::reference_wrapper<T> mValue;
}; };
template <class T>
class ScopeGuarded
{
public:
ScopeGuarded() = default;
ScopeGuarded(const T& value)
: mValue(value)
{}
ScopeGuarded(T&& value)
: mValue(std::move(value))
{}
Locked<T> lock()
{
return Locked<T>(mMutex, mValue);
}
Locked<const T> lockConst()
{
return Locked<const T>(mMutex, mValue);
}
private:
std::mutex mMutex;
T mValue;
};
template <class T> template <class T>
class SharedGuarded class SharedGuarded
{ {