diff --git a/Core/Config.cpp b/Core/Config.cpp index bbb534fbc6..ebb0521f6e 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -19,8 +19,10 @@ #include #include #include +#include #include #include +#include #include "ppsspp_config.h" @@ -56,6 +58,9 @@ http::Downloader g_DownloadManager; Config g_Config; bool jitForcedOff; +static std::mutex recentIsosLock; +static std::mutex recentIsosThreadLock; +static std::thread recentIsosThread; #ifdef _DEBUG static const char *logSectionName = "LogDebug"; @@ -1206,6 +1211,19 @@ static void IterateSettings(IniFile &iniFile, std::function guard(recentIsosThreadLock); + if (recentIsosThread.joinable()) + recentIsosThread.join(); +} + +static void SetRecentIsosThread(std::function f) { + std::lock_guard guard(recentIsosThreadLock); + if (recentIsosThread.joinable()) + recentIsosThread.join(); + recentIsosThread = std::thread(f); +} + Config::Config() { } @@ -1213,6 +1231,7 @@ Config::~Config() { if (bUpdatedInstanceCounter) { ShutdownInstanceCounter(); } + ResetRecentIsosThread(); } std::map> GetLangValuesMapping() { @@ -1315,6 +1334,8 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) { iMaxRecent = 60; if (iMaxRecent > 0) { + ResetRecentIsosThread(); + std::lock_guard guard(recentIsosLock); recentIsos.clear(); for (int i = 0; i < iMaxRecent; i++) { char keyName[64]; @@ -1470,9 +1491,11 @@ bool Config::Save(const char *saveReason) { Section *recent = iniFile.GetOrCreateSection("Recent"); recent->Set("MaxRecent", iMaxRecent); + ResetRecentIsosThread(); for (int i = 0; i < iMaxRecent; i++) { char keyName[64]; snprintf(keyName, sizeof(keyName), "FileName%d", i); + std::lock_guard guard(recentIsosLock); if (i < (int)recentIsos.size()) { recent->Set(keyName, recentIsos[i]); } else { @@ -1610,6 +1633,8 @@ void Config::AddRecent(const std::string &file) { // We'll add it back below. This makes sure it's at the front, and only once. RemoveRecent(file); + ResetRecentIsosThread(); + std::lock_guard guard(recentIsosLock); const std::string filename = File::ResolvePath(file); recentIsos.insert(recentIsos.begin(), filename); if ((int)recentIsos.size() > iMaxRecent) @@ -1621,6 +1646,8 @@ void Config::RemoveRecent(const std::string &file) { if (iMaxRecent <= 0) return; + ResetRecentIsosThread(); + std::lock_guard guard(recentIsosLock); const std::string filename = File::ResolvePath(file); for (auto iter = recentIsos.begin(); iter != recentIsos.end();) { const std::string recent = File::ResolvePath(*iter); @@ -1634,35 +1661,52 @@ void Config::RemoveRecent(const std::string &file) { } void Config::CleanRecent() { - double startTime = time_now_d(); + SetRecentIsosThread([this] { + double startTime = time_now_d(); - std::vector cleanedRecent; - for (size_t i = 0; i < recentIsos.size(); i++) { - bool exists = false; - Path path = Path(recentIsos[i]); - switch (path.Type()) { - case PathType::CONTENT_URI: - case PathType::NATIVE: - exists = File::Exists(path); - break; - default: - FileLoader *loader = ConstructFileLoader(path); - exists = loader->ExistsFast(); - delete loader; - break; - } + std::lock_guard guard(recentIsosLock); + std::vector cleanedRecent; + for (size_t i = 0; i < recentIsos.size(); i++) { + bool exists = false; + Path path = Path(recentIsos[i]); + switch (path.Type()) { + case PathType::CONTENT_URI: + case PathType::NATIVE: + exists = File::Exists(path); + break; + default: + FileLoader *loader = ConstructFileLoader(path); + exists = loader->ExistsFast(); + delete loader; + break; + } - if (exists) { - // Make sure we don't have any redundant items. - auto duplicate = std::find(cleanedRecent.begin(), cleanedRecent.end(), recentIsos[i]); - if (duplicate == cleanedRecent.end()) { - cleanedRecent.push_back(recentIsos[i]); + if (exists) { + // Make sure we don't have any redundant items. + auto duplicate = std::find(cleanedRecent.begin(), cleanedRecent.end(), recentIsos[i]); + if (duplicate == cleanedRecent.end()) { + cleanedRecent.push_back(recentIsos[i]); + } } } - } - INFO_LOG(SYSTEM, "CleanRecent took %0.2f", time_now_d() - startTime); - recentIsos = cleanedRecent; + INFO_LOG(SYSTEM, "CleanRecent took %0.2f", time_now_d() - startTime); + recentIsos = cleanedRecent; + }); +} + +std::vector Config::RecentIsos() const { + std::lock_guard guard(recentIsosLock); + return recentIsos; +} +bool Config::HasRecentIsos() const { + std::lock_guard guard(recentIsosLock); + return !recentIsos.empty(); +} +void Config::ClearRecentIsos() { + ResetRecentIsosThread(); + std::lock_guard guard(recentIsosLock); + recentIsos.clear(); } void Config::SetSearchPath(const Path &searchPath) { diff --git a/Core/Config.h b/Core/Config.h index 599c7de818..1125f5437b 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -535,15 +535,9 @@ public: return bFullScreen; } - std::vector RecentIsos() const { - return recentIsos; - } - bool HasRecentIsos() const { - return !recentIsos.empty(); - } - void ClearRecentIsos() { - recentIsos.clear(); - } + std::vector RecentIsos() const; + bool HasRecentIsos() const; + void ClearRecentIsos(); protected: void LoadStandardControllerIni();