From 4203f53b6727b69b676c7845d2269f2a03bc8da9 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 28 Jan 2017 17:59:43 +0300 Subject: [PATCH] IdManager bugfixed --- rpcs3/Emu/IdManager.cpp | 16 +++++++++++----- rpcs3/Emu/IdManager.h | 32 +++++++++++++++++--------------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/rpcs3/Emu/IdManager.cpp b/rpcs3/Emu/IdManager.cpp index 06a1e8e015..c2bf6c1d06 100644 --- a/rpcs3/Emu/IdManager.cpp +++ b/rpcs3/Emu/IdManager.cpp @@ -37,7 +37,7 @@ id_manager::id_map::pointer idm::allocate_id(std::pair types, u32 base return nullptr; } - const u32 _next = map.rbegin()->first.id() + step; + const u32 _next = next + step * count; if (_next > base && _next < base + step * count) { @@ -46,9 +46,15 @@ id_manager::id_map::pointer idm::allocate_id(std::pair types, u32 base } // Check all IDs starting from "next id" (TODO) - for (next; next < base + step * count; next += step) + for (u32 i = 0; i < count; i++, next += step) { - // Get ID + // Get correct ID value + if (next >= base + step * count) + { + next = base; + } + + // Try to allocate ID storage const auto result = map.emplace(id_manager::id_key(next, types.second), nullptr); if (result.second) @@ -64,9 +70,9 @@ id_manager::id_map::pointer idm::allocate_id(std::pair types, u32 base return nullptr; } -id_manager::id_map::pointer idm::find_id(u32 type, u32 true_type, u32 id) +id_manager::id_map::const_pointer idm::find_id(u32 type, u32 true_type, u32 id) { - auto& map = g_map[type]; + const auto& map = g_map[type]; const auto found = map.find(id); diff --git a/rpcs3/Emu/IdManager.h b/rpcs3/Emu/IdManager.h index e0e109502c..17460ea301 100644 --- a/rpcs3/Emu/IdManager.h +++ b/rpcs3/Emu/IdManager.h @@ -5,7 +5,7 @@ #include #include -#include +#include // idm/fxm: helper namespace namespace id_manager @@ -149,7 +149,15 @@ namespace id_manager } }; - using id_map = std::map>; + struct id_hash + { + std::size_t operator()(const id_key& id) const + { + return id ^ (id >> 8); + } + }; + + using id_map = std::unordered_map, id_hash>; } // Object manager for emulated process. Multiple objects of specified arbitrary type are given unique IDs. @@ -236,7 +244,7 @@ class idm static std::shared_ptr delete_id(u32 type, u32 true_type, u32 id); // Get ID (additionally check true_type if not equal) - static id_manager::id_map::pointer find_id(u32 type, u32 true_type, u32 id); + static id_manager::id_map::const_pointer find_id(u32 type, u32 true_type, u32 id); // Allocate new ID and assign the object from the provider() template @@ -509,28 +517,26 @@ public: template static inline explicit_bool_t remove(u32 id) { - auto ptr = delete_id(get_type(), get_type(), id); - - if (LIKELY(ptr)) + if (auto ptr = (writer_lock{id_manager::g_mutex}, delete_id(get_type(), get_type(), id))) { id_manager::on_stop::func(static_cast(ptr.get())); + return true; } - return ptr.operator bool(); + return false; } // Remove the ID and return the object template static inline std::shared_ptr withdraw(u32 id) { - auto ptr = delete_id(get_type(), get_type(), id); - - if (LIKELY(ptr)) + if (auto ptr = (writer_lock{id_manager::g_mutex}, delete_id(get_type(), get_type(), id))) { id_manager::on_stop::func(static_cast(ptr.get())); + return {ptr, static_cast(ptr.get())}; } - return {ptr, static_cast(ptr.get())}; + return nullptr; } // Remove the ID after accessing the object under writer lock, return the object and propagate return value @@ -553,8 +559,6 @@ public: func(*static_cast(found->second.get())); ptr = delete_id(get_type(), get_type(), id); - - g_map[get_type()].erase(id); } id_manager::on_stop::func(static_cast(ptr.get())); @@ -590,8 +594,6 @@ public: } ptr = delete_id(get_type(), get_type(), id); - - g_map[get_type()].erase(id); } id_manager::on_stop::func(static_cast(ptr.get()));