rpcsx/rpcs3/Emu/IdManager.h

176 lines
3.4 KiB
C
Raw Normal View History

#pragma once
2015-03-06 23:58:42 +01:00
#define ID_MANAGER_INCLUDED
// ID type
enum : u32
{
ID_TYPE_NONE = 0,
};
// Helper template to detect type
template<typename T> struct ID_type
{
//static_assert(sizeof(T) == 0, "ID type not registered (use REG_ID_TYPE)");
static const u32 type = ID_TYPE_NONE; // default type
};
class ID_data_t final
{
public:
const std::shared_ptr<void> data;
const std::type_info& info;
const u32 type;
2015-05-28 21:13:35 +02:00
template<typename T> force_inline ID_data_t(std::shared_ptr<T> data, u32 type)
: data(std::move(data))
, info(typeid(T))
, type(type)
{
}
ID_data_t(const ID_data_t& right) = delete;
2015-03-06 23:10:04 +01:00
ID_data_t& operator =(const ID_data_t& right) = delete;
ID_data_t(ID_data_t&& right)
2015-05-28 21:13:35 +02:00
: data(std::move(const_cast<std::shared_ptr<void>&>(right.data)))
, info(right.info)
, type(right.type)
{
}
ID_data_t& operator =(ID_data_t&& other) = delete;
};
class ID_manager
{
2015-03-15 14:26:01 +01:00
std::mutex m_mutex;
std::unordered_map<u32, ID_data_t> m_id_map;
u32 m_cur_id = 1; // first ID
public:
// check if ID exists and has specified type
template<typename T> bool check_id(const u32 id)
{
2015-03-15 14:26:01 +01:00
std::lock_guard<std::mutex> lock(m_mutex);
2015-03-10 15:42:08 +01:00
auto f = m_id_map.find(id);
return f != m_id_map.end() && f->second.info == typeid(T);
}
// must be called from the constructor called through make() to get further ID of current object
u32 get_current_id()
{
// if called correctly from make(), the mutex is locked
// if called illegally, the mutex is unlocked with high probability (wrong ID is returned otherwise)
if (m_mutex.try_lock())
{
// schedule unlocking
std::lock_guard<std::mutex> lock(m_mutex, std::adopt_lock);
throw "Invalid get_cur_id() usage";
}
return m_cur_id;
}
void clear()
{
2015-03-15 14:26:01 +01:00
std::lock_guard<std::mutex> lock(m_mutex);
m_id_map.clear();
m_cur_id = 1; // first ID
}
// add new ID using existing std::shared_ptr (not recommended, use make() instead)
2015-05-28 21:13:35 +02:00
template<typename T> u32 add(std::shared_ptr<T> data, u32 type = ID_type<T>::type)
{
2015-03-15 14:26:01 +01:00
std::lock_guard<std::mutex> lock(m_mutex);
2015-05-28 21:13:35 +02:00
m_id_map.emplace(m_cur_id, ID_data_t(std::move(data), type));
return m_cur_id++;
}
// add new ID of specified type with specified constructor arguments (passed to std::make_shared<>)
template<typename T, typename... Args> u32 make(Args&&... args)
2015-03-12 20:02:02 +01:00
{
2015-03-15 14:26:01 +01:00
std::lock_guard<std::mutex> lock(m_mutex);
2015-03-12 20:02:02 +01:00
const u32 type = ID_type<T>::type;
2015-03-12 20:02:02 +01:00
m_id_map.emplace(m_cur_id, ID_data_t(std::make_shared<T>(args...), type));
return m_cur_id++;
}
template<typename T> std::shared_ptr<T> get(u32 id)
2015-03-15 10:20:29 +01:00
{
2015-03-15 14:26:01 +01:00
std::lock_guard<std::mutex> lock(m_mutex);
2015-03-15 10:20:29 +01:00
auto f = m_id_map.find(id);
2015-03-15 10:20:29 +01:00
if (f == m_id_map.end() || f->second.info != typeid(T))
2015-03-15 10:20:29 +01:00
{
return nullptr;
2015-03-15 10:20:29 +01:00
}
return std::static_pointer_cast<T>(f->second.data);
2015-03-15 10:20:29 +01:00
}
template<typename T> bool remove(u32 id)
{
2015-03-15 14:26:01 +01:00
std::lock_guard<std::mutex> lock(m_mutex);
auto item = m_id_map.find(id);
if (item == m_id_map.end() || item->second.info != typeid(T))
2015-03-12 20:02:02 +01:00
{
return false;
}
2015-03-12 20:02:02 +01:00
m_id_map.erase(item);
return true;
}
u32 get_count_by_type(u32 type)
2014-12-24 17:09:32 +01:00
{
2015-03-15 14:26:01 +01:00
std::lock_guard<std::mutex> lock(m_mutex);
2014-12-24 17:09:32 +01:00
u32 result = 0;
for (auto& v : m_id_map)
2014-12-24 17:09:32 +01:00
{
if (v.second.type == type)
{
result++;
}
2014-12-24 17:09:32 +01:00
}
return result;
2014-12-24 17:09:32 +01:00
}
std::set<u32> get_IDs_by_type(u32 type)
2014-12-24 17:09:32 +01:00
{
2015-03-15 14:26:01 +01:00
std::lock_guard<std::mutex> lock(m_mutex);
2014-12-24 17:09:32 +01:00
std::set<u32> result;
for (auto& v : m_id_map)
2014-12-24 17:09:32 +01:00
{
if (v.second.type == type)
{
result.insert(v.first);
}
2014-12-24 17:09:32 +01:00
}
return result;
2014-12-24 17:09:32 +01:00
}
};