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-11-26 09:06:29 +01:00
|
|
|
// TODO: make id_aux_initialize and id_aux_finalize safer against a possible ODR violation
|
2015-09-18 00:41:14 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Function called after the successfull creation of an ID (does nothing by default, provide an overload)
|
|
|
|
|
inline void id_aux_initialize(void*)
|
|
|
|
|
{
|
|
|
|
|
;
|
|
|
|
|
}
|
2015-09-18 00:41:14 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Function called after the ID removal (does nothing by default, provide an overload)
|
|
|
|
|
inline void id_aux_finalize(void*)
|
2015-09-18 00:41:14 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
;
|
2015-09-18 00:41:14 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Type-erased id_aux_* function type
|
|
|
|
|
using id_aux_func_t = void(*)(void*);
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
struct id_type_info_t
|
2015-08-11 18:14:53 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
static const auto size = sizeof(T); // forbid forward declarations
|
2015-08-11 18:14:53 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
static const id_aux_func_t on_remove;
|
|
|
|
|
};
|
2015-08-11 18:14:53 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Type-erased finalization function
|
|
|
|
|
template<typename T>
|
|
|
|
|
const id_aux_func_t id_type_info_t<T>::on_remove = [](void* ptr)
|
|
|
|
|
{
|
|
|
|
|
return id_aux_finalize(static_cast<T*>(ptr));
|
2015-08-11 18:14:53 +02:00
|
|
|
};
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
using id_type_index_t = const id_aux_func_t*;
|
|
|
|
|
|
|
|
|
|
// Get a unique pointer to the on_remove value (will be unique for each type)
|
|
|
|
|
template<typename T>
|
|
|
|
|
inline constexpr id_type_index_t get_id_type_index()
|
2015-05-27 05:11:59 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
return &id_type_info_t<T>::on_remove;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Default ID traits for any arbitrary type
|
|
|
|
|
template<typename T>
|
|
|
|
|
struct id_traits
|
|
|
|
|
{
|
|
|
|
|
static const auto size = sizeof(T); // forbid forward declarations
|
|
|
|
|
|
|
|
|
|
// 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; }
|
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-11-26 09:06:29 +01:00
|
|
|
struct id_data_t final
|
|
|
|
|
{
|
|
|
|
|
std::shared_ptr<void> data;
|
|
|
|
|
const std::type_info* info;
|
|
|
|
|
id_type_index_t type_index;
|
|
|
|
|
|
|
|
|
|
template<typename T> id_data_t(const std::shared_ptr<T>& data)
|
|
|
|
|
: data(data)
|
|
|
|
|
, info(&typeid(T))
|
|
|
|
|
, type_index(get_id_type_index<T>())
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
};
|
2015-09-18 00:41:14 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
using map_t = std::unordered_map<u32, id_data_t>;
|
2015-09-18 00:41:14 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Can be called from the constructor called through make() or make_ptr() to get the ID of the object being created
|
|
|
|
|
inline u32 get_last_id()
|
2015-09-18 00:41:14 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
extern thread_local u32 g_tls_last_id;
|
|
|
|
|
|
2015-08-11 18:14:53 +02:00
|
|
|
return g_tls_last_id;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Remove all objects
|
|
|
|
|
void clear();
|
2015-08-05 17:30:32 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Internal
|
|
|
|
|
bool check(u32 in_id, id_type_index_t type);
|
2014-01-19 04:14:11 +01:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Check if an ID of specified type exists
|
|
|
|
|
template<typename T>
|
|
|
|
|
bool check(u32 id)
|
2015-09-18 00:41:14 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
return check(id_traits<T>::in_id(id), get_id_type_index<T>());
|
2015-08-08 03:16:08 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Check if an ID exists and return its type or nullptr
|
|
|
|
|
const std::type_info* get_type(u32 raw_id);
|
2015-08-08 03:16:08 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Internal
|
|
|
|
|
template<typename T, typename Ptr>
|
|
|
|
|
std::shared_ptr<T> add(Ptr&& get_ptr)
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
extern std::mutex g_mutex;
|
|
|
|
|
extern idm::map_t g_map;
|
|
|
|
|
extern u32 g_last_raw_id;
|
|
|
|
|
extern thread_local u32 g_tls_last_id;
|
|
|
|
|
|
2015-09-18 00:41:14 +02:00
|
|
|
std::lock_guard<std::mutex> lock(g_mutex);
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-09-18 00:41:14 +02:00
|
|
|
for (u32 raw_id = g_last_raw_id; (raw_id = id_traits<T>::next_id(raw_id)); /**/)
|
2015-08-04 12:46:05 +02:00
|
|
|
{
|
2015-09-18 00:41:14 +02:00
|
|
|
if (g_map.find(raw_id) != g_map.end()) continue;
|
2015-08-11 18:14:53 +02:00
|
|
|
|
|
|
|
|
g_tls_last_id = id_traits<T>::out_id(raw_id);
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
std::shared_ptr<T> ptr = get_ptr();
|
2015-07-01 00:25:52 +02:00
|
|
|
|
2015-09-18 00:41:14 +02:00
|
|
|
g_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
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Add a new ID of specified type with specified constructor arguments (returns object or nullptr)
|
|
|
|
|
template<typename T, typename... Args>
|
|
|
|
|
std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make_ptr(Args&&... args)
|
2015-03-12 20:02:02 +01:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
if (auto ptr = add<T>(WRAP_EXPR(std::make_shared<T>(std::forward<Args>(args)...))))
|
2015-08-04 12:46:05 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_initialize(ptr.get());
|
|
|
|
|
return ptr;
|
2015-08-04 12:46:05 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
return nullptr;
|
2015-08-04 12:46:05 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Add a 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-08-07 23:28:09 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
if (auto ptr = add<T>(WRAP_EXPR(std::make_shared<T>(std::forward<Args>(args)...))))
|
2015-08-07 23:28:09 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_initialize(ptr.get());
|
|
|
|
|
return get_last_id();
|
2015-08-07 23:28:09 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
throw EXCEPTION("Out of IDs ('%s')", typeid(T).name());
|
2015-08-07 23:28:09 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Add a new ID for an existing object provided (returns new id)
|
|
|
|
|
template<typename T>
|
|
|
|
|
u32 import(const std::shared_ptr<T>& ptr)
|
2015-03-15 10:20:29 +01:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
static const auto size = sizeof(T); // forbid forward declarations
|
2015-08-05 17:30:32 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
if (add<T>(WRAP_EXPR(ptr)))
|
2015-03-15 10:20:29 +01:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_initialize(ptr.get());
|
|
|
|
|
return get_last_id();
|
2015-03-15 10:20:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
throw EXCEPTION("Out of IDs ('%s')", typeid(T).name());
|
2015-03-15 10:20:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Internal
|
|
|
|
|
std::shared_ptr<void> get(u32 in_id, id_type_index_t type);
|
|
|
|
|
|
|
|
|
|
// Get ID of specified type
|
|
|
|
|
template<typename T>
|
|
|
|
|
std::shared_ptr<T> get(u32 id)
|
2015-07-08 17:01:59 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
return std::static_pointer_cast<T>(get(id_traits<T>::in_id(id), get_id_type_index<T>()));
|
|
|
|
|
}
|
2015-07-08 17:01:59 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Internal
|
|
|
|
|
idm::map_t get_all(id_type_index_t type);
|
2015-07-08 17:01:59 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Get all IDs of specified type T (unsorted)
|
|
|
|
|
template<typename T>
|
|
|
|
|
std::vector<std::shared_ptr<T>> get_all()
|
|
|
|
|
{
|
|
|
|
|
std::vector<std::shared_ptr<T>> result;
|
2015-07-08 17:01:59 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
for (auto& id : get_all(get_id_type_index<T>()))
|
2015-07-08 17:01:59 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
result.emplace_back(std::static_pointer_cast<T>(id.second.data));
|
2015-07-08 17:01:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
std::shared_ptr<void> withdraw(u32 in_id, id_type_index_t type);
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Remove the ID created with type T
|
|
|
|
|
template<typename T>
|
|
|
|
|
bool remove(u32 id)
|
|
|
|
|
{
|
|
|
|
|
if (auto ptr = withdraw(id_traits<T>::in_id(id), get_id_type_index<T>()))
|
2015-08-04 12:46:05 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_finalize(static_cast<T*>(ptr.get()));
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
2015-08-04 12:46:05 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
return false;
|
2015-08-04 12:46:05 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Remove the ID created with type T and return it
|
|
|
|
|
template<typename T>
|
|
|
|
|
std::shared_ptr<T> withdraw(u32 id)
|
2015-08-07 23:28:09 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
if (auto ptr = std::static_pointer_cast<T>(withdraw(id_traits<T>::in_id(id), get_id_type_index<T>())))
|
2015-08-07 23:28:09 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_finalize(ptr.get());
|
2015-08-07 23:28:09 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
return ptr;
|
|
|
|
|
}
|
2015-08-07 23:28:09 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
return nullptr;
|
2015-08-07 23:28:09 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
u32 get_count(id_type_index_t type);
|
2015-07-01 00:25:52 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
template<typename T>
|
|
|
|
|
u32 get_count()
|
|
|
|
|
{
|
|
|
|
|
return get_count(get_id_type_index<T>());
|
2015-07-01 00:25:52 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Get sorted list of all IDs of specified type
|
|
|
|
|
template<typename T>
|
|
|
|
|
std::set<u32> get_set()
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
|
|
|
|
std::set<u32> result;
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
for (auto& id : get_all(get_id_type_index<T>()))
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
result.emplace(id_traits<T>::out_id(id.first));
|
2015-07-01 00:25:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Get sorted map (ID value -> ID data) of all IDs 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
|
|
|
std::map<u32, std::shared_ptr<T>> result;
|
2015-07-01 00:25:52 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
for (auto& id : get_all(get_id_type_index<T>()))
|
2015-07-01 00:25:52 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
result[id_traits<T>::out_id(id.first)] = std::static_pointer_cast<T>(id.second.data);
|
2015-07-01 00:25:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
2015-11-26 09:06:29 +01:00
|
|
|
}
|
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
|
|
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
using map_t = std::unordered_map<id_type_index_t, std::shared_ptr<void>>;
|
2015-09-18 00:41:14 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Remove all objects
|
|
|
|
|
void clear();
|
2015-09-18 00:41:14 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Internal (returns old and new pointers)
|
|
|
|
|
template<typename T, bool Always, typename Ptr>
|
|
|
|
|
std::pair<std::shared_ptr<T>, std::shared_ptr<T>> add(Ptr&& get_ptr)
|
2015-09-18 00:41:14 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
extern std::mutex g_mutex;
|
|
|
|
|
extern fxm::map_t g_map;
|
2015-08-06 15:05:33 +02:00
|
|
|
|
2015-09-18 00:41:14 +02:00
|
|
|
std::lock_guard<std::mutex> lock(g_mutex);
|
2015-08-06 15:05:33 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
auto& item = g_map[get_id_type_index<T>()];
|
2015-08-06 15:05:33 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
if (Always || !item)
|
2015-08-06 15:05:33 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
std::shared_ptr<T> old = std::static_pointer_cast<T>(std::move(item));
|
|
|
|
|
std::shared_ptr<T> ptr = get_ptr();
|
2015-08-06 15:05:33 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Set new object
|
|
|
|
|
item = ptr;
|
2015-08-06 15:05:33 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
return{ std::move(old), std::move(ptr) };
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return{ std::static_pointer_cast<T>(item), nullptr };
|
2015-08-06 15:05:33 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Create the object (returns nullptr if it already exists)
|
|
|
|
|
template<typename T, typename... Args>
|
|
|
|
|
std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<T>> make(Args&&... args)
|
2015-08-06 17:55:19 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
auto pair = add<T, false>(WRAP_EXPR(std::make_shared<T>(std::forward<Args>(args)...)));
|
2015-09-18 00:41:14 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
if (pair.second)
|
2015-09-18 00:41:14 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_initialize(pair.second.get());
|
|
|
|
|
return std::move(pair.second);
|
2015-09-18 00:41:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Create the object unconditionally (old object will be removed 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)
|
2015-09-18 00:41:14 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
auto pair = add<T, true>(WRAP_EXPR(std::make_shared<T>(std::forward<Args>(args)...)));
|
2015-09-18 00:41:14 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
if (pair.first)
|
|
|
|
|
{
|
|
|
|
|
id_aux_finalize(pair.first.get());
|
|
|
|
|
}
|
2015-08-06 17:55:19 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_initialize(pair.second.get());
|
|
|
|
|
return std::move(pair.second);
|
2015-08-06 17:55:19 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Emplace the object
|
|
|
|
|
template<typename T>
|
|
|
|
|
bool import(const std::shared_ptr<T>& ptr)
|
2015-08-10 21:39:52 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
static const auto size = sizeof(T); // forbid forward declarations
|
2015-08-10 21:39:52 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
auto pair = add<T, false>(WRAP_EXPR(ptr));
|
2015-08-10 21:39:52 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
if (pair.second)
|
2015-08-10 21:39:52 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_initialize(pair.second.get());
|
|
|
|
|
return true;
|
2015-08-10 21:39:52 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
return false;
|
2015-08-10 21:39:52 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Emplace the object unconditionally (old object will be removed if it exists)
|
|
|
|
|
template<typename T>
|
|
|
|
|
void import_always(const std::shared_ptr<T>& ptr)
|
2015-08-06 15:05:33 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
static const auto size = sizeof(T); // forbid forward declarations
|
2015-08-06 15:05:33 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
auto pair = add<T, true>(WRAP_EXPR(ptr));
|
2015-08-06 15:05:33 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
if (pair.first)
|
2015-08-06 15:05:33 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_finalize(pair.first.get());
|
2015-08-06 15:05:33 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_initialize(pair.second.get());
|
2015-08-06 15:05:33 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Get the object unconditionally (create an object 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)
|
2015-08-06 15:05:33 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
auto pair = add<T, false>(WRAP_EXPR(std::make_shared<T>(std::forward<Args>(args)...)));
|
2015-08-06 15:05:33 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
if (pair.second)
|
2015-08-06 15:05:33 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_initialize(pair.second.get());
|
|
|
|
|
return std::move(pair.second);
|
2015-08-06 15:05:33 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
return std::move(pair.first);
|
2015-08-06 15:05:33 +02:00
|
|
|
}
|
2015-08-06 17:55:19 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Internal
|
|
|
|
|
bool check(id_type_index_t type);
|
|
|
|
|
|
|
|
|
|
// Check whether the object exists
|
|
|
|
|
template<typename T>
|
|
|
|
|
bool check()
|
2015-08-06 17:55:19 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
return check(get_id_type_index<T>());
|
|
|
|
|
}
|
2015-08-06 17:55:19 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Internal
|
|
|
|
|
std::shared_ptr<void> get(id_type_index_t type);
|
2015-08-06 17:55:19 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Get the object (returns nullptr if it doesn't exist)
|
|
|
|
|
template<typename T>
|
|
|
|
|
std::shared_ptr<T> get()
|
|
|
|
|
{
|
|
|
|
|
return std::static_pointer_cast<T>(get(get_id_type_index<T>()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Internal
|
|
|
|
|
std::shared_ptr<void> withdraw(id_type_index_t type);
|
|
|
|
|
|
|
|
|
|
// Delete the object
|
|
|
|
|
template<typename T>
|
|
|
|
|
bool remove()
|
|
|
|
|
{
|
|
|
|
|
if (auto ptr = withdraw(get_id_type_index<T>()))
|
2015-08-06 17:55:19 +02:00
|
|
|
{
|
2015-11-26 09:06:29 +01:00
|
|
|
id_aux_finalize(static_cast<T*>(ptr.get()));
|
|
|
|
|
return true;
|
2015-08-06 17:55:19 +02:00
|
|
|
}
|
|
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
2015-08-06 17:55:19 +02:00
|
|
|
|
2015-11-26 09:06:29 +01:00
|
|
|
// Delete the object and return it
|
|
|
|
|
template<typename T>
|
|
|
|
|
std::shared_ptr<T> withdraw()
|
|
|
|
|
{
|
|
|
|
|
if (auto ptr = std::static_pointer_cast<T>(withdraw(get_id_type_index<T>())))
|
|
|
|
|
{
|
|
|
|
|
id_aux_finalize(ptr.get());
|
|
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
2015-08-06 17:55:19 +02:00
|
|
|
}
|
2015-11-26 09:06:29 +01:00
|
|
|
}
|