diff --git a/rpcs3/Emu/Cell/lv2/sys_config.cpp b/rpcs3/Emu/Cell/lv2/sys_config.cpp index f3fa0bbe21..629beb6d23 100644 --- a/rpcs3/Emu/Cell/lv2/sys_config.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_config.cpp @@ -167,7 +167,7 @@ void lv2_config_service_listener::notify_all() { services.push_back(service.get_shared_ptr()); } - }, 0); + }); // Sort services by timestamp sort(services.begin(), services.end(), [](const std::shared_ptr& s1, const std::shared_ptr& s2) diff --git a/rpcs3/Emu/Cell/lv2/sys_fs.h b/rpcs3/Emu/Cell/lv2/sys_fs.h index de970c8339..0a2b5950ff 100644 --- a/rpcs3/Emu/Cell/lv2/sys_fs.h +++ b/rpcs3/Emu/Cell/lv2/sys_fs.h @@ -160,8 +160,6 @@ extern lv2_fs_mount_point g_mp_sys_dev_hdd1; struct lv2_fs_object { - using id_type = lv2_fs_object; - static const u32 id_base = 3; static const u32 id_step = 1; static const u32 id_count = 255 - id_base; diff --git a/rpcs3/Emu/Cell/lv2/sys_sync.h b/rpcs3/Emu/Cell/lv2/sys_sync.h index a96fd236ce..a26f4ad71c 100644 --- a/rpcs3/Emu/Cell/lv2/sys_sync.h +++ b/rpcs3/Emu/Cell/lv2/sys_sync.h @@ -65,8 +65,6 @@ enum ppu_thread_status : u32; // Base class for some kernel objects (shared set of 8192 objects). struct lv2_obj { - using id_type = lv2_obj; - static const u32 id_step = 0x100; static const u32 id_count = 8192; static constexpr std::pair id_invl_range = {0, 8}; diff --git a/rpcs3/Emu/IdManager.h b/rpcs3/Emu/IdManager.h index 1a49015ad2..4216fc9622 100644 --- a/rpcs3/Emu/IdManager.h +++ b/rpcs3/Emu/IdManager.h @@ -20,40 +20,36 @@ namespace id_manager // Common global mutex extern shared_mutex g_mutex; + template + constexpr std::pair get_invl_range() + { + return {0, 0}; + } + + template requires requires () { T::id_invl_range; } + constexpr std::pair get_invl_range() + { + return T::id_invl_range; + } + + template + concept IdmCompatible = requires () { T::id_base, T::id_step, T::id_count; }; + // ID traits - template + template struct id_traits { - static_assert(sizeof(T) == 0, "ID object must specify: id_base, id_step, id_count"); + static_assert(IdmCompatible, "ID object must specify: id_base, id_step, id_count"); - static constexpr u32 base = 1; // First ID (N = 0) - static constexpr u32 step = 1; // Any ID: N * id_step + id_base - static constexpr u32 count = 65535; // Limit: N < id_count - static constexpr u32 invalid = 0; - static constexpr std::pair invl_range{0, 0}; - }; + enum : u32 + { + base = T::id_base, // First ID (N = 0) + step = T::id_step, // Any ID: N * id_setp + id_base + count = T::id_count, // Limit: N < id_count + invalid = -+!base, // Invalid ID sample + }; - template - struct invl_range_extract_impl - { - static constexpr std::pair invl_range{0, 0}; - }; - - template - struct invl_range_extract_impl> - { - static constexpr std::pair invl_range = T::id_invl_range; - }; - - template - struct id_traits> - { - static constexpr u32 base = T::id_base; - static constexpr u32 step = T::id_step; - static constexpr u32 count = T::id_count; - static constexpr u32 invalid = -+!base; - - static constexpr std::pair invl_range = invl_range_extract_impl::invl_range; + static constexpr std::pair invl_range = get_invl_range(); static_assert(count && step && u64{step} * (count - 1) + base < u32{umax} + u64{base != 0 ? 1 : 0}, "ID traits: invalid object range"); @@ -61,19 +57,6 @@ namespace id_manager static_assert(!invl_range.second || (u64{invl_range.second} + invl_range.first <= 32 /*....*/ )); }; - // Correct usage testing - template - struct id_verify : std::integral_constant::value> - { - // If common case, T2 shall be derived from or equal to T - }; - - template - struct id_verify> : std::integral_constant::value> - { - // If T2 contains id_type type, T must be equal to it - }; - class typeinfo { // Global variable for each registered type @@ -227,20 +210,6 @@ class idm using result_type = R; }; - template - struct function_traits - { - using object_type = A2; - using void_type = void; - }; - - template - struct function_traits - { - using object_type = A2; - using void_type = void; - }; - // Helper type: pointer + return value propagated template struct return_pair @@ -296,7 +265,7 @@ class idm template static map_data* find_id(u32 id) { - static_assert(id_manager::id_verify::value, "Invalid ID type combination"); + static_assert(PtrSame, "Invalid ID type combination"); const u32 index = get_index(id); @@ -332,7 +301,7 @@ class idm template static map_data* create_id(F&& provider) { - static_assert(id_manager::id_verify::value, "Invalid ID type combination"); + static_assert(PtrSame, "Invalid ID type combination"); // ID traits using traits = id_manager::id_traits; @@ -373,8 +342,8 @@ public: } // Add a new ID of specified type with specified constructor arguments (returns object or nullptr) - template - static inline std::enable_if_t::value, std::shared_ptr> make_ptr(Args&&... args) + template requires (std::is_constructible_v) + static inline std::shared_ptr make_ptr(Args&&... args) { if (auto pair = create_id([&] { return std::make_shared(std::forward(args)...); })) { @@ -385,8 +354,8 @@ public: } // Add a new ID of specified type with specified constructor arguments (returns id) - template - static inline std::enable_if_t::value, u32> make(Args&&... args) + template requires (std::is_constructible_v) + static inline u32 make(Args&&... args) { if (auto pair = create_id([&] { return std::make_shared(std::forward(args)...); })) { @@ -396,20 +365,8 @@ public: return id_manager::id_traits::invalid; } - // Add a new ID for an existing object provided (returns new id) - template - static inline u32 import_existing(const std::shared_ptr& ptr) - { - if (auto pair = create_id([&] { return ptr; })) - { - return pair->first; - } - - return id_manager::id_traits::invalid; - } - // Add a new ID for an object returned by provider() - template > + template requires (std::is_invocable_v) static inline u32 import(F&& provider) { if (auto pair = create_id(std::forward(provider))) @@ -420,6 +377,13 @@ public: return id_manager::id_traits::invalid; } + // Add a new ID for an existing object provided (returns new id) + template + static inline u32 import_existing(std::shared_ptr ptr) + { + return import([&] { return std::move(ptr); }); + } + // Access the ID record without locking (unsafe) template static inline map_data* find_unlocked(u32 id) @@ -497,14 +461,7 @@ public: { reader_lock lock(id_manager::g_mutex); - const auto found = find_id(id); - - if (found == nullptr) [[unlikely]] - { - return nullptr; - } - - return std::static_pointer_cast(found->second); + return get_unlocked(id); } // Get the object, access object under reader lock @@ -533,57 +490,46 @@ public: } } + static constexpr std::false_type unlocked{}; + // Access all objects of specified type. Returns the number of objects processed. - template ::operator()), typename FRT = typename function_traits::void_type> - static inline u32 select(F&& func, int = 0) + // If function result evaluates to true, stop and return the object and the value. + template + static inline auto select(F&& func, Lock = {}) { - static_assert(id_manager::id_verify::value, "Invalid ID type combination"); + static_assert((PtrSame && ...), "Invalid ID type combination"); - reader_lock lock(id_manager::g_mutex); + std::conditional_t(Lock()), reader_lock, const shared_mutex&> lock(id_manager::g_mutex); - u32 result = 0; + using func_traits = function_traits()))::operator())>; + using object_type = typename func_traits::object_type; + using result_type = typename func_traits::result_type; - for (auto& id : g_fxo->get>().vec) - { - if (id.second) - { - if (std::is_same::value || id.first.type() == get_type()) - { - func(id.first, *static_cast::object_type*>(id.second.get())); - result++; - } - } - } + static_assert(PtrSame, "Invalid function argument type combination"); - return result; - } - - // Access all objects of specified type. If function result evaluates to true, stop and return the object and the value. - template ::operator()), typename FRT = typename function_traits::result_type> - static inline auto select(F&& func) - { - static_assert(id_manager::id_verify::value, "Invalid ID type combination"); - - using object_type = typename function_traits::object_type; - using result_type = return_pair; - - reader_lock lock(id_manager::g_mutex); + std::conditional_t, u32, return_pair> result{}; for (auto& id : g_fxo->get>().vec) { if (auto ptr = static_cast(id.second.get())) { - if (std::is_same::value || id.first.type() == get_type()) + if (sizeof...(Get) == 0 || ((id.first.type() == get_type()) || ...)) { - if (FRT result = func(id.first, *ptr)) + if constexpr (std::is_void_v) { - return result_type{{id.second, ptr}, std::move(result)}; + func(id.first, *ptr); + result++; + } + else if ((result.ret = func(id.first, *ptr))) + { + result.ptr = {id.second, ptr}; + break; } } } } - return result_type{nullptr}; + return result; } // Remove the ID diff --git a/rpcs3/rpcs3qt/kernel_explorer.cpp b/rpcs3/rpcs3qt/kernel_explorer.cpp index e30f55cb78..21ad392125 100644 --- a/rpcs3/rpcs3qt/kernel_explorer.cpp +++ b/rpcs3/rpcs3qt/kernel_explorer.cpp @@ -578,7 +578,7 @@ void kernel_explorer::update() add_leaf(find_node(root, additional_nodes::memory_containers), qstr(fmt::format("Memory Container 0x%08x: Used: 0x%x/0x%x (%0.2f/%0.2f MB)", id, used, container.size, used * 1. / (1024 * 1024), container.size * 1. / (1024 * 1024)))); }); - std::unique_lock lock_lv2(lv2_obj::g_mutex); + std::optional> lock_idm_lv2(std::in_place, id_manager::g_mutex, lv2_obj::g_mutex); idm::select>([&](u32 id, ppu_thread& ppu) { @@ -587,9 +587,9 @@ void kernel_explorer::update() add_leaf(find_node(root, additional_nodes::ppu_threads), qstr(fmt::format(u8"PPU 0x%07x: ā€œ%sā€, PRIO: %d, Joiner: %s, Status: %s, State: %s, %s func: ā€œ%sā€", id, *ppu.ppu_tname.load(), +ppu.prio, ppu.joiner.load(), status, ppu.state.load() , ppu.current_function ? "In" : "Last", func ? func : ""))); - }); + }, idm::unlocked); - lock_lv2.unlock(); + lock_idm_lv2.reset(); idm::select>([&](u32 /*id*/, spu_thread& spu) { diff --git a/rpcs3/util/types.hpp b/rpcs3/util/types.hpp index 017b611986..dd2e270c7f 100644 --- a/rpcs3/util/types.hpp +++ b/rpcs3/util/types.hpp @@ -1039,7 +1039,7 @@ concept PtrCastable = requires(const volatile X* x, const volatile Y* y) }; template requires PtrCastable -constexpr bool is_same_ptr() +consteval bool is_same_ptr() { if constexpr (std::is_void_v || std::is_void_v || std::is_same_v, std::remove_cv_t>) { @@ -1051,33 +1051,24 @@ constexpr bool is_same_ptr() } else { - if (std::is_constant_evaluated()) + bool result = false; + + if constexpr (sizeof(X) < sizeof(Y)) { - bool result = false; - - if constexpr (sizeof(X) < sizeof(Y)) - { - std::allocator a{}; - Y* ptr = a.allocate(1); - result = static_cast(ptr) == static_cast(ptr); - a.deallocate(ptr, 1); - } - else - { - std::allocator a{}; - X* ptr = a.allocate(1); - result = static_cast(ptr) == static_cast(ptr); - a.deallocate(ptr, 1); - } - - return result; + std::allocator a{}; + Y* ptr = a.allocate(1); + result = static_cast(ptr) == static_cast(ptr); + a.deallocate(ptr, 1); } else { - std::aligned_union_t<0, X, Y> s; - Y* ptr = reinterpret_cast(&s); - return static_cast(ptr) == static_cast(ptr); + std::allocator a{}; + X* ptr = a.allocate(1); + result = static_cast(ptr) == static_cast(ptr); + a.deallocate(ptr, 1); } + + return result; } }