id_manager: embedded RTTI

This commit is contained in:
Nekotekina 2016-08-01 02:26:55 +03:00
parent e585939ac2
commit e6bd91ada0
9 changed files with 93 additions and 77 deletions

View File

@ -558,9 +558,9 @@ s32 cellAdecOpen(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResource> res, vm::
return CELL_ADEC_ERROR_ARG; return CELL_ADEC_ERROR_ARG;
} }
auto&& adec = std::make_shared<AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg); auto&& adec = idm::make_ptr<ppu_thread, AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg);
*handle = idm::import_existing<ppu_thread>(adec); *handle = adec->id;
adec->run(); adec->run();
@ -576,9 +576,9 @@ s32 cellAdecOpenEx(vm::ptr<CellAdecType> type, vm::ptr<CellAdecResourceEx> res,
return CELL_ADEC_ERROR_ARG; return CELL_ADEC_ERROR_ARG;
} }
auto&& adec = std::make_shared<AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg); auto&& adec = idm::make_ptr<ppu_thread, AudioDecoder>(type->audioCodecType, res->startAddr, res->totalMemSize, cb->cbFunc, cb->cbArg);
*handle = idm::import_existing<ppu_thread>(adec); *handle = adec->id;
adec->run(); adec->run();

View File

@ -976,9 +976,9 @@ s32 cellDmuxOpen(vm::cptr<CellDmuxType> type, vm::cptr<CellDmuxResource> res, vm
} }
// TODO: check demuxerResource and demuxerCb arguments // TODO: check demuxerResource and demuxerCb arguments
auto&& dmux = std::make_shared<Demuxer>(res->memAddr, res->memSize, cb->cbMsgFunc, cb->cbArg); auto&& dmux = idm::make_ptr<ppu_thread, Demuxer>(res->memAddr, res->memSize, cb->cbMsgFunc, cb->cbArg);
*handle = idm::import_existing<ppu_thread>(dmux); *handle = dmux->id;
dmux->run(); dmux->run();
@ -995,9 +995,9 @@ s32 cellDmuxOpenEx(vm::cptr<CellDmuxType> type, vm::cptr<CellDmuxResourceEx> res
} }
// TODO: check demuxerResourceEx and demuxerCb arguments // TODO: check demuxerResourceEx and demuxerCb arguments
auto&& dmux = std::make_shared<Demuxer>(resEx->memAddr, resEx->memSize, cb->cbMsgFunc, cb->cbArg); auto&& dmux = idm::make_ptr<ppu_thread, Demuxer>(resEx->memAddr, resEx->memSize, cb->cbMsgFunc, cb->cbArg);
*handle = idm::import_existing<ppu_thread>(dmux); *handle = dmux->id;
dmux->run(); dmux->run();
@ -1021,9 +1021,9 @@ s32 cellDmuxOpen2(vm::cptr<CellDmuxType2> type2, vm::cptr<CellDmuxResource2> res
} }
// TODO: check demuxerType2, demuxerResource2 and demuxerCb arguments // TODO: check demuxerType2, demuxerResource2 and demuxerCb arguments
auto&& dmux = std::make_shared<Demuxer>(res2->memAddr, res2->memSize, cb->cbMsgFunc, cb->cbArg); auto&& dmux = idm::make_ptr<ppu_thread, Demuxer>(res2->memAddr, res2->memSize, cb->cbMsgFunc, cb->cbArg);
*handle = idm::import_existing<ppu_thread>(dmux); *handle = dmux->id;
dmux->run(); dmux->run();

View File

@ -737,12 +737,12 @@ struct fs_aio_thread : ppu_thread
struct fs_aio_manager struct fs_aio_manager
{ {
std::shared_ptr<fs_aio_thread> t = std::make_shared<fs_aio_thread>("FS AIO Thread", 500); std::shared_ptr<fs_aio_thread> thread;
fs_aio_manager() fs_aio_manager()
: thread(idm::make_ptr<ppu_thread, fs_aio_thread>("FS AIO Thread", 500))
{ {
idm::import_existing<ppu_thread>(t); thread->run();
t->run();
} }
}; };
@ -779,13 +779,13 @@ s32 cellFsAioRead(vm::ptr<CellFsAio> aio, vm::ptr<s32> id, fs_aio_cb_t func)
const auto m = fxm::get_always<fs_aio_manager>(); const auto m = fxm::get_always<fs_aio_manager>();
m->t->cmd_list m->thread->cmd_list
({ ({
{ 1, xid }, { 1, xid },
{ aio, func }, { aio, func },
}); });
m->t->lock_notify(); m->thread->lock_notify();
return CELL_OK; return CELL_OK;
} }
@ -800,13 +800,13 @@ s32 cellFsAioWrite(vm::ptr<CellFsAio> aio, vm::ptr<s32> id, fs_aio_cb_t func)
const auto m = fxm::get_always<fs_aio_manager>(); const auto m = fxm::get_always<fs_aio_manager>();
m->t->cmd_list m->thread->cmd_list
({ ({
{ 2, xid }, { 2, xid },
{ aio, func }, { aio, func },
}); });
m->t->lock_notify(); m->thread->lock_notify();
return CELL_OK; return CELL_OK;
} }

