rpcs3/Utilities/IdManager.h

158 lines
2.3 KiB
C++

#pragma once
#include <unordered_map>
typedef u32 ID_TYPE;
class IDData
{
protected:
void* m_ptr;
std::function<void(void*)> m_destr;
public:
IDData(void* ptr, std::function<void(void*)> destr)
: m_ptr(ptr)
, m_destr(destr)
{
}
~IDData()
{
m_destr(m_ptr);
}
template<typename T> T* get()
{
return (T*)m_ptr;
}
template<typename T> const T* get() const
{
return (const T*)m_ptr;
}
};
struct ID
{
wxString m_name;
u8 m_attr;
IDData* m_data;
template<typename T>
ID(const wxString& name, T* data, const u8 attr)
: m_name(name)
, m_attr(attr)
{
m_data = new IDData(data, [](void *ptr) -> void { delete (T*)ptr; });
}
ID() : m_data(nullptr)
{
}
void Kill()
{
delete m_data;
}
};
class IdManager
{
ArrayF<ID> IDs;
static const ID_TYPE s_first_id = 1;
static const ID_TYPE s_max_id = -1;
std::unordered_map<ID_TYPE, ID> m_id_map;
std::mutex m_mtx_main;
ID_TYPE m_cur_id;
public:
IdManager() : m_cur_id(s_first_id)
{
}
~IdManager()
{
Clear();
}
bool CheckID(const ID_TYPE id)
{
std::lock_guard<std::mutex> lock(m_mtx_main);
return m_id_map.find(id) != m_id_map.end();
}
void Clear()
{
std::lock_guard<std::mutex> lock(m_mtx_main);
for(auto& i : m_id_map)
{
i.second.Kill();
}
m_id_map.clear();
m_cur_id = s_first_id;
}
template<typename T>
ID_TYPE GetNewID(const wxString& name = wxEmptyString, T* data = nullptr, const u8 attr = 0)
{
std::lock_guard<std::mutex> lock(m_mtx_main);
m_id_map[m_cur_id] = std::move(ID(name, data, attr));
return m_cur_id++;
}
ID& GetID(const ID_TYPE id)
{
std::lock_guard<std::mutex> lock(m_mtx_main);
return m_id_map[id];
}
template<typename T>
bool GetIDData(const ID_TYPE id, T*& result)
{
std::lock_guard<std::mutex> lock(m_mtx_main);
auto f = m_id_map.find(id);
if(f == m_id_map.end())
{
return false;
}
result = f->second.m_data->get<T>();
return true;
}
bool HasID(const s64 id)
{
std::lock_guard<std::mutex> lock(m_mtx_main);
if(id == wxID_ANY)
return m_id_map.begin() != m_id_map.end();
return CheckID(id);
}
bool RemoveID(const ID_TYPE id)
{
std::lock_guard<std::mutex> lock(m_mtx_main);
auto item = m_id_map.find(id);
if(item == m_id_map.end()) return false;
item->second.Kill();
m_id_map.erase(item);
return true;
}
};