/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2020 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #ifndef XENIA_KERNEL_UTIL_OBJECT_TABLE_H_ #define XENIA_KERNEL_UTIL_OBJECT_TABLE_H_ #include #include #include #include "xenia/base/mutex.h" #include "xenia/base/string_key.h" #include "xenia/kernel/xobject.h" #include "xenia/xbox.h" namespace xe { class ByteStream; } // namespace xe namespace xe { namespace kernel { namespace util { class ObjectTable { public: ObjectTable(); ~ObjectTable(); void Reset(); X_STATUS AddHandle(XObject* object, X_HANDLE* out_handle); X_STATUS DuplicateHandle(X_HANDLE orig, X_HANDLE* out_handle); X_STATUS RetainHandle(X_HANDLE handle); X_STATUS ReleaseHandle(X_HANDLE handle); X_STATUS ReleaseHandleInLock(X_HANDLE handle); X_STATUS RemoveHandle(X_HANDLE handle); bool Save(ByteStream* stream); bool Restore(ByteStream* stream); // Restores a XObject reference with a handle. Mainly for internal use - do // not use. X_STATUS RestoreHandle(X_HANDLE handle, XObject* object); template object_ref LookupObject(X_HANDLE handle, bool already_locked = false) { auto object = LookupObject(handle, already_locked); if (object) { assert_true(object->type() == T::kObjectType); } auto result = object_ref(reinterpret_cast(object)); return result; } X_STATUS AddNameMapping(const std::string_view name, X_HANDLE handle); void RemoveNameMapping(const std::string_view name); X_STATUS GetObjectByName(const std::string_view name, X_HANDLE* out_handle); template std::vector> GetObjectsByType(XObject::Type type) { std::vector> results; GetObjectsByType( type, reinterpret_cast>*>(&results)); return results; } template std::vector> GetObjectsByType() { std::vector> results; GetObjectsByType( T::kObjectType, reinterpret_cast>*>(&results)); return results; } std::vector> GetAllObjects(); void PurgeAllObjects(); // Purges the object table of all guest objects private: struct ObjectTableEntry { int handle_ref_count = 0; XObject* object = nullptr; }; ObjectTableEntry* LookupTableInLock(X_HANDLE handle); ObjectTableEntry* LookupTable(X_HANDLE handle); XObject* LookupObject(X_HANDLE handle, bool already_locked); void GetObjectsByType(XObject::Type type, std::vector>* results); X_HANDLE TranslateHandle(X_HANDLE handle); static constexpr uint32_t GetHandleSlot(X_HANDLE handle, bool host) { handle &= host ? ~XObject::kHandleHostBase : ~XObject::kHandleBase; return handle >> 2; } X_STATUS FindFreeSlot(uint32_t* out_slot, bool host); bool Resize(uint32_t new_capacity, bool host); xe::global_critical_region global_critical_region_; uint32_t table_capacity_ = 0; uint32_t host_table_capacity_ = 0; ObjectTableEntry* table_ = nullptr; ObjectTableEntry* host_table_ = nullptr; uint32_t last_free_entry_ = 0; uint32_t last_free_host_entry_ = 0; std::unordered_map name_table_; }; // Generic lookup template <> object_ref ObjectTable::LookupObject(X_HANDLE handle, bool already_locked); } // namespace util } // namespace kernel } // namespace xe #endif // XENIA_KERNEL_UTIL_OBJECT_TABLE_H_