View File

@ -607,9 +607,9 @@ s32 _spurs::create_handler(vm::ptr<CellSpurs> spurs, u32 ppuPriority)
} }
}; };
auto&& eht = std::make_shared<handler_thread>(std::string(spurs->prefix, spurs->prefixSize) + "SpursHdlr0", ppuPriority, 0x4000); auto&& eht = idm::make_ptr<ppu_thread, handler_thread>(std::string(spurs->prefix, spurs->prefixSize) + "SpursHdlr0", ppuPriority, 0x4000);
spurs->ppu0 = idm::import_existing<ppu_thread>(eht); spurs->ppu0 = eht->id;
eht->gpr[3] = spurs.addr(); eht->gpr[3] = spurs.addr();
eht->run(); eht->run();
@ -804,11 +804,9 @@ s32 _spurs::create_event_helper(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 p
} }
}; };
auto&& eht = std::make_shared<event_helper_thread>(std::string(spurs->prefix, spurs->prefixSize) + "SpursHdlr1", ppuPriority, 0x8000); auto&& eht = idm::make_ptr<ppu_thread, event_helper_thread>(std::string(spurs->prefix, spurs->prefixSize) + "SpursHdlr1", ppuPriority, 0x8000);
const u32 tid = idm::import_existing<ppu_thread>(eht); if (!eht)
if (tid == 0)
{ {
sys_event_port_disconnect(spurs->eventPort); sys_event_port_disconnect(spurs->eventPort);
sys_event_port_destroy(spurs->eventPort); sys_event_port_destroy(spurs->eventPort);
@ -825,7 +823,7 @@ s32 _spurs::create_event_helper(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, u32 p
eht->gpr[3] = spurs.addr(); eht->gpr[3] = spurs.addr();
eht->run(); eht->run();
spurs->ppu1 = tid; spurs->ppu1 = eht->id;
return CELL_OK; return CELL_OK;
} }

View File

@ -399,10 +399,10 @@ s32 cellVdecOpen(vm::cptr<CellVdecType> type, vm::cptr<CellVdecResource> res, vm
cellVdec.warning("cellVdecOpen(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle); cellVdec.warning("cellVdecOpen(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle);
// Create decoder thread // Create decoder thread
auto&& vdec = std::make_shared<vdec_thread>(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg); auto&& vdec = idm::make_ptr<ppu_thread, vdec_thread>(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg);
// Hack: store thread id (normally it should be pointer) // Hack: store thread id (normally it should be pointer)
*handle = idm::import_existing<ppu_thread>(vdec); *handle = vdec->id;
vdec->run(); vdec->run();
@ -414,10 +414,10 @@ s32 cellVdecOpenEx(vm::cptr<CellVdecTypeEx> type, vm::cptr<CellVdecResourceEx> r
cellVdec.warning("cellVdecOpenEx(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle); cellVdec.warning("cellVdecOpenEx(type=*0x%x, res=*0x%x, cb=*0x%x, handle=*0x%x)", type, res, cb, handle);
// Create decoder thread // Create decoder thread
auto&& vdec = std::make_shared<vdec_thread>(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg); auto&& vdec = idm::make_ptr<ppu_thread, vdec_thread>(type->codecType, type->profileLevel, res->memAddr, res->memSize, cb->cbFunc, cb->cbArg);
// Hack: store thread id (normally it should be pointer) // Hack: store thread id (normally it should be pointer)
*handle = idm::import_existing<ppu_thread>(vdec); *handle = vdec->id;
vdec->run(); vdec->run();
@ -428,7 +428,7 @@ s32 cellVdecClose(u32 handle)
{ {
cellVdec.warning("cellVdecClose(handle=0x%x)", handle); cellVdec.warning("cellVdecClose(handle=0x%x)", handle);
const auto vdec = std::dynamic_pointer_cast<vdec_thread>(idm::get<ppu_thread>(handle)); // TODO: avoid RTTI const auto vdec = idm::get<ppu_thread, vdec_thread>(handle);
if (!vdec) if (!vdec)
{ {
@ -446,7 +446,7 @@ s32 cellVdecStartSeq(u32 handle)
{ {
cellVdec.trace("cellVdecStartSeq(handle=0x%x)", handle); cellVdec.trace("cellVdecStartSeq(handle=0x%x)", handle);
const auto vdec = std::dynamic_pointer_cast<vdec_thread>(idm::get<ppu_thread>(handle)); // TODO: avoid RTTI const auto vdec = idm::get<ppu_thread, vdec_thread>(handle);
if (!vdec) if (!vdec)
{ {
@ -462,7 +462,7 @@ s32 cellVdecEndSeq(u32 handle)
{ {
cellVdec.warning("cellVdecEndSeq(handle=0x%x)", handle); cellVdec.warning("cellVdecEndSeq(handle=0x%x)", handle);
const auto vdec = std::dynamic_pointer_cast<vdec_thread>(idm::get<ppu_thread>(handle)); // TODO: avoid RTTI const auto vdec = idm::get<ppu_thread, vdec_thread>(handle);
if (!vdec) if (!vdec)
{ {
@ -478,7 +478,7 @@ s32 cellVdecDecodeAu(u32 handle, CellVdecDecodeMode mode, vm::cptr<CellVdecAuInf
{ {
cellVdec.trace("cellVdecDecodeAu(handle=0x%x, mode=%d, auInfo=*0x%x)", handle, mode, auInfo); cellVdec.trace("cellVdecDecodeAu(handle=0x%x, mode=%d, auInfo=*0x%x)", handle, mode, auInfo);
const auto vdec = std::dynamic_pointer_cast<vdec_thread>(idm::get<ppu_thread>(handle)); // TODO: avoid RTTI const auto vdec = idm::get<ppu_thread, vdec_thread>(handle);
if (mode > CELL_VDEC_DEC_MODE_PB_SKIP || !vdec) if (mode > CELL_VDEC_DEC_MODE_PB_SKIP || !vdec)
{ {
@ -509,7 +509,7 @@ s32 cellVdecGetPicture(u32 handle, vm::cptr<CellVdecPicFormat> format, vm::ptr<u
{ {
cellVdec.trace("cellVdecGetPicture(handle=0x%x, format=*0x%x, outBuff=*0x%x)", handle, format, outBuff); cellVdec.trace("cellVdecGetPicture(handle=0x%x, format=*0x%x, outBuff=*0x%x)", handle, format, outBuff);
const auto vdec = std::dynamic_pointer_cast<vdec_thread>(idm::get<ppu_thread>(handle)); // TODO: avoid RTTI const auto vdec = idm::get<ppu_thread, vdec_thread>(handle);
if (!format || !vdec) if (!format || !vdec)
{ {
@ -629,7 +629,7 @@ s32 cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
{ {
cellVdec.trace("cellVdecGetPicItem(handle=0x%x, picItem=**0x%x)", handle, picItem); cellVdec.trace("cellVdecGetPicItem(handle=0x%x, picItem=**0x%x)", handle, picItem);
const auto vdec = std::dynamic_pointer_cast<vdec_thread>(idm::get<ppu_thread>(handle)); // TODO: avoid RTTI const auto vdec = idm::get<ppu_thread, vdec_thread>(handle);
if (!vdec) if (!vdec)
{ {
@ -824,7 +824,7 @@ s32 cellVdecSetFrameRate(u32 handle, CellVdecFrameRate frc)
{ {
cellVdec.trace("cellVdecSetFrameRate(handle=0x%x, frc=0x%x)", handle, frc); cellVdec.trace("cellVdecSetFrameRate(handle=0x%x, frc=0x%x)", handle, frc);
const auto vdec = std::dynamic_pointer_cast<vdec_thread>(idm::get<ppu_thread>(handle)); // TODO: avoid RTTI const auto vdec = idm::get<ppu_thread, vdec_thread>(handle);
if (!vdec) if (!vdec)
{ {

View File

@ -489,9 +489,7 @@ s32 cellSurMixerCreate(vm::cptr<CellSurMixerConfig> config)
libmixer.warning("*** surMixer created (ch1=%d, ch2=%d, ch6=%d, ch8=%d)", config->chStrips1, config->chStrips2, config->chStrips6, config->chStrips8); libmixer.warning("*** surMixer created (ch1=%d, ch2=%d, ch6=%d, ch8=%d)", config->chStrips1, config->chStrips2, config->chStrips6, config->chStrips8);
auto&& thread = std::make_shared<surmixer_thread>("Surmixer Thread"); auto&& thread = idm::make_ptr<ppu_thread, surmixer_thread>("Surmixer Thread");
idm::import_existing<ppu_thread>(thread);
thread->run(); thread->run();

View File

@ -80,6 +80,7 @@ std::string ppu_thread::dump() const
{ {
std::string ret; std::string ret;
ret += fmt::format("Type: %s\n", typeid(*this).name());
ret += fmt::format("State: 0x%08x\n", state.load()); ret += fmt::format("State: 0x%08x\n", state.load());
ret += fmt::format("Priority: %d\n", prio); ret += fmt::format("Priority: %d\n", prio);

View File

@ -24,7 +24,7 @@ u32 id_manager::typeinfo::add_type()
return ::size32(list) - 1; return ::size32(list) - 1;
} }
id_manager::id_map::pointer idm::allocate_id(u32 tag, u32 min, u32 max) id_manager::id_map::pointer idm::allocate_id(u32 tag, u32 type, u32 min, u32 max)
{ {
// Check all IDs starting from "next id" // Check all IDs starting from "next id"
for (u32 i = 0; i <= max - min; i++) for (u32 i = 0; i <= max - min; i++)
@ -33,7 +33,7 @@ id_manager::id_map::pointer idm::allocate_id(u32 tag, u32 min, u32 max)
if (g_id[tag] < min || g_id[tag] > max) g_id[tag] = min; if (g_id[tag] < min || g_id[tag] > max) g_id[tag] = min;
// Get ID // Get ID
const auto r = g_map[tag].emplace(g_id[tag]++, nullptr); const auto r = g_map[tag].emplace(id_manager::id_key{g_id[tag]++, type}, nullptr);
if (r.second) if (r.second)
{ {
@ -58,19 +58,23 @@ std::shared_ptr<void> idm::deallocate_id(u32 tag, u32 id)
return ptr; return ptr;
} }
id_manager::id_map::pointer idm::find_id(u32 type, u32 id) id_manager::id_map::pointer idm::find_id(u32 type, u32 true_type, u32 id)
{ {
const auto found = g_map[type].find(id); const auto found = g_map[type].find(id);
if (found == g_map[type].end()) return nullptr; if (found == g_map[type].end()) return nullptr;
if (true_type != get_type<void>() && found->first.type() != true_type) return nullptr;
return &*found; return &*found;
} }
std::shared_ptr<void> idm::delete_id(u32 type, u32 tag, u32 id) std::shared_ptr<void> idm::delete_id(u32 type, u32 true_type, u32 tag, u32 id)
{ {
writer_lock lock(g_mutex); writer_lock lock(g_mutex);
if (!find_id(type, true_type, id)) return nullptr; // ???
auto&& ptr = deallocate_id(tag, id); auto&& ptr = deallocate_id(tag, id);
g_map[type].erase(id); g_map[type].erase(id);

View File

@ -228,13 +228,13 @@ class idm
}; };
// Prepares new ID, returns nullptr if out of resources // Prepares new ID, returns nullptr if out of resources
static id_manager::id_map::pointer allocate_id(u32 tag, u32 min, u32 max); static id_manager::id_map::pointer allocate_id(u32 tag, u32 type, u32 min, u32 max);
// Deallocate ID, returns object // Deallocate ID, returns object
static std::shared_ptr<void> deallocate_id(u32 tag, u32 id); static std::shared_ptr<void> deallocate_id(u32 tag, u32 id);
// Allocate new ID and construct it from the provider() // Allocate new ID and construct it from the provider()
template<typename T, typename F> template<typename T, typename Set, typename F>
static id_manager::id_map::pointer create_id(F&& provider) static id_manager::id_map::pointer create_id(F&& provider)
{ {
id_manager::typeinfo::update<T>(); id_manager::typeinfo::update<T>();
@ -242,7 +242,7 @@ class idm
writer_lock lock(g_mutex); writer_lock lock(g_mutex);
if (auto place = allocate_id(get_tag<T>(), id_manager::id_traits<T>::min, id_manager::id_traits<T>::max)) if (auto place = allocate_id(get_tag<T>(), get_type<Set>(), id_manager::id_traits<T>::min, id_manager::id_traits<T>::max))
{ {
try try
{ {
@ -265,10 +265,10 @@ class idm
} }
// Get ID (internal) // Get ID (internal)
static id_manager::id_map::pointer find_id(u32 type, u32 id); static id_manager::id_map::pointer find_id(u32 type, u32 true_type, u32 id);
// Remove ID and return object // Remove ID and return object
static std::shared_ptr<void> delete_id(u32 type, u32 tag, u32 id); static std::shared_ptr<void> delete_id(u32 type, u32 true_type, u32 tag, u32 id);
public: public:
// Initialize object manager // Initialize object manager
@ -279,13 +279,13 @@ public:
// Add a new ID of specified type with specified constructor arguments (returns object or nullptr) // Add a new ID of specified type with specified constructor arguments (returns object or nullptr)
template<typename T, typename Make = T, typename... Args> template<typename T, typename Make = T, typename... Args>
static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<T>> make_ptr(Args&&... args) static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<Make>> make_ptr(Args&&... args)
{ {
if (auto pair = create_id<T>(WRAP_EXPR(std::make_shared<Make>(std::forward<Args>(args)...)))) if (auto pair = create_id<T, Make>(WRAP_EXPR(std::make_shared<Make>(std::forward<Args>(args)...))))
{ {
id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second); id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second);
id_manager::on_stop<T>::func(nullptr); id_manager::on_stop<T>::func(nullptr);
return{ pair->second, static_cast<T*>(pair->second.get()) }; return{ pair->second, static_cast<Make*>(pair->second.get()) };
} }
return nullptr; return nullptr;
@ -295,7 +295,7 @@ public:
template<typename T, typename Make = T, typename... Args> template<typename T, typename Make = T, typename... Args>
static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, u32> make(Args&&... args) static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, u32> make(Args&&... args)
{ {
if (auto pair = create_id<T>(WRAP_EXPR(std::make_shared<Make>(std::forward<Args>(args)...)))) if (auto pair = create_id<T, Make>(WRAP_EXPR(std::make_shared<Make>(std::forward<Args>(args)...))))
{ {
id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second); id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second);
id_manager::on_stop<T>::func(nullptr); id_manager::on_stop<T>::func(nullptr);
@ -306,10 +306,10 @@ public:
} }
// Add a new ID for an existing object provided (returns new id) // Add a new ID for an existing object provided (returns new id)
template<typename T> template<typename T, typename Made = T>
static inline u32 import_existing(const std::shared_ptr<T>& ptr) static inline u32 import_existing(const std::shared_ptr<T>& ptr)
{ {
if (auto pair = create_id<T>(WRAP_EXPR(ptr))) if (auto pair = create_id<T, Made>(WRAP_EXPR(ptr)))
{ {
id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second); id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second);
id_manager::on_stop<T>::func(nullptr); id_manager::on_stop<T>::func(nullptr);
@ -320,53 +320,53 @@ public:
} }
// Add a new ID for an object returned by provider() // Add a new ID for an object returned by provider()
template<typename T, typename F, typename = std::result_of_t<F()>> template<typename T, typename Made = T, typename F, typename = std::result_of_t<F()>>
static inline std::shared_ptr<T> import(F&& provider) static inline std::shared_ptr<Made> import(F&& provider)
{ {
if (auto pair = create_id<T>(std::forward<F>(provider))) if (auto pair = create_id<T, Made>(std::forward<F>(provider)))
{ {
id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second); id_manager::on_init<T>::func(static_cast<T*>(pair->second.get()), pair->second);
id_manager::on_stop<T>::func(nullptr); id_manager::on_stop<T>::func(nullptr);
return { pair->second, static_cast<T*>(pair->second.get()) }; return { pair->second, static_cast<Made*>(pair->second.get()) };
} }
return nullptr; return nullptr;
} }
// Check whether the ID exists // Check whether the ID exists
template<typename T> template<typename T, typename Get = void>
static inline bool check(u32 id) static inline bool check(u32 id)
{ {
reader_lock lock(g_mutex); reader_lock lock(g_mutex);
return find_id(get_type<T>(), id) != nullptr; return find_id(get_type<T>(), get_type<Get>(), id) != nullptr;
} }
// Get the ID // Get the ID
template<typename T> template<typename T, typename Get = void, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>>
static inline std::shared_ptr<T> get(u32 id) static inline std::shared_ptr<Made> get(u32 id)
{ {
reader_lock lock(g_mutex); reader_lock lock(g_mutex);
const auto found = find_id(get_type<T>(), id); const auto found = find_id(get_type<T>(), get_type<Get>(), id);
if (UNLIKELY(found == nullptr)) if (UNLIKELY(found == nullptr))
{ {
return nullptr; return nullptr;
} }
return{ found->second, static_cast<T*>(found->second.get()) }; return{ found->second, static_cast<Made*>(found->second.get()) };
} }
// Conditionally get the ID, almost similar to select() but for the single object only. // Conditionally get the ID, almost similar to select() but for the single object only.
template<typename T, typename F, typename FT = decltype(&F::operator()), typename A2 = typename function_traits<FT>::second_type> template<typename T, typename Get = void, typename F, typename FT = decltype(&F::operator()), typename A2 = typename function_traits<FT>::second_type>
static inline auto get(u32 id, F&& pred) static inline auto get(u32 id, F&& pred)
{ {
using result_type = std::conditional_t<std::is_void<typename function_traits<FT>::return_type>::value, void, std::shared_ptr<A2>>; using result_type = std::conditional_t<std::is_void<typename function_traits<FT>::return_type>::value, void, std::shared_ptr<A2>>;
reader_lock lock(g_mutex); reader_lock lock(g_mutex);
const auto found = find_id(get_type<T>(), id); const auto found = find_id(get_type<T>(), get_type<Get>(), id);
if (UNLIKELY(found == nullptr)) if (UNLIKELY(found == nullptr))
{ {
@ -404,19 +404,34 @@ public:
} }
// Get count of objects // Get count of objects
template<typename T> template<typename T, typename Get = void>
static inline u32 get_count() static inline u32 get_count()
{ {
reader_lock lock(g_mutex); reader_lock lock(g_mutex);
if (std::is_void<Get>::value)
{
return ::size32(g_map[get_type<T>()]); return ::size32(g_map[get_type<T>()]);
} }
u32 result = 0;
for (auto& id : g_map[get_type<T>()])
{
if (id.first.type() == get_type<Get>())
{
result++;
}
}
return result;
}
// Remove the ID // Remove the ID
template<typename T> template<typename T, typename Get = void>
static inline bool remove(u32 id) static inline bool remove(u32 id)
{ {
auto&& ptr = delete_id(get_type<T>(), get_tag<T>(), id); auto&& ptr = delete_id(get_type<T>(), get_type<Get>(), get_tag<T>(), id);
if (LIKELY(ptr)) if (LIKELY(ptr))
{ {
@ -427,28 +442,28 @@ public:
} }
// Remove the ID and return it // Remove the ID and return it
template<typename T> template<typename T, typename Get = void, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>>
static inline std::shared_ptr<T> withdraw(u32 id) static inline std::shared_ptr<Made> withdraw(u32 id)
{ {
auto&& ptr = delete_id(get_type<T>(), get_tag<T>(), id); auto&& ptr = delete_id(get_type<T>(), get_type<Get>(), get_tag<T>(), id);
if (LIKELY(ptr)) if (LIKELY(ptr))
{ {
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get())); id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
} }
return{ ptr, static_cast<T*>(ptr.get()) }; return{ ptr, static_cast<Made*>(ptr.get()) };
} }
// Conditionally remove the ID and return it. // Conditionally remove the ID and return it.
template<typename T, typename F> template<typename T, typename Get = void, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>, typename F>
static inline std::shared_ptr<T> withdraw(u32 id, F&& pred) static inline std::shared_ptr<Made> withdraw(u32 id, F&& pred)
{ {
std::shared_ptr<void> ptr; std::shared_ptr<void> ptr;
{ {
writer_lock lock(g_mutex); writer_lock lock(g_mutex);
const auto found = find_id(get_type<T>(), id); const auto found = find_id(get_type<T>(), get_type<Get>(), id);
if (UNLIKELY(found == nullptr || !pred(id, *static_cast<T*>(found->second.get())))) if (UNLIKELY(found == nullptr || !pred(id, *static_cast<T*>(found->second.get()))))
{ {
@ -462,7 +477,7 @@ public:
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get())); id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
return{ ptr, static_cast<T*>(ptr.get()) }; return{ ptr, static_cast<Made*>(ptr.get()) };
} }
}; };