From c8fc7abade6e28507f2a1590007a098e647026a9 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 14 Feb 2020 01:28:50 -0500 Subject: thread-safe OriginConnection ThreadPool now keeps threads running keep ModThreads around so avoid reallocating buffers --- src/shared/directoryentry.cpp | 101 +++++++++++++++++++++++++++++++++--------- src/shared/directoryentry.h | 8 +++- 2 files changed, 87 insertions(+), 22 deletions(-) (limited to 'src/shared') diff --git a/src/shared/directoryentry.cpp b/src/shared/directoryentry.cpp index 19500167..4e64d1c1 100644 --- a/src/shared/directoryentry.cpp +++ b/src/shared/directoryentry.cpp @@ -211,35 +211,57 @@ public: --OriginConnectionCount; } + std::pair getOrCreate( + const std::wstring &originName, const std::wstring &directory, int priority, + const boost::shared_ptr& fileRegister, + const boost::shared_ptr& originConnection, + DirectoryStats& stats) + { + std::unique_lock lock(m_Mutex); + + auto itor = m_OriginsNameMap.find(originName); + + if (itor == m_OriginsNameMap.end()) { + FilesOrigin& origin = createOriginNoLock( + originName, directory, priority, fileRegister, originConnection); + + return {origin, true}; + } else { + FilesOrigin& origin = m_Origins[itor->second]; + lock.unlock(); + + origin.enable(true, stats); + return {origin, false}; + } + } + FilesOrigin& createOrigin( const std::wstring &originName, const std::wstring &directory, int priority, boost::shared_ptr fileRegister, boost::shared_ptr originConnection) { - int newID = createID(); - - auto itor = m_Origins.insert({newID, FilesOrigin( - newID, originName, directory, priority, - fileRegister, originConnection)}).first; - - m_OriginsNameMap.insert({originName, newID}); - m_OriginsPriorityMap.insert({priority, newID}); + std::scoped_lock lock(m_Mutex); - return itor->second; + return createOriginNoLock( + originName, directory, priority, fileRegister, originConnection); } bool exists(const std::wstring &name) { + std::scoped_lock lock(m_Mutex); return m_OriginsNameMap.find(name) != m_OriginsNameMap.end(); } FilesOrigin &getByID(Index ID) { + std::scoped_lock lock(m_Mutex); return m_Origins[ID]; } const FilesOrigin* findByID(Index ID) const { + std::scoped_lock lock(m_Mutex); + auto itor = m_Origins.find(ID); if (itor == m_Origins.end()) { @@ -251,6 +273,8 @@ public: FilesOrigin &getByName(const std::wstring &name) { + std::scoped_lock lock(m_Mutex); + std::map::iterator iter = m_OriginsNameMap.find(name); if (iter != m_OriginsNameMap.end()) { @@ -264,6 +288,8 @@ public: void changePriorityLookup(int oldPriority, int newPriority) { + std::scoped_lock lock(m_Mutex); + auto iter = m_OriginsPriorityMap.find(oldPriority); if (iter != m_OriginsPriorityMap.end()) { @@ -275,6 +301,8 @@ public: void changeNameLookup(const std::wstring &oldName, const std::wstring &newName) { + std::scoped_lock lock(m_Mutex); + auto iter = m_OriginsNameMap.find(oldName); if (iter != m_OriginsNameMap.end()) { @@ -291,11 +319,29 @@ private: std::map m_Origins; std::map m_OriginsNameMap; std::map m_OriginsPriorityMap; + mutable std::mutex m_Mutex; Index createID() { return m_NextID++; } + + FilesOrigin& createOriginNoLock( + const std::wstring &originName, const std::wstring &directory, int priority, + boost::shared_ptr fileRegister, + boost::shared_ptr originConnection) + { + int newID = createID(); + + auto itor = m_Origins.insert({newID, FilesOrigin( + newID, originName, directory, priority, + fileRegister, originConnection)}).first; + + m_OriginsNameMap.insert({originName, newID}); + m_OriginsPriorityMap.insert({priority, newID}); + + return itor->second; + } }; @@ -898,11 +944,19 @@ void DirectoryEntry::clear() void DirectoryEntry::addFromOrigin( const std::wstring &originName, const std::wstring &directory, int priority, DirectoryStats& stats) +{ + env::DirectoryWalker walker; + addFromOrigin(walker, originName, directory, priority, stats); +} + +void DirectoryEntry::addFromOrigin( + env::DirectoryWalker& walker, const std::wstring &originName, + const std::wstring &directory, int priority, DirectoryStats& stats) { FilesOrigin &origin = createOrigin(originName, directory, priority, stats); if (!directory.empty()) { - addFiles(origin, directory, stats); + addFiles(walker, origin, directory, stats); } m_Populated = true; @@ -993,7 +1047,10 @@ void DirectoryEntry::addFromBSA( void DirectoryEntry::propagateOrigin(int origin) { - m_Origins.insert(origin); + { + std::scoped_lock lock(m_OriginsMutex); + m_Origins.insert(origin); + } if (m_Parent != nullptr) { m_Parent->propagateOrigin(origin); @@ -1252,16 +1309,17 @@ FilesOrigin &DirectoryEntry::createOrigin( const std::wstring &originName, const std::wstring &directory, int priority, DirectoryStats& stats) { - if (m_OriginConnection->exists(originName)) { - ++stats.originExists; - FilesOrigin &origin = m_OriginConnection->getByName(originName); - origin.enable(true, stats); - return origin; - } else { + auto r = m_OriginConnection->getOrCreate( + originName, directory, priority, + m_FileRegister, m_OriginConnection, stats); + + if (r.second) { ++stats.originCreate; - return m_OriginConnection->createOrigin( - originName, directory, priority, m_FileRegister, m_OriginConnection); + } else { + ++stats.originExists; } + + return r.first; } void DirectoryEntry::removeFiles(const std::set &indices) @@ -1359,7 +1417,8 @@ FileEntry::Ptr DirectoryEntry::insert( } void DirectoryEntry::addFiles( - FilesOrigin &origin, const std::wstring& path, DirectoryStats& stats) + env::DirectoryWalker& walker, FilesOrigin &origin, + const std::wstring& path, DirectoryStats& stats) { struct Context { @@ -1371,7 +1430,7 @@ void DirectoryEntry::addFiles( Context cx = {origin, stats}; cx.current.push(this); - env::forEachEntry(path, &cx, + walker.forEachEntry(path, &cx, [](void* pcx, std::wstring_view path) { Context* cx = (Context*)pcx; diff --git a/src/shared/directoryentry.h b/src/shared/directoryentry.h index 8f6afbb1..2a70d486 100644 --- a/src/shared/directoryentry.h +++ b/src/shared/directoryentry.h @@ -410,6 +410,10 @@ public: const std::wstring &originName, const std::wstring &directory, int priority, DirectoryStats& stats); + void addFromOrigin( + env::DirectoryWalker& walker, const std::wstring &originName, + const std::wstring &directory, int priority, DirectoryStats& stats); + void addFromBSA( const std::wstring &originName, std::wstring &directory, const std::wstring &fileName, int priority, int order); @@ -556,6 +560,7 @@ private: bool m_TopLevel; std::mutex m_SubDirMutex; std::mutex m_FilesMutex; + std::mutex m_OriginsMutex; DirectoryEntry(const DirectoryEntry &reference); @@ -569,7 +574,8 @@ private: std::wstring_view archive, int order, DirectoryStats& stats); void addFiles( - FilesOrigin &origin, const std::wstring& path, DirectoryStats& stats); + env::DirectoryWalker& walker, FilesOrigin &origin, + const std::wstring& path, DirectoryStats& stats); void addFiles( FilesOrigin &origin, BSA::Folder::Ptr archiveFolder, FILETIME &fileTime, -- cgit v1.3.1