diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java index a6f5261048..ed0f65741a 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java @@ -96,12 +96,7 @@ public class GameFileCache return pathSet; } - /** - * Scans through the file system and updates the cache to match. - * - * @return true if the cache was modified - */ - public boolean update() + public static String[] getAllGamePaths() { boolean recursiveScan = BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.getBooleanGlobal(); @@ -109,17 +104,33 @@ public class GameFileCache String[] folderPaths = folderPathsSet.toArray(new String[0]); - return update(folderPaths, recursiveScan); + return getAllGamePaths(folderPaths, recursiveScan); } + public static native String[] getAllGamePaths(String[] folderPaths, boolean recursiveScan); + public native int getSize(); public native GameFile[] getAllGames(); public native GameFile addOrGet(String gamePath); - public native boolean update(String[] folderPaths, boolean recursiveScan); + /** + * Sets the list of games to cache. + * + * Games which are in the passed-in list but not in the cache are scanned and added to the cache, + * and games which are in the cache but not in the passed-in list are removed from the cache. + * + * @return true if the cache was modified + */ + public native boolean update(String[] gamePaths); + /** + * For each game that already is in the cache, scans the folder that contains the game + * for additional metadata files (PNG/XML). + * + * @return true if the cache was modified + */ public native boolean updateAdditionalMetadata(); public native boolean load(); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java index 7cff59a3e9..3be5fb039f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java @@ -159,9 +159,20 @@ public final class GameFileCacheService extends IntentService public static GameFile addOrGet(String gamePath) { - // The existence of this one function, which is called from one - // single place, forces us to use synchronization in onHandleIntent... - // A bit annoying, but should be good enough for now + // Common case: The game is in the cache, so just grab it from there. + // (Actually, addOrGet already checks for this case, but we want to avoid calling it if possible + // because onHandleIntent may hold a lock on gameFileCache for extended periods of time.) + GameFile[] allGames = gameFiles.get(); + for (GameFile game : allGames) + { + if (game.getPath().equals(gamePath)) + { + return game; + } + } + + // Unusual case: The game wasn't found in the cache. + // Scan the game and add it to the cache so that we can return it. synchronized (gameFileCache) { return gameFileCache.addOrGet(gamePath); @@ -192,26 +203,29 @@ public final class GameFileCacheService extends IntentService { if (gameFileCache != null) { + String[] gamePaths = GameFileCache.getAllGamePaths(); + + boolean changed; synchronized (gameFileCache) { - boolean changed = gameFileCache.update(); - if (changed) - { - updateGameFileArray(); - sendBroadcast(CACHE_UPDATED); - } + changed = gameFileCache.update(gamePaths); + } + if (changed) + { + updateGameFileArray(); + sendBroadcast(CACHE_UPDATED); + } - boolean additionalMetadataChanged = gameFileCache.updateAdditionalMetadata(); - if (additionalMetadataChanged) - { - updateGameFileArray(); - sendBroadcast(CACHE_UPDATED); - } + boolean additionalMetadataChanged = gameFileCache.updateAdditionalMetadata(); + if (additionalMetadataChanged) + { + updateGameFileArray(); + sendBroadcast(CACHE_UPDATED); + } - if (changed || additionalMetadataChanged) - { - gameFileCache.save(); - } + if (changed || additionalMetadataChanged) + { + gameFileCache.save(); } } diff --git a/Source/Android/jni/GameList/GameFileCache.cpp b/Source/Android/jni/GameList/GameFileCache.cpp index 06329a70ac..b79d85db15 100644 --- a/Source/Android/jni/GameList/GameFileCache.cpp +++ b/Source/Android/jni/GameList/GameFileCache.cpp @@ -38,6 +38,13 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_model_GameFileCache_finali delete GetPointer(env, obj); } +JNIEXPORT jobjectArray JNICALL Java_org_dolphinemu_dolphinemu_model_GameFileCache_getAllGamePaths( + JNIEnv* env, jclass, jobjectArray folder_paths, jboolean recursive_scan) +{ + return VectorToJStringArray( + env, UICommon::FindAllGamePaths(JStringArrayToVector(env, folder_paths), recursive_scan)); +} + JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFileCache_getSize(JNIEnv* env, jobject obj) { @@ -66,10 +73,9 @@ JNIEXPORT jobject JNICALL Java_org_dolphinemu_dolphinemu_model_GameFileCache_add } JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_model_GameFileCache_update( - JNIEnv* env, jobject obj, jobjectArray folder_paths, jboolean recursive_scan) + JNIEnv* env, jobject obj, jobjectArray game_paths) { - return GetPointer(env, obj)->Update( - UICommon::FindAllGamePaths(JStringArrayToVector(env, folder_paths), recursive_scan)); + return GetPointer(env, obj)->Update(JStringArrayToVector(env, game_paths)); } JNIEXPORT jboolean JNICALL diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 3f0afcaf34..8ac7f4fe26 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -14,6 +14,8 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") add_definitions(-D_CRT_SECURE_NO_DEPRECATE) add_definitions(-D_CRT_NONSTDC_NO_WARNINGS) add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING) + # The replacement for the old atomic shared_ptr functions was added in C++20, so we can't use it yet + add_definitions(-D_SILENCE_CXX20_OLD_SHARED_PTR_ATOMIC_SUPPORT_DEPRECATION_WARNING) endif() if (MSVC) diff --git a/Source/Core/UICommon/GameFileCache.cpp b/Source/Core/UICommon/GameFileCache.cpp index a0bf0caf42..30bbca924b 100644 --- a/Source/Core/UICommon/GameFileCache.cpp +++ b/Source/Core/UICommon/GameFileCache.cpp @@ -4,6 +4,7 @@ #include "UICommon/GameFileCache.h" #include +#include #include #include #include @@ -202,7 +203,7 @@ bool GameFileCache::UpdateAdditionalMetadata(std::shared_ptr* game_fil if (custom_cover_changed) copy->CustomCoverCommit(); - *game_file = std::move(copy); + std::atomic_store(game_file, std::move(copy)); return true; } diff --git a/Source/VSProps/Base.props b/Source/VSProps/Base.props index 79489143a7..e656544188 100644 --- a/Source/VSProps/Base.props +++ b/Source/VSProps/Base.props @@ -64,6 +64,8 @@ _WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions) + + _SILENCE_CXX20_OLD_SHARED_PTR_ATOMIC_SUPPORT_DEPRECATION_WARNING;%(PreprocessorDefinitions) USE_UPNP;USE_USBDK;__LIBUSB__;%(PreprocessorDefinitions) SFML_STATIC;%(PreprocessorDefinitions) USE_ANALYTICS=1;%(PreprocessorDefinitions)