diff options
| author | shuffle2 <godisgovernment@gmail.com> | 2017-06-26 12:40:40 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-06-26 12:40:40 -0700 |
| commit | 7d60f03acb6efe99e5daecdf3cb410d3d6a8961e (patch) | |
| tree | 70b18bcdd3d67b14ca67d9ed7414c02b89b035c3 /Source/Core/DolphinWX/GameListCtrl.cpp | |
| parent | 0ace7fd8f3d4cc7c0ab95df1852255f2a6252aa1 (diff) | |
| parent | f51df62344dc2686a31381951804228839333ef6 (diff) | |
Merge pull request #5687 from shuffle2/wx-cache
DolphinWX: properly sync EmuState and banner changes.
Diffstat (limited to 'Source/Core/DolphinWX/GameListCtrl.cpp')
| -rw-r--r-- | Source/Core/DolphinWX/GameListCtrl.cpp | 123 |
1 files changed, 79 insertions, 44 deletions
diff --git a/Source/Core/DolphinWX/GameListCtrl.cpp b/Source/Core/DolphinWX/GameListCtrl.cpp index 4e89a7051c..5b68857c01 100644 --- a/Source/Core/DolphinWX/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/GameListCtrl.cpp @@ -269,27 +269,11 @@ GameListCtrl::GameListCtrl(bool disable_scanning, wxWindow* parent, const wxWind Common::SetCurrentThreadName("gamelist scanner"); if (SyncCacheFile(false)) - { - // Account for changes outside the cache (just wii banners atm; could scan Ini here) - // Note this is on the initial load path. Further improvements could be made if updates - // from scan->ui threads described small changelists instead of updating the entire list - // at once. - bool cache_modified = false; - for (auto& file : m_cached_files) - { - if (file->ReloadBannerIfNeeded()) - cache_modified = true; - } - QueueEvent(new wxCommandEvent(DOLPHIN_EVT_REFRESH_GAMELIST)); - if (cache_modified) - SyncCacheFile(true); - } - else - { - RescanList(); - } + // Always do an initial scan to catch new files and perform the more expensive per-file + // checks. TODO Make this safely cancellable if it becomes too slow? + RescanList(); m_scan_trigger.Wait(); while (!m_scan_exiting.IsSet()) @@ -421,20 +405,23 @@ void GameListCtrl::RefreshList() return; m_shown_files.clear(); - for (auto& item : m_cached_files) { - if (ShouldDisplayGameListItem(*item)) - m_shown_files.push_back(item); + std::unique_lock<std::mutex> lk(m_cache_mutex); + for (auto& item : m_cached_files) + { + if (ShouldDisplayGameListItem(*item)) + m_shown_files.push_back(item); + } } // Drives are not cached. Not sure if this is required, but better to err on the // side of caution if cross-platform issues could come into play. if (SConfig::GetInstance().m_ListDrives) { - const Core::TitleDatabase title_database; + std::unique_lock<std::mutex> lk(m_title_database_mutex); for (const auto& drive : cdio_get_devices()) { - auto file = std::make_shared<GameListItem>(drive, title_database); + auto file = std::make_shared<GameListItem>(drive, m_title_database); if (file->IsValid()) m_shown_files.push_back(file); } @@ -768,33 +755,75 @@ void GameListCtrl::RescanList() std::set_difference(search_results.cbegin(), search_results.cend(), cached_paths.cbegin(), cached_paths.cend(), std::back_inserter(new_paths)); - const Core::TitleDatabase title_database; + // Reload the TitleDatabase + { + std::unique_lock<std::mutex> lk(m_title_database_mutex); + m_title_database = {}; + } + // For now, only scan new_paths. This could cause false negatives (file actively being written), // but otherwise should be fine. - for (const auto& path : removed_paths) + bool cache_changed = false; { - auto it = std::find_if( - m_cached_files.cbegin(), m_cached_files.cend(), - [&path](const std::shared_ptr<GameListItem>& file) { return file->GetFileName() == path; }); - if (it != m_cached_files.cend()) - m_cached_files.erase(it); + std::unique_lock<std::mutex> lk(m_cache_mutex); + for (const auto& path : removed_paths) + { + auto it = std::find_if(m_cached_files.cbegin(), m_cached_files.cend(), + [&path](const std::shared_ptr<GameListItem>& file) { + return file->GetFileName() == path; + }); + if (it != m_cached_files.cend()) + { + cache_changed = true; + m_cached_files.erase(it); + } + } + for (const auto& path : new_paths) + { + auto file = std::make_shared<GameListItem>(path, m_title_database); + if (file->IsValid()) + { + cache_changed = true; + m_cached_files.push_back(std::move(file)); + } + } } - for (const auto& path : new_paths) + // The common case is that just a file has been added/removed, so trigger a refresh ASAP with the + // assumption that other properties of files will not change at the same time (which will be fine + // and just causes a double refresh). + if (cache_changed) + QueueEvent(new wxCommandEvent(DOLPHIN_EVT_REFRESH_GAMELIST)); + + // If any cached files need updates, apply the updates to a copy and delete the original - this + // makes the UI thread's use of cached files safe. Note however, it is assumed that RefreshList + // will not iterate m_cached_files while the scan thread is modifying the list itself. + bool refresh_needed = false; { - auto file = std::make_shared<GameListItem>(path, title_database); - if (file->IsValid()) - m_cached_files.push_back(std::move(file)); + std::unique_lock<std::mutex> lk(m_cache_mutex); + for (auto& file : m_cached_files) + { + bool emu_state_changed = file->EmuStateChanged(); + bool banner_changed = file->BannerChanged(); + if (emu_state_changed || banner_changed) + { + cache_changed = refresh_needed = true; + auto copy = std::make_shared<GameListItem>(*file); + if (emu_state_changed) + copy->EmuStateCommit(); + if (banner_changed) + copy->BannerCommit(); + file = std::move(copy); + } + } } + // Only post UI event to update the displayed list if something actually changed + if (refresh_needed) + QueueEvent(new wxCommandEvent(DOLPHIN_EVT_REFRESH_GAMELIST)); - for (auto& file : m_cached_files) - file->ReloadINI(); - - // Post UI event to update the displayed list - QueueEvent(new wxCommandEvent(DOLPHIN_EVT_REFRESH_GAMELIST)); + post_status(""); - post_status(_("Scan complete!")); - - SyncCacheFile(true); + if (cache_changed) + SyncCacheFile(true); } void GameListCtrl::OnRefreshGameList(wxCommandEvent& WXUNUSED(event)) @@ -802,8 +831,14 @@ void GameListCtrl::OnRefreshGameList(wxCommandEvent& WXUNUSED(event)) RefreshList(); } -void GameListCtrl::OnRescanGameList(wxCommandEvent& WXUNUSED(event)) +void GameListCtrl::OnRescanGameList(wxCommandEvent& event) { + if (event.GetInt()) + { + // Knock out the cache on a purge event + std::unique_lock<std::mutex> lk(m_cache_mutex); + m_cached_files.clear(); + } m_scan_trigger.Set(); } |
