2012-11-15 00:39:56 +01:00
|
|
|
#pragma once
|
2015-03-06 23:58:42 +01:00
|
|
|
|
|
|
|
|
#define ID_MANAGER_INCLUDED
|
2012-11-15 00:39:56 +01:00
|
|
|
|
2015-08-12 03:52:26 +02:00
|
|
|
// default traits for any arbitrary type
|
2015-08-11 18:14:53 +02:00
|
|
|
template<typename T> struct id_traits
|
|
|
|
|
{
|
|
|
|
|
// get next mapped id (may return 0 if out of IDs)
|
|
|
|
|
static u32 next_id(u32 raw_id) { return raw_id < 0x80000000 ? (raw_id + 1) & 0x7fffffff : 0; }
|
|
|
|
|
|
|
|
|
|
// convert "public" id to mapped id (may return 0 if invalid)
|
|
|
|
|
static u32 in_id(u32 id) { return id; }
|
|
|
|
|
|
|
|
|
|
// convert mapped id to "public" id
|
|
|
|
|
static u32 out_id(u32 raw_id) { return raw_id; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class id_data_t final
|
2015-05-27 05:11:59 +02:00
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
const std::shared_ptr<void> data;
|
2015-07-09 21:55:50 +02:00
|
|
|
const std::type_info& info;
|
|
|
|
|
const std::size_t hash;
|
2015-05-27 05:11:59 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
template<typename T> force_inline id_data_t(std::shared_ptr<T> data)
|
2015-05-28 21:13:35 +02:00
|
|
|
: data(std::move(data))
|
2015-07-09 21:55:50 +02:00
|
|
|
, info(typeid(T))
|
|
|
|
|
, hash(typeid(T).hash_code())
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
|
|
|
|
}
|
2015-03-06 23:10:04 +01:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
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)))
|
2015-05-27 05:11:59 +02:00
|
|
|
, info(right.info)
|
2015-07-09 21:55:50 +02:00
|
|
|
, hash(right.hash)
|
2014-10-01 11:45:43 +02:00
|
|
|
{
|
|
|
|
|
}
|
2012-11-15 00:39:56 +01:00
|
|
|
};
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
// ID Manager
|
|
|
|
|
// 0 is invalid ID
|
|
|
|
|
// 1..0x7fffffff : general purpose IDs
|
2015-08-11 18:14:53 +02:00
|
|
|
// 0x80000000+ : reserved (may be used through id_traits specializations)
|
2015-08-05 17:30:32 +02:00
|
|
|
namespace idm
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
2015-08-11 18:14:53 +02:00
|
|
|
// can be called from the constructor called through make() or make_ptr() to get the ID of currently created object
|
|
|
|
|
inline u32 get_last_id()
|
|
|
|
|
{
|
|
|
|
|
thread_local extern u32 g_tls_last_id;
|
|
|
|
|
|
|
|
|
|
return g_tls_last_id;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
// reinitialize ID manager
|
|
|
|
|
void clear();
|
|
|
|
|
|
2015-08-08 03:16:08 +02:00
|
|
|
// check if ID of specified type exists
|
2015-08-05 17:30:32 +02:00
|
|
|
template<typename T> bool check(u32 id)
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
2015-08-05 17:30:32 +02:00
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
2015-08-05 17:30:32 +02:00
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
2014-01-19 04:14:11 +01:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
const auto found = g_id_map.find(id_traits<T>::in_id(id));
|
2015-03-10 15:42:08 +01:00
|
|
|
|
2015-08-08 03:16:08 +02:00
|
|
|
return found != g_id_map.end() && found->second.info == typeid(T);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check if ID exists and return its type or nullptr
|
2015-08-11 18:14:53 +02:00
|
|
|
inline const std::type_info* get_type(u32 raw_id)
|
2015-08-08 03:16:08 +02:00
|
|
|
{
|
|
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
2015-08-08 03:16:08 +02:00
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
|
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
const auto found = g_id_map.find(raw_id);
|
2015-08-08 03:16:08 +02:00
|
|
|
|
|
|
|
|
return found == g_id_map.end() ? nullptr : &found->second.info;
|
2015-07-08 17:01:59 +02:00
|
|
|
}
|
|
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
// add new ID of specified type with specified constructor arguments (returns object or nullptr)
|
2015-08-05 17:30:32 +02:00
|
|
|
template<typename T, typename... Args> std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make_ptr(Args&&... args)
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
2015-08-05 17:30:32 +02:00
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
|
|
|
|
extern u32 g_last_raw_id;
|
|
|
|
|
thread_local extern u32 g_tls_last_id;
|
2015-07-01 00:25:52 +02:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
2015-07-01 00:25:52 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
u32 raw_id = g_last_raw_id;
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
while ((raw_id = id_traits<T>::next_id(raw_id)))
|
2015-08-04 12:46:05 +02:00
|
|
|
{
|
2015-08-11 18:14:53 +02:00
|
|
|
if (g_id_map.find(raw_id) != g_id_map.end()) continue;
|
|
|
|
|
|
|
|
|
|
g_tls_last_id = id_traits<T>::out_id(raw_id);
|
|
|
|
|
|
2015-08-04 12:46:05 +02:00
|
|
|
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
|
2015-07-01 00:25:52 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
g_id_map.emplace(raw_id, id_data_t(ptr));
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
if (raw_id < 0x80000000) g_last_raw_id = raw_id;
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
return ptr;
|
2015-08-04 12:46:05 +02:00
|
|
|
}
|
2015-07-01 00:25:52 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
return nullptr;
|
2015-07-01 00:25:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// add new ID of specified type with specified constructor arguments (returns id)
|
|
|
|
|
template<typename T, typename... Args> std::enable_if_t<std::is_constructible<T, Args...>::value, u32> make(Args&&... args)
|
2015-03-12 20:02:02 +01:00
|
|
|
{
|
2015-08-05 17:30:32 +02:00
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
|
|
|
|
extern u32 g_last_raw_id;
|
|
|
|
|
thread_local extern u32 g_tls_last_id;
|
2015-03-12 20:02:02 +01:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
2015-03-12 20:02:02 +01:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
u32 raw_id = g_last_raw_id;
|
2014-01-19 04:14:11 +01:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
while ((raw_id = id_traits<T>::next_id(raw_id)))
|
2015-08-04 12:46:05 +02:00
|
|
|
{
|
2015-08-11 18:14:53 +02:00
|
|
|
if (g_id_map.find(raw_id) != g_id_map.end()) continue;
|
|
|
|
|
|
|
|
|
|
g_tls_last_id = id_traits<T>::out_id(raw_id);
|
|
|
|
|
|
|
|
|
|
g_id_map.emplace(raw_id, id_data_t(std::make_shared<T>(std::forward<Args>(args)...)));
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
if (raw_id < 0x80000000) g_last_raw_id = raw_id;
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
return id_traits<T>::out_id(raw_id);
|
2015-08-04 12:46:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw EXCEPTION("Out of IDs");
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-07 23:28:09 +02:00
|
|
|
// add new ID for an existing object provided (don't use for initial object creation)
|
|
|
|
|
template<typename T> u32 import(const std::shared_ptr<T>& ptr)
|
|
|
|
|
{
|
|
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
|
|
|
|
extern u32 g_last_raw_id;
|
|
|
|
|
thread_local extern u32 g_tls_last_id;
|
2015-08-07 23:28:09 +02:00
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
|
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
u32 raw_id = g_last_raw_id;
|
|
|
|
|
|
|
|
|
|
while ((raw_id = id_traits<T>::next_id(raw_id)))
|
2015-08-07 23:28:09 +02:00
|
|
|
{
|
2015-08-11 18:14:53 +02:00
|
|
|
if (g_id_map.find(raw_id) != g_id_map.end()) continue;
|
|
|
|
|
|
|
|
|
|
g_tls_last_id = id_traits<T>::out_id(raw_id);
|
|
|
|
|
|
|
|
|
|
g_id_map.emplace(raw_id, id_data_t(ptr));
|
2015-08-07 23:28:09 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
if (raw_id < 0x80000000) g_last_raw_id = raw_id;
|
2015-08-07 23:28:09 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
return id_traits<T>::out_id(raw_id);
|
2015-08-07 23:28:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw EXCEPTION("Out of IDs");
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
// get ID of specified type
|
|
|
|
|
template<typename T> std::shared_ptr<T> get(u32 id)
|
2015-03-15 10:20:29 +01:00
|
|
|
{
|
2015-08-05 17:30:32 +02:00
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
2015-08-05 17:30:32 +02:00
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
2015-03-15 10:20:29 +01:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
const auto found = g_id_map.find(id_traits<T>::in_id(id));
|
2015-03-15 10:20:29 +01:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
if (found == g_id_map.end() || found->second.info != typeid(T))
|
2015-03-15 10:20:29 +01:00
|
|
|
{
|
2015-05-27 05:11:59 +02:00
|
|
|
return nullptr;
|
2015-03-15 10:20:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-08-04 12:46:05 +02:00
|
|
|
return std::static_pointer_cast<T>(found->second.data);
|
2015-03-15 10:20:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-08-06 15:05:33 +02:00
|
|
|
// get all IDs of specified type T (unsorted)
|
2015-08-05 17:30:32 +02:00
|
|
|
template<typename T> std::vector<std::shared_ptr<T>> get_all()
|
2015-07-08 17:01:59 +02:00
|
|
|
{
|
2015-08-05 17:30:32 +02:00
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
2015-08-05 17:30:32 +02:00
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
2015-07-08 17:01:59 +02:00
|
|
|
|
|
|
|
|
std::vector<std::shared_ptr<T>> result;
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
const std::size_t hash = typeid(T).hash_code();
|
2015-07-08 17:01:59 +02:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
for (auto& v : g_id_map)
|
2015-07-08 17:01:59 +02:00
|
|
|
{
|
2015-08-05 17:30:32 +02:00
|
|
|
if (v.second.hash == hash && v.second.info == typeid(T))
|
2015-07-08 17:01:59 +02:00
|
|
|
{
|
|
|
|
|
result.emplace_back(std::static_pointer_cast<T>(v.second.data));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
// remove ID created with type T
|
|
|
|
|
template<typename T> bool remove(u32 id)
|
2015-08-04 12:46:05 +02:00
|
|
|
{
|
2015-08-05 17:30:32 +02:00
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
const auto found = g_id_map.find(id_traits<T>::in_id(id));
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
if (found == g_id_map.end() || found->second.info != typeid(T))
|
2015-08-04 12:46:05 +02:00
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
g_id_map.erase(found);
|
2015-08-04 12:46:05 +02:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-07 23:28:09 +02:00
|
|
|
// remove ID created with type T and return the object
|
|
|
|
|
template<typename T> std::shared_ptr<T> withdraw(u32 id)
|
|
|
|
|
{
|
|
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
2015-08-07 23:28:09 +02:00
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
|
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
const auto found = g_id_map.find(id_traits<T>::in_id(id));
|
2015-08-07 23:28:09 +02:00
|
|
|
|
|
|
|
|
if (found == g_id_map.end() || found->second.info != typeid(T))
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto ptr = std::static_pointer_cast<T>(found->second.data);
|
|
|
|
|
|
|
|
|
|
g_id_map.erase(found);
|
|
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-01 00:25:52 +02:00
|
|
|
template<typename T> u32 get_count()
|
|
|
|
|
{
|
2015-08-05 17:30:32 +02:00
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
2015-08-05 17:30:32 +02:00
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
2015-07-01 00:25:52 +02:00
|
|
|
|
|
|
|
|
u32 result = 0;
|
|
|
|
|
|
2015-07-08 17:01:59 +02:00
|
|
|
const std::size_t hash = typeid(T).hash_code();
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
for (auto& v : g_id_map)
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
2015-07-09 21:55:50 +02:00
|
|
|
if (v.second.hash == hash && v.second.info == typeid(T))
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
|
|
|
|
result++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
// get sorted ID list of specified type
|
2015-08-04 12:46:05 +02:00
|
|
|
template<typename T> std::set<u32> get_set()
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
2015-08-05 17:30:32 +02:00
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
2015-08-05 17:30:32 +02:00
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
2015-07-01 00:25:52 +02:00
|
|
|
|
|
|
|
|
std::set<u32> result;
|
|
|
|
|
|
2015-07-08 17:01:59 +02:00
|
|
|
const std::size_t hash = typeid(T).hash_code();
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
for (auto& v : g_id_map)
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
2015-07-09 21:55:50 +02:00
|
|
|
if (v.second.hash == hash && v.second.info == typeid(T))
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
2015-08-11 18:14:53 +02:00
|
|
|
result.insert(id_traits<T>::out_id(v.first));
|
2015-07-01 00:25:52 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
// get sorted ID map (ID value -> ID data) of specified type
|
|
|
|
|
template<typename T> std::map<u32, std::shared_ptr<T>> get_map()
|
2014-12-24 17:09:32 +01:00
|
|
|
{
|
2015-08-05 17:30:32 +02:00
|
|
|
extern std::mutex g_id_mutex;
|
2015-08-11 18:14:53 +02:00
|
|
|
extern std::unordered_map<u32, id_data_t> g_id_map;
|
2014-12-24 17:09:32 +01:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
std::lock_guard<std::mutex> lock(g_id_mutex);
|
2015-05-27 05:11:59 +02:00
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
std::map<u32, std::shared_ptr<T>> result;
|
2015-07-01 00:25:52 +02:00
|
|
|
|
2015-07-08 17:01:59 +02:00
|
|
|
const std::size_t hash = typeid(T).hash_code();
|
|
|
|
|
|
2015-08-05 17:30:32 +02:00
|
|
|
for (auto& v : g_id_map)
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
2015-07-09 21:55:50 +02:00
|
|
|
if (v.second.hash == hash && v.second.info == typeid(T))
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
2015-08-11 18:14:53 +02:00
|
|
|
result[id_traits<T>::out_id(v.first)] = std::static_pointer_cast<T>(v.second.data);
|
2015-07-01 00:25:52 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2015-08-06 15:05:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fixed Object Manager
|
|
|
|
|
// allows to manage shared objects of any specified type, but only one object per type;
|
|
|
|
|
// object are deleted when the emulation is stopped
|
|
|
|
|
namespace fxm
|
|
|
|
|
{
|
|
|
|
|
// reinitialize
|
|
|
|
|
void clear();
|
|
|
|
|
|
|
|
|
|
// add fixed object of specified type only if it doesn't exist (one unique object per type may exist)
|
|
|
|
|
template<typename T, typename... Args> std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make(Args&&... args)
|
|
|
|
|
{
|
|
|
|
|
extern std::mutex g_fx_mutex;
|
|
|
|
|
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
|
|
|
|
|
|
|
|
|
const auto found = g_fx_map.find(typeid(T));
|
|
|
|
|
|
|
|
|
|
// only if object of this type doesn't exist
|
|
|
|
|
if (found == g_fx_map.end())
|
|
|
|
|
{
|
|
|
|
|
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
|
|
|
|
|
|
|
|
|
|
g_fx_map.emplace(typeid(T), ptr);
|
|
|
|
|
|
|
|
|
|
return std::move(ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-06 17:55:19 +02:00
|
|
|
// add fixed object of specified type, replacing previous one if it exists
|
|
|
|
|
template<typename T, typename... Args> std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make_always(Args&&... args)
|
|
|
|
|
{
|
|
|
|
|
extern std::mutex g_fx_mutex;
|
|
|
|
|
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
|
|
|
|
|
|
|
|
|
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
|
|
|
|
|
|
|
|
|
|
g_fx_map[typeid(T)] = ptr;
|
|
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-10 21:39:52 +02:00
|
|
|
// get fixed object of specified type (always returns an object, it's created if it doesn't exist)
|
|
|
|
|
template<typename T, typename... Args> std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> get_always(Args&&... args)
|
|
|
|
|
{
|
|
|
|
|
extern std::mutex g_fx_mutex;
|
|
|
|
|
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
|
|
|
|
|
|
|
|
|
const auto found = g_fx_map.find(typeid(T));
|
|
|
|
|
|
|
|
|
|
if (found == g_fx_map.end())
|
|
|
|
|
{
|
|
|
|
|
auto ptr = std::make_shared<T>(std::forward<Args>(args)...);
|
|
|
|
|
|
|
|
|
|
g_fx_map[typeid(T)] = ptr;
|
|
|
|
|
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::static_pointer_cast<T>(found->second);
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-06 15:05:33 +02:00
|
|
|
// check whether the object exists
|
|
|
|
|
template<typename T> bool check()
|
|
|
|
|
{
|
|
|
|
|
extern std::mutex g_fx_mutex;
|
|
|
|
|
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
|
|
|
|
|
|
|
|
|
return g_fx_map.find(typeid(T)) != g_fx_map.end();
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-10 21:39:52 +02:00
|
|
|
// get fixed object of specified type (returns nullptr if it doesn't exist)
|
2015-08-06 15:05:33 +02:00
|
|
|
template<typename T> std::shared_ptr<T> get()
|
|
|
|
|
{
|
|
|
|
|
extern std::mutex g_fx_mutex;
|
|
|
|
|
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
|
|
|
|
|
|
|
|
|
const auto found = g_fx_map.find(typeid(T));
|
|
|
|
|
|
|
|
|
|
if (found == g_fx_map.end())
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::static_pointer_cast<T>(found->second);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// remove fixed object created with type T
|
|
|
|
|
template<typename T> bool remove()
|
|
|
|
|
{
|
|
|
|
|
extern std::mutex g_fx_mutex;
|
|
|
|
|
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
|
|
|
|
|
|
|
|
|
const auto found = g_fx_map.find(typeid(T));
|
|
|
|
|
|
|
|
|
|
if (found == g_fx_map.end())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return g_fx_map.erase(found), true;
|
|
|
|
|
}
|
2015-08-06 17:55:19 +02:00
|
|
|
|
|
|
|
|
// remove fixed object created with type T and return it
|
|
|
|
|
template<typename T> std::shared_ptr<T> withdraw()
|
|
|
|
|
{
|
|
|
|
|
extern std::mutex g_fx_mutex;
|
|
|
|
|
extern std::unordered_map<std::type_index, std::shared_ptr<void>> g_fx_map;
|
|
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(g_fx_mutex);
|
|
|
|
|
|
|
|
|
|
const auto found = g_fx_map.find(typeid(T));
|
|
|
|
|
|
|
|
|
|
if (found == g_fx_map.end())
|
|
|
|
|
{
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto ptr = std::static_pointer_cast<T>(std::move(found->second));
|
|
|
|
|
|
|
|
|
|
return g_fx_map.erase(found), ptr;
|
|
|
|
|
}
|
2015-08-06 15:05:33 +02:00
|
|
|
}
|