diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 59f1cc9da5..05e7577e5f 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -4033,3 +4033,81 @@ bool thread_ctrl::is_main() { return get_tid() == utils::main_tid; } + +usz map_workload(std::string_view thread_name, usz thread_count, usz count, std::function&& func) +{ + ensure(!!func); + + if (thread_count <= 1) + { + for (usz i = 0; i < count; i++) + { + func(i); + } + return 1; + } + + atomic_t num_threads_succeeded {0}; // Check if any thread didn't finish. For example when hitting an exception. + + atomic_t indexer = 0; + const auto iterate = [count, &func, &indexer]() + { + while (thread_ctrl::state() != thread_state::aborting) + { + // Make sure indexer does not exceed count + const usz index = indexer.fetch_op([count](usz& v) + { + if (v < count) + { + v++; + return true; + } + + return false; + }).first; + + if (index >= count) + { + break; + } + + func(index); + } + }; + named_thread_group workers(thread_name, ::narrow(thread_count) - 1, [&iterate, &num_threads_succeeded]() + { + iterate(); + num_threads_succeeded++; + }); + + iterate(); + + workers.join(); + + return num_threads_succeeded + 1; +} + +usz map_workload(std::string_view thread_name, usz thread_count, std::function&& func) +{ + ensure(!!func); + + if (thread_count <= 1) + { + func(); + return 1; + } + + atomic_t num_threads_succeeded {0}; // Check if any thread didn't finish. For example when hitting an exception. + + named_thread_group workers(thread_name, ::narrow(thread_count) - 1, [&func, &num_threads_succeeded]() + { + func(); + num_threads_succeeded++; + }); + + func(); + + workers.join(); + + return num_threads_succeeded + 1; +} diff --git a/Utilities/Thread.h b/Utilities/Thread.h index 5d6d07c870..cc6c826581 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -905,3 +905,6 @@ public: ::operator delete(static_cast(m_threads), std::align_val_t{alignof(Thread)}); } }; + +usz map_workload(std::string_view thread_name, usz thread_count, usz count, std::function&& func); +usz map_workload(std::string_view thread_name, usz thread_count, std::function&& func); diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index d696a28c62..c9a49348a5 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -1364,26 +1364,10 @@ package_install_result package_reader::extract_data(std::deque& { // Disc archives don't like multithreaded file reads, so let's just use a single thread here const usz thread_count = from_optical_drive ? 1 : std::min(utils::get_thread_count(), reader.m_install_entries.size()); - atomic_t num_threads_succeeded {0}; // Check if any thread didn't finish. For example when hitting an exception. - - if (thread_count > 1) - { - named_thread_group workers("PKG Installer "sv, ::narrow(thread_count) - 1, [&]() - { - reader.extract_worker(); - num_threads_succeeded++; - }); - - reader.extract_worker(); - num_threads_succeeded++; - - workers.join(); - } - else + const usz num_threads_succeeded = map_workload("PKG Installer "sv, thread_count, [&reader]() { reader.extract_worker(); - num_threads_succeeded++; - } + }); if (thread_count != num_threads_succeeded) { diff --git a/rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture_game_grid.cpp b/rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture_game_grid.cpp index f40074b7ad..e285b9bb0c 100644 --- a/rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture_game_grid.cpp +++ b/rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture_game_grid.cpp @@ -120,50 +120,11 @@ namespace rsx // Parse entries (multithreaded) const std::vector::path_entry>& entries = m_game_enumeration.path_entries(); - const usz thread_count = std::min(utils::get_thread_count(), entries.size()); - if (thread_count > 1) + usz thread_count = std::min(utils::get_thread_count(), entries.size()); + map_workload("BPM Parser "sv, thread_count, entries.size(), [this, &entries](usz index) { - atomic_t entry_indexer = 0; - const auto parse_entries = [this, &entry_indexer, &entries]() - { - while (thread_ctrl::state() != thread_state::aborting) - { - // Make sure entry_indexer does not exceed m_install_entries - const usz index = entry_indexer.fetch_op([&entries](usz& v) - { - if (v < entries.size()) - { - v++; - return true; - } - - return false; - }).first; - - if (index >= entries.size()) - { - break; - } - - m_game_enumeration.parse_entry(entries[index]); - } - }; - named_thread_group workers("BPM Parser "sv, ::narrow(thread_count) - 1, [&parse_entries]() - { - parse_entries(); - }); - - parse_entries(); - - workers.join(); - } - else - { - for (const game_enumeration::path_entry& entry : entries) - { - m_game_enumeration.parse_entry(entry); - } - } + m_game_enumeration.parse_entry(entries[index]); + }); // Try to update the app version for disc games if there is a patch // Also try to find updated game icons and movies @@ -186,11 +147,19 @@ namespace rsx return a.name < b.name; }); - finish_reload(); + // Create tiles (multithreaded) + std::vector> tiles(m_games.size()); + thread_count = std::min(utils::get_thread_count(), tiles.size()); + map_workload("BPM Tiles "sv, thread_count, tiles.size(), [this, &tiles](usz index) + { + tiles[index] = std::make_unique(m_games[index], m_tile_size); + }); + + finish_reload(std::move(tiles)); }); } - void big_picture_game_grid::finish_reload() + void big_picture_game_grid::finish_reload(std::vector>&& tiles) { std::lock_guard lock(m_reload_mutex); @@ -206,7 +175,7 @@ namespace rsx std::unique_ptr row; - for (usz i = 0; i < m_games.size(); i++) + for (usz i = 0; i < tiles.size(); i++) { if (i % m_columns == 0) { @@ -219,8 +188,7 @@ namespace rsx row->pack_padding = 20; } - auto tile = std::make_unique(m_games[i], m_tile_size); - m_tiles.push_back(row->add_element(tile)); + m_tiles.push_back(row->add_element(tiles[i])); } if (row) diff --git a/rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture_game_grid.h b/rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture_game_grid.h index 5a744debb6..4c1907af50 100644 --- a/rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture_game_grid.h +++ b/rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture_game_grid.h @@ -47,7 +47,7 @@ namespace rsx private: void start_reload(); - void finish_reload(); + void finish_reload(std::vector>&& tiles); void select_tile(s32 index); static constexpr u16 m_columns = 5; diff --git a/rpcs3/rpcs3qt/memory_string_searcher.cpp b/rpcs3/rpcs3qt/memory_string_searcher.cpp index de8ee1814f..c7f693b9c4 100644 --- a/rpcs3/rpcs3qt/memory_string_searcher.cpp +++ b/rpcs3/rpcs3qt/memory_string_searcher.cpp @@ -185,7 +185,7 @@ u64 memory_viewer_panel::OnSearch(std::string wstr, u32 mode) vm::writer_lock rlock; - const named_thread_group workers("Memory Searcher "sv, max_threads, [&]() + map_workload("Memory Searcher "sv, max_threads, [&]() { if (mode == as_inst || mode == as_fake_spu_inst || mode == as_regex_inst || mode == as_regex_fake_spu_inst) { @@ -448,7 +448,5 @@ u64 memory_viewer_panel::OnSearch(std::string wstr, u32 mode) found += local_found; }); - workers.join(); - return found; }