From ee5b68f1fcbc4d4f0d08fef9d1d0fb4d745ca868 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 9 Dec 2017 16:47:37 -0800 Subject: [PATCH 1/5] Loaders: Add cancelation to all file loaders. Mainly, for HTTP which might be stalled trying to connect (especially if you're not near your PC right now and it's in your recent, for example.) --- Core/FileLoaders/CachingFileLoader.cpp | 6 +++++- Core/FileLoaders/CachingFileLoader.h | 10 ++++++---- Core/FileLoaders/DiskCachingFileLoader.cpp | 23 +++++++++++----------- Core/FileLoaders/DiskCachingFileLoader.h | 14 +++++++------ Core/FileLoaders/HTTPFileLoader.cpp | 17 +++++++++++++++- Core/FileLoaders/HTTPFileLoader.h | 17 ++++++++-------- Core/FileLoaders/RamCachingFileLoader.cpp | 20 ++++++++++++------- Core/FileLoaders/RamCachingFileLoader.h | 13 +++++++----- Core/FileLoaders/RetryingFileLoader.cpp | 4 ++++ Core/FileLoaders/RetryingFileLoader.h | 2 ++ Core/Loaders.h | 4 ++++ 11 files changed, 87 insertions(+), 43 deletions(-) diff --git a/Core/FileLoaders/CachingFileLoader.cpp b/Core/FileLoaders/CachingFileLoader.cpp index 5e7b1b67e1..55429da251 100644 --- a/Core/FileLoaders/CachingFileLoader.cpp +++ b/Core/FileLoaders/CachingFileLoader.cpp @@ -25,7 +25,7 @@ // Takes ownership of backend. CachingFileLoader::CachingFileLoader(FileLoader *backend) - : filesize_(0), backend_(backend), exists_(-1), isDirectory_(-1), aheadThread_(false) { + : backend_(backend) { } void CachingFileLoader::Prepare() { @@ -288,3 +288,7 @@ void CachingFileLoader::StartReadAhead(s64 pos) { }); th.detach(); } + +void CachingFileLoader::Cancel() { + backend_->Cancel(); +} diff --git a/Core/FileLoaders/CachingFileLoader.h b/Core/FileLoaders/CachingFileLoader.h index c9f3031139..bdfc268daf 100644 --- a/Core/FileLoaders/CachingFileLoader.h +++ b/Core/FileLoaders/CachingFileLoader.h @@ -39,6 +39,8 @@ public: } size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override; + void Cancel() override; + private: void Prepare(); void InitCache(); @@ -57,10 +59,10 @@ private: BLOCK_READAHEAD = 4, }; - s64 filesize_; + s64 filesize_ = 0; FileLoader *backend_; - int exists_; - int isDirectory_; + int exists_ = -1; + int isDirectory_ = -1; u64 generation_; u64 oldestGeneration_; size_t cacheSize_; @@ -77,6 +79,6 @@ private: std::map blocks_; std::recursive_mutex blocksMutex_; - bool aheadThread_; + bool aheadThread_ = false; std::once_flag preparedFlag_; }; diff --git a/Core/FileLoaders/DiskCachingFileLoader.cpp b/Core/FileLoaders/DiskCachingFileLoader.cpp index 912ca4f509..6fd2320068 100644 --- a/Core/FileLoaders/DiskCachingFileLoader.cpp +++ b/Core/FileLoaders/DiskCachingFileLoader.cpp @@ -41,19 +41,16 @@ std::mutex DiskCachingFileLoader::cachesMutex_; // Takes ownership of backend. DiskCachingFileLoader::DiskCachingFileLoader(FileLoader *backend) - : prepared_(false), filesize_(0), backend_(backend), cache_(nullptr) { + : backend_(backend) { } void DiskCachingFileLoader::Prepare() { - if (prepared_) { - return; - } - prepared_ = true; - - filesize_ = backend_->FileSize(); - if (filesize_ > 0) { - InitCache(); - } + std::call_once(preparedFlag_, [this]() { + filesize_ = backend_->FileSize(); + if (filesize_ > 0) { + InitCache(); + } + }); } DiskCachingFileLoader::~DiskCachingFileLoader() { @@ -118,6 +115,10 @@ size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, return readSize; } +void DiskCachingFileLoader::Cancel() { + backend_->Cancel(); +} + std::vector DiskCachingFileLoader::GetCachedPathsInUse() { std::lock_guard guard(cachesMutex_); @@ -156,7 +157,7 @@ void DiskCachingFileLoader::ShutdownCache() { } DiskCachingFileLoaderCache::DiskCachingFileLoaderCache(const std::string &path, u64 filesize) - : refCount_(0), filesize_(filesize), origPath_(path), f_(nullptr), fd_(0) { + : filesize_(filesize), origPath_(path) { InitCache(path); } diff --git a/Core/FileLoaders/DiskCachingFileLoader.h b/Core/FileLoaders/DiskCachingFileLoader.h index 1ea27ee0cb..fb02c6c33b 100644 --- a/Core/FileLoaders/DiskCachingFileLoader.h +++ b/Core/FileLoaders/DiskCachingFileLoader.h @@ -43,6 +43,8 @@ public: } size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override; + void Cancel() override; + static std::vector GetCachedPathsInUse(); private: @@ -50,10 +52,10 @@ private: void InitCache(); void ShutdownCache(); - bool prepared_; - s64 filesize_; + std::once_flag preparedFlag_; + s64 filesize_ = 0; FileLoader *backend_; - DiskCachingFileLoaderCache *cache_; + DiskCachingFileLoaderCache *cache_ = nullptr; // We don't support concurrent disk cache access (we use memory cached indexes.) // So we have to ensure there's only one of these per. @@ -139,7 +141,7 @@ private: INVALID_INDEX = 0xFFFFFFFF, }; - int refCount_; + int refCount_ = 0; s64 filesize_; u32 blockSize_; u16 generation_; @@ -176,8 +178,8 @@ private: std::vector index_; std::vector blockIndexLookup_; - FILE *f_; - int fd_; + FILE *f_ = nullptr; + int fd_ = 0; static std::string cacheDir_; }; diff --git a/Core/FileLoaders/HTTPFileLoader.cpp b/Core/FileLoaders/HTTPFileLoader.cpp index c18e7eef56..4dda285844 100644 --- a/Core/FileLoaders/HTTPFileLoader.cpp +++ b/Core/FileLoaders/HTTPFileLoader.cpp @@ -22,7 +22,7 @@ #include "Core/FileLoaders/HTTPFileLoader.h" HTTPFileLoader::HTTPFileLoader(const std::string &filename) - : filesize_(0), filepos_(0), url_(filename), filename_(filename), connected_(false) { + : url_(filename), filename_(filename) { } void HTTPFileLoader::Prepare() { @@ -33,6 +33,10 @@ void HTTPFileLoader::Prepare() { } Connect(); + if (!connected_) { + return; + } + int err = client_.SendRequest("HEAD", url_.Resource().c_str()); if (err < 0) { Disconnect(); @@ -123,6 +127,9 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f } Connect(); + if (!connected_) { + return 0; + } char requestHeaders[4096]; // Note that the Range header is *inclusive*. @@ -186,3 +193,11 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f filepos_ = absolutePos + readBytes; return readBytes; } + +void HTTPFileLoader::Connect() { + if (!connected_) { + cancelConnect_ = false; + // Latency is important here, so reduce the timeout. + connected_ = client_.Connect(3, 10.0, &cancelConnect_); + } +} diff --git a/Core/FileLoaders/HTTPFileLoader.h b/Core/FileLoaders/HTTPFileLoader.h index 5b27bf5288..9befbb1e63 100644 --- a/Core/FileLoaders/HTTPFileLoader.h +++ b/Core/FileLoaders/HTTPFileLoader.h @@ -41,14 +41,14 @@ public: } virtual size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override; + void Cancel() override { + cancelConnect_ = true; + } + private: void Prepare(); - void Connect() { - if (!connected_) { - connected_ = client_.Connect(); - } - } + void Connect(); void Disconnect() { if (connected_) { @@ -57,12 +57,13 @@ private: connected_ = false; } - s64 filesize_; - s64 filepos_; + s64 filesize_ = 0; + s64 filepos_ = 0; Url url_; http::Client client_; std::string filename_; - bool connected_; + bool connected_ = false; + bool cancelConnect_ = false; std::once_flag preparedFlag_; std::mutex readAtMutex_; diff --git a/Core/FileLoaders/RamCachingFileLoader.cpp b/Core/FileLoaders/RamCachingFileLoader.cpp index 1bc01e9749..0aad8644c2 100644 --- a/Core/FileLoaders/RamCachingFileLoader.cpp +++ b/Core/FileLoaders/RamCachingFileLoader.cpp @@ -28,7 +28,7 @@ // Takes ownership of backend. RamCachingFileLoader::RamCachingFileLoader(FileLoader *backend) - : filesize_(0), backend_(backend), exists_(-1), isDirectory_(-1), aheadThread_(false) { + : backend_(backend) { filesize_ = backend->FileSize(); if (filesize_ > 0) { InitCache(); @@ -107,11 +107,7 @@ void RamCachingFileLoader::InitCache() { } void RamCachingFileLoader::ShutdownCache() { - { - std::lock_guard guard(blocksMutex_); - // Try to have the thread stop. - aheadRemaining_ = 0; - } + Cancel(); // We can't delete while the thread is running, so have to wait. // This should only happen from the menu. @@ -127,6 +123,15 @@ void RamCachingFileLoader::ShutdownCache() { } } +void RamCachingFileLoader::Cancel() { + if (aheadThread_) { + std::lock_guard guard(blocksMutex_); + aheadCancel_ = true; + } + + backend_->Cancel(); +} + size_t RamCachingFileLoader::ReadFromCache(s64 pos, size_t bytes, void *data) { s64 cacheStartPos = pos >> BLOCK_SHIFT; s64 cacheEndPos = (pos + bytes - 1) >> BLOCK_SHIFT; @@ -220,10 +225,11 @@ void RamCachingFileLoader::StartReadAhead(s64 pos) { } aheadThread_ = true; + aheadCancel_ = false; std::thread th([this] { setCurrentThreadName("FileLoaderReadAhead"); - while (aheadRemaining_ != 0) { + while (aheadRemaining_ != 0 && !aheadCancel_) { // Where should we look? const u32 cacheStartPos = NextAheadBlock(); if (cacheStartPos == 0xFFFFFFFF) { diff --git a/Core/FileLoaders/RamCachingFileLoader.h b/Core/FileLoaders/RamCachingFileLoader.h index 0911b43074..4ea38dee04 100644 --- a/Core/FileLoaders/RamCachingFileLoader.h +++ b/Core/FileLoaders/RamCachingFileLoader.h @@ -39,6 +39,8 @@ public: } size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override; + void Cancel() override; + private: void InitCache(); void ShutdownCache(); @@ -55,15 +57,16 @@ private: BLOCK_READAHEAD = 4, }; - s64 filesize_; + s64 filesize_ = 0; FileLoader *backend_; - u8 *cache_; - int exists_; - int isDirectory_; + u8 *cache_ = nullptr; + int exists_ = -1; + int isDirectory_ = -1; std::vector blocks_; std::mutex blocksMutex_; u32 aheadRemaining_; s64 aheadPos_; - bool aheadThread_; + bool aheadThread_ = false; + bool aheadCancel_ = false; }; diff --git a/Core/FileLoaders/RetryingFileLoader.cpp b/Core/FileLoaders/RetryingFileLoader.cpp index b9c7927cc2..d90c852864 100644 --- a/Core/FileLoaders/RetryingFileLoader.cpp +++ b/Core/FileLoaders/RetryingFileLoader.cpp @@ -72,3 +72,7 @@ size_t RetryingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Fla return readSize; } + +void RetryingFileLoader::Cancel() { + backend_->Cancel(); +} diff --git a/Core/FileLoaders/RetryingFileLoader.h b/Core/FileLoaders/RetryingFileLoader.h index 98ed64f036..5e6835dc89 100644 --- a/Core/FileLoaders/RetryingFileLoader.h +++ b/Core/FileLoaders/RetryingFileLoader.h @@ -36,6 +36,8 @@ public: } size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override; + void Cancel() override; + private: enum { MAX_RETRIES = 3, diff --git a/Core/Loaders.h b/Core/Loaders.h index fe24872bfd..ac24f2f3c9 100644 --- a/Core/Loaders.h +++ b/Core/Loaders.h @@ -86,6 +86,10 @@ public: virtual size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) { return ReadAt(absolutePos, 1, bytes, data, flags); } + + // Cancel any operations that might block, if possible. + virtual void Cancel() { + } }; inline u32 operator & (const FileLoader::Flags &a, const FileLoader::Flags &b) { From 2943bbdbfd5a332d333622c81008be535290ea55 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 9 Dec 2017 16:48:38 -0800 Subject: [PATCH 2/5] UI: Cancel loaders on shutdown. Improves backend switching / locking / etc. performance when the recent list has games that aren't currently available. Also, remove unnecessary duplicate gameinfo flush on EGL loop shutdown. Already happens in NativeShutdownGraphics(). --- UI/GameInfoCache.cpp | 13 +++++++++++++ UI/GameInfoCache.h | 1 + android/jni/app-android.cpp | 2 -- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 37f962c874..23fcfc3574 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -674,6 +674,8 @@ void GameInfoCache::Init() { } void GameInfoCache::Shutdown() { + CancelAll(); + if (gameInfoWQ_) { StopProcessingWorkQueue(gameInfoWQ_); delete gameInfoWQ_; @@ -682,6 +684,8 @@ void GameInfoCache::Shutdown() { } void GameInfoCache::Clear() { + CancelAll(); + if (gameInfoWQ_) { gameInfoWQ_->Flush(); gameInfoWQ_->WaitUntilDone(); @@ -689,6 +693,15 @@ void GameInfoCache::Clear() { info_.clear(); } +void GameInfoCache::CancelAll() { + for (auto info : info_) { + FileLoader *fl = info.second->GetFileLoader(); + if (fl) { + fl->Cancel(); + } + } +} + void GameInfoCache::FlushBGs() { for (auto iter = info_.begin(); iter != info_.end(); iter++) { std::lock_guard lock(iter->second->lock); diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index f664a1d621..4cf43a7ca7 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -173,6 +173,7 @@ public: PrioritizedWorkQueue *WorkQueue() { return gameInfoWQ_; } + void CancelAll(); void WaitUntilDone(std::shared_ptr &info); private: diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 5c44abb5a6..87d5d799c0 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1171,8 +1171,6 @@ retry: } ILOG("Leaving EGL/Vulkan render loop."); - if (g_gameInfoCache) - g_gameInfoCache->WorkQueue()->Flush(); NativeShutdownGraphics(); renderer_inited = false; From 8b665ae6962ab45160393337c33fba0c9c2e54c9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 9 Dec 2017 17:07:42 -0800 Subject: [PATCH 3/5] Loaders: Depriorize disc streaming queue items. We want the local items, if any, to load first. This gives us icons, etc. --- Core/FileLoaders/CachingFileLoader.cpp | 4 ++++ Core/FileLoaders/CachingFileLoader.h | 1 + Core/FileLoaders/DiskCachingFileLoader.cpp | 4 ++++ Core/FileLoaders/DiskCachingFileLoader.h | 1 + Core/FileLoaders/HTTPFileLoader.h | 3 +++ Core/FileLoaders/RamCachingFileLoader.cpp | 4 ++++ Core/FileLoaders/RamCachingFileLoader.h | 1 + Core/FileLoaders/RetryingFileLoader.cpp | 4 ++++ Core/FileLoaders/RetryingFileLoader.h | 1 + Core/Loaders.h | 3 +++ UI/GameInfoCache.cpp | 5 +++++ 11 files changed, 31 insertions(+) diff --git a/Core/FileLoaders/CachingFileLoader.cpp b/Core/FileLoaders/CachingFileLoader.cpp index 55429da251..597fafadcc 100644 --- a/Core/FileLoaders/CachingFileLoader.cpp +++ b/Core/FileLoaders/CachingFileLoader.cpp @@ -289,6 +289,10 @@ void CachingFileLoader::StartReadAhead(s64 pos) { th.detach(); } +bool CachingFileLoader::IsRemote() { + return backend_->IsRemote(); +} + void CachingFileLoader::Cancel() { backend_->Cancel(); } diff --git a/Core/FileLoaders/CachingFileLoader.h b/Core/FileLoaders/CachingFileLoader.h index bdfc268daf..03d3aa726e 100644 --- a/Core/FileLoaders/CachingFileLoader.h +++ b/Core/FileLoaders/CachingFileLoader.h @@ -28,6 +28,7 @@ public: CachingFileLoader(FileLoader *backend); ~CachingFileLoader() override; + bool IsRemote() override; bool Exists() override; bool ExistsFast() override; bool IsDirectory() override; diff --git a/Core/FileLoaders/DiskCachingFileLoader.cpp b/Core/FileLoaders/DiskCachingFileLoader.cpp index 6fd2320068..b098df4866 100644 --- a/Core/FileLoaders/DiskCachingFileLoader.cpp +++ b/Core/FileLoaders/DiskCachingFileLoader.cpp @@ -115,6 +115,10 @@ size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, return readSize; } +bool DiskCachingFileLoader::IsRemote() { + return backend_->IsRemote(); +} + void DiskCachingFileLoader::Cancel() { backend_->Cancel(); } diff --git a/Core/FileLoaders/DiskCachingFileLoader.h b/Core/FileLoaders/DiskCachingFileLoader.h index fb02c6c33b..e396ff5736 100644 --- a/Core/FileLoaders/DiskCachingFileLoader.h +++ b/Core/FileLoaders/DiskCachingFileLoader.h @@ -32,6 +32,7 @@ public: DiskCachingFileLoader(FileLoader *backend); ~DiskCachingFileLoader() override; + bool IsRemote() override; bool Exists() override; bool ExistsFast() override; bool IsDirectory() override; diff --git a/Core/FileLoaders/HTTPFileLoader.h b/Core/FileLoaders/HTTPFileLoader.h index 9befbb1e63..ab4773604f 100644 --- a/Core/FileLoaders/HTTPFileLoader.h +++ b/Core/FileLoaders/HTTPFileLoader.h @@ -30,6 +30,9 @@ public: HTTPFileLoader(const std::string &filename); virtual ~HTTPFileLoader() override; + bool IsRemote() override { + return true; + } virtual bool Exists() override; virtual bool ExistsFast() override; virtual bool IsDirectory() override; diff --git a/Core/FileLoaders/RamCachingFileLoader.cpp b/Core/FileLoaders/RamCachingFileLoader.cpp index 0aad8644c2..ccaa3c7bef 100644 --- a/Core/FileLoaders/RamCachingFileLoader.cpp +++ b/Core/FileLoaders/RamCachingFileLoader.cpp @@ -270,3 +270,7 @@ u32 RamCachingFileLoader::NextAheadBlock() { return 0xFFFFFFFF; } + +bool RamCachingFileLoader::IsRemote() { + return backend_->IsRemote(); +} diff --git a/Core/FileLoaders/RamCachingFileLoader.h b/Core/FileLoaders/RamCachingFileLoader.h index 4ea38dee04..624305155a 100644 --- a/Core/FileLoaders/RamCachingFileLoader.h +++ b/Core/FileLoaders/RamCachingFileLoader.h @@ -28,6 +28,7 @@ public: RamCachingFileLoader(FileLoader *backend); ~RamCachingFileLoader() override; + bool IsRemote() override; bool Exists() override; bool ExistsFast() override; bool IsDirectory() override; diff --git a/Core/FileLoaders/RetryingFileLoader.cpp b/Core/FileLoaders/RetryingFileLoader.cpp index d90c852864..4ce1da0261 100644 --- a/Core/FileLoaders/RetryingFileLoader.cpp +++ b/Core/FileLoaders/RetryingFileLoader.cpp @@ -73,6 +73,10 @@ size_t RetryingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Fla return readSize; } +bool RetryingFileLoader::IsRemote() { + return backend_->IsRemote(); +} + void RetryingFileLoader::Cancel() { backend_->Cancel(); } diff --git a/Core/FileLoaders/RetryingFileLoader.h b/Core/FileLoaders/RetryingFileLoader.h index 5e6835dc89..5c8cb59292 100644 --- a/Core/FileLoaders/RetryingFileLoader.h +++ b/Core/FileLoaders/RetryingFileLoader.h @@ -25,6 +25,7 @@ public: RetryingFileLoader(FileLoader *backend); ~RetryingFileLoader() override; + bool IsRemote() override; bool Exists() override; bool ExistsFast() override; bool IsDirectory() override; diff --git a/Core/Loaders.h b/Core/Loaders.h index ac24f2f3c9..05837433f8 100644 --- a/Core/Loaders.h +++ b/Core/Loaders.h @@ -66,6 +66,9 @@ public: virtual ~FileLoader() {} + virtual bool IsRemote() { + return false; + } virtual bool Exists() = 0; virtual bool ExistsFast() { return Exists(); diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 23fcfc3574..b5df8b4776 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -650,6 +650,11 @@ handleELF: } float priority() override { + auto fl = info_->GetFileLoader(); + if (fl && fl->IsRemote()) { + // Increase the value so remote info loads after non-remote. + return info_->lastAccessedTime + 1000.0f; + } return info_->lastAccessedTime; } From 472ee12391a78f95e34752cbab62ff5cf52d7ffd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 9 Dec 2017 17:26:26 -0800 Subject: [PATCH 4/5] UI: Add threadsafety to cache item file loaders. --- UI/GameInfoCache.cpp | 28 ++++++++++++---------------- UI/GameInfoCache.h | 5 +++-- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index b5df8b4776..ad5ddd7bd2 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -54,7 +54,7 @@ GameInfo::~GameInfo() { icon.Clear(); pic0.Clear(); pic1.Clear(); - delete fileLoader; + fileLoader.reset(); } bool GameInfo::Delete() { @@ -218,8 +218,7 @@ bool GameInfo::LoadFromPath(const std::string &gamePath) { std::lock_guard guard(lock); // No need to rebuild if we already have it loaded. if (filePath_ != gamePath) { - delete fileLoader; - fileLoader = ConstructFileLoader(gamePath); + fileLoader.reset(ConstructFileLoader(gamePath)); if (!fileLoader) return false; filePath_ = gamePath; @@ -231,16 +230,15 @@ bool GameInfo::LoadFromPath(const std::string &gamePath) { return fileLoader ? fileLoader->Exists() : true; } -FileLoader *GameInfo::GetFileLoader() { +std::shared_ptr GameInfo::GetFileLoader() { if (!fileLoader) { - fileLoader = ConstructFileLoader(filePath_); + fileLoader.reset(ConstructFileLoader(filePath_)); } return fileLoader; } void GameInfo::DisposeFileLoader() { - delete fileLoader; - fileLoader = nullptr; + fileLoader.reset(); } bool GameInfo::DeleteAllSaveData() { @@ -373,24 +371,22 @@ public: { std::lock_guard lock(info_->lock); info_->working = true; - info_->fileType = Identify_File(info_->GetFileLoader()); + info_->fileType = Identify_File(info_->GetFileLoader().get()); } switch (info_->fileType) { case IdentifiedFileType::PSP_PBP: case IdentifiedFileType::PSP_PBP_DIRECTORY: { - FileLoader *pbpLoader = info_->GetFileLoader(); - std::unique_ptr altLoader; + auto pbpLoader = info_->GetFileLoader(); if (info_->fileType == IdentifiedFileType::PSP_PBP_DIRECTORY) { std::string ebootPath = ResolvePBPFile(gamePath_); if (ebootPath != gamePath_) { - pbpLoader = ConstructFileLoader(ebootPath); - altLoader.reset(pbpLoader); + pbpLoader.reset(ConstructFileLoader(ebootPath)); } } - PBPReader pbp(pbpLoader); + PBPReader pbp(pbpLoader.get()); if (!pbp.IsValid()) { if (pbp.IsELF()) { goto handleELF; @@ -559,10 +555,10 @@ handleELF: // Let's assume it's an ISO. // TODO: This will currently read in the whole directory tree. Not really necessary for just a // few files. - FileLoader *fl = info_->GetFileLoader(); + auto fl = info_->GetFileLoader(); if (!fl) return; // Happens with UWP currently, TODO... - BlockDevice *bd = constructBlockDevice(info_->GetFileLoader()); + BlockDevice *bd = constructBlockDevice(info_->GetFileLoader().get()); if (!bd) return; // nothing to do here.. ISOFileSystem umd(&handles, bd); @@ -700,7 +696,7 @@ void GameInfoCache::Clear() { void GameInfoCache::CancelAll() { for (auto info : info_) { - FileLoader *fl = info.second->GetFileLoader(); + auto fl = info.second->GetFileLoader(); if (fl) { fl->Cancel(); } diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index 4cf43a7ca7..0b4201d4a4 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -93,7 +94,7 @@ public: bool DeleteAllSaveData(); bool LoadFromPath(const std::string &gamePath); - FileLoader *GetFileLoader(); + std::shared_ptr GetFileLoader(); void DisposeFileLoader(); u64 GetGameSizeInBytes(); @@ -148,7 +149,7 @@ protected: // Note: this can change while loading, use GetTitle(). std::string title; - FileLoader *fileLoader = nullptr; + std::shared_ptr fileLoader; std::string filePath_; private: From 27227f87fde14ead3cdeb52c690edacbedee4a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 10 Dec 2017 11:28:27 +0100 Subject: [PATCH 5/5] Don't hold the lock when processing messages, only when taking them off the queue. Fixes #10383 --- UI/NativeApp.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 78918c57e2..bd7c165699 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -942,15 +942,18 @@ void HandleGlobalMessage(const std::string &msg, const std::string &value) { void NativeUpdate() { PROFILE_END_FRAME(); + std::vector toProcess; { std::lock_guard lock(pendingMutex); - for (size_t i = 0; i < pendingMessages.size(); i++) { - HandleGlobalMessage(pendingMessages[i].msg, pendingMessages[i].value); - screenManager->sendMessage(pendingMessages[i].msg.c_str(), pendingMessages[i].value.c_str()); - } + toProcess = std::move(pendingMessages); pendingMessages.clear(); } + for (size_t i = 0; i < toProcess.size(); i++) { + HandleGlobalMessage(toProcess[i].msg, toProcess[i].value); + screenManager->sendMessage(toProcess[i].msg.c_str(), toProcess[i].value.c_str()); + } + g_DownloadManager.Update(); screenManager->update(); }