IdManager improved

This commit is contained in:
Nekotekina 2017-01-25 20:50:30 +03:00 committed by Ivan
parent 6c189511af
commit 591a6c8671
43 changed files with 408 additions and 307 deletions

View File

@ -839,34 +839,6 @@ struct multicast<T, Value, void>
} }
}; };
// Tagged ID type
template <typename T = void, typename ID = u32>
class id_value
{
// Initial value
mutable ID m_value{static_cast<ID>(-1)};
// Allow access for ID manager
friend class idm;
// Update ID
void operator=(const ID& value) const
{
m_value = value;
}
public:
constexpr id_value()
{
}
// Get the value
operator ID() const
{
return m_value;
}
};
// Error code type (return type), implements error reporting. Could be a template. // Error code type (return type), implements error reporting. Could be a template.
struct error_code struct error_code
{ {
@ -921,14 +893,3 @@ constexpr FORCE_INLINE error_code::not_an_error not_an_error(const T& value)
{ {
return static_cast<error_code::not_an_error>(static_cast<s32>(value)); return static_cast<error_code::not_an_error>(static_cast<s32>(value));
} }
template <typename T, typename ID>
struct fmt_unveil<id_value<T, ID>>
{
using type = typename fmt_unveil<ID>::type;
static inline auto get(const id_value<T, ID>& value)
{
return fmt_unveil<ID>::get(value);
}
};

View File

@ -93,7 +93,8 @@ cpu_thread::~cpu_thread()
{ {
} }
cpu_thread::cpu_thread() cpu_thread::cpu_thread(u32 id)
: id(id)
{ {
} }

View File

@ -31,9 +31,9 @@ public:
virtual void on_stop() override; virtual void on_stop() override;
virtual ~cpu_thread() override; virtual ~cpu_thread() override;
const id_value<> id{}; const u32 id;
cpu_thread(); cpu_thread(u32 id);
// Public thread state // Public thread state
atomic_t<bs_t<cpu_flag>> state{+cpu_flag::stop}; atomic_t<bs_t<cpu_flag>> state{+cpu_flag::stop};
@ -50,6 +50,12 @@ public:
// Set cpu_flag::signal // Set cpu_flag::signal
void set_signal(); void set_signal();
// Check thread type
u32 id_type()
{
return id >> 24;
}
// Print CPU state // Print CPU state
virtual std::string dump() const; virtual std::string dump() const;

View File

@ -143,10 +143,14 @@ class ElementaryStream
bool is_full(u32 space); bool is_full(u32 space);
public: public:
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec); ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec);
Demuxer* dmux; Demuxer* dmux;
const id_value<> id{}; const u32 id = idm::last_id();
const u32 memAddr; const u32 memAddr;
const u32 memSize; const u32 memSize;
const u32 fidMajor; const u32 fidMajor;

View File

@ -109,6 +109,10 @@ struct CellJpgDecDataOutInfo
// Custom structs // Custom structs
struct CellJpgDecSubHandle struct CellJpgDecSubHandle
{ {
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
u32 fd; u32 fd;
u64 fileSize; u64 fileSize;
CellJpgDecInfo info; CellJpgDecInfo info;

View File

@ -321,6 +321,10 @@ struct CellVpostPictureInfo
class VpostInstance class VpostInstance
{ {
public: public:
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const bool to_rgba; const bool to_rgba;
VpostInstance(bool rgba) VpostInstance(bool rgba)

View File

@ -16,7 +16,11 @@ logs::channel sceNpTrophy("sceNpTrophy", logs::level::notice);
struct trophy_context_t struct trophy_context_t
{ {
const id_value<> id{}; static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const u32 id = idm::last_id();
std::string trp_name; std::string trp_name;
fs::file trp_stream; fs::file trp_stream;
@ -25,7 +29,11 @@ struct trophy_context_t
struct trophy_handle_t struct trophy_handle_t
{ {
const id_value<> id{}; static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const u32 id = idm::last_id();
}; };
// Functions // Functions

View File

@ -9,6 +9,10 @@ extern logs::channel sysPrxForUser;
struct HeapInfo struct HeapInfo
{ {
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const std::string name; const std::string name;
HeapInfo(const char* name) HeapInfo(const char* name)

View File

@ -11,6 +11,10 @@ using sys_mempool_t = u32;
struct memory_pool_t struct memory_pool_t
{ {
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
vm::ptr<void> chunk; vm::ptr<void> chunk;
u64 chunk_size; u64 chunk_size;
u64 block_size; u64 block_size;

View File

@ -86,10 +86,9 @@ int inet_pton(int af, const char *src, char *dst)
// We map host sockets to sequential IDs to return as descriptors because syscalls expect socket IDs to be under 1024. // We map host sockets to sequential IDs to return as descriptors because syscalls expect socket IDs to be under 1024.
struct sys_net_socket final struct sys_net_socket final
{ {
using id_base = sys_net_socket; static const u32 id_base = 0;
static const u32 id_step = 1;
static constexpr u32 id_min = 0; // Minimal valid socket number is 0 (not 1). static const u32 id_count = 1024;
static constexpr u32 id_max = 1023;
sys_net::socket_t s = -1; sys_net::socket_t s = -1;

View File

@ -253,7 +253,7 @@ ppu_thread::~ppu_thread()
} }
ppu_thread::ppu_thread(const std::string& name, u32 prio, u32 stack) ppu_thread::ppu_thread(const std::string& name, u32 prio, u32 stack)
: cpu_thread() : cpu_thread(idm::last_id())
, prio(prio) , prio(prio)
, stack_size(std::max<u32>(stack, 0x4000)) , stack_size(std::max<u32>(stack, 0x4000))
, stack_addr(vm::alloc(stack_size, vm::stack)) , stack_addr(vm::alloc(stack_size, vm::stack))
@ -404,7 +404,7 @@ void ppu_thread::fast_call(u32 addr, u32 rtoc)
u32 ppu_thread::stack_push(u32 size, u32 align_v) u32 ppu_thread::stack_push(u32 size, u32 align_v)
{ {
if (auto cpu = get_current_cpu_thread()) if (cpu->id >= id_min) if (auto cpu = get_current_cpu_thread()) if (cpu->id_type() == 1)
{ {
ppu_thread& context = static_cast<ppu_thread&>(*cpu); ppu_thread& context = static_cast<ppu_thread&>(*cpu);
@ -430,7 +430,7 @@ u32 ppu_thread::stack_push(u32 size, u32 align_v)
void ppu_thread::stack_pop_verbose(u32 addr, u32 size) noexcept void ppu_thread::stack_pop_verbose(u32 addr, u32 size) noexcept
{ {
if (auto cpu = get_current_cpu_thread()) if (cpu->id >= id_min) if (auto cpu = get_current_cpu_thread()) if (cpu->id_type() == 1)
{ {
ppu_thread& context = static_cast<ppu_thread&>(*cpu); ppu_thread& context = static_cast<ppu_thread&>(*cpu);

View File

@ -20,10 +20,9 @@ enum class ppu_cmd : u32
class ppu_thread : public cpu_thread class ppu_thread : public cpu_thread
{ {
public: public:
using id_base = ppu_thread; static const u32 id_base = 0x01000000; // TODO (used to determine thread type)
static const u32 id_step = 1;
static constexpr u32 id_min = 0x70000000; // TODO (used to determine thread type) static const u32 id_count = 65535;
static constexpr u32 id_max = 0x7fffffff;
virtual std::string get_name() const override; virtual std::string get_name() const override;
virtual std::string dump() const override; virtual std::string dump() const override;

View File

@ -7,12 +7,9 @@ class RawSPUThread final : public SPUThread
void cpu_task() override; void cpu_task() override;
public: public:
/* IdManager setups */ static const u32 id_base = 0;
static const u32 id_step = 1;
using id_base = RawSPUThread; static const u32 id_count = 5;
static constexpr u32 id_min = 0;
static constexpr u32 id_max = 4;
void on_init(const std::shared_ptr<void>&) override; void on_init(const std::shared_ptr<void>&) override;

View File

@ -238,7 +238,7 @@ SPUThread::~SPUThread()
} }
SPUThread::SPUThread(const std::string& name) SPUThread::SPUThread(const std::string& name)
: cpu_thread() : cpu_thread(idm::last_id())
, m_name(name) , m_name(name)
, index(0) , index(0)
, offset(0) , offset(0)
@ -246,7 +246,7 @@ SPUThread::SPUThread(const std::string& name)
} }
SPUThread::SPUThread(const std::string& name, u32 index) SPUThread::SPUThread(const std::string& name, u32 index)
: cpu_thread() : cpu_thread(idm::last_id())
, m_name(name) , m_name(name)
, index(index) , index(index)
, offset(verify("SPU LS" HERE, vm::alloc(0x40000, vm::main))) , offset(verify("SPU LS" HERE, vm::alloc(0x40000, vm::main)))

View File

@ -501,6 +501,10 @@ protected:
SPUThread(const std::string& name); SPUThread(const std::string& name);
public: public:
static const u32 id_base = 0x02000000; // TODO (used to determine thread type)
static const u32 id_step = 1;
static const u32 id_count = 65535;
SPUThread(const std::string& name, u32 index); SPUThread(const std::string& name, u32 index);
std::array<v128, 128> gpr; // General-Purpose Registers std::array<v128, 128> gpr; // General-Purpose Registers

View File

@ -19,6 +19,10 @@ struct sys_cond_attribute_t
struct lv2_cond_t struct lv2_cond_t
{ {
static const u32 id_base = 0x86000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u64 name; const u64 name;
const std::shared_ptr<lv2_mutex_t> mutex; // associated mutex const std::shared_ptr<lv2_mutex_t> mutex; // associated mutex

View File

@ -18,20 +18,25 @@ extern u64 get_system_time();
std::shared_ptr<lv2_event_queue_t> lv2_event_queue_t::make(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size) std::shared_ptr<lv2_event_queue_t> lv2_event_queue_t::make(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size)
{ {
auto queue = std::make_shared<lv2_event_queue_t>(protocol, type, name, ipc_key, size); std::shared_ptr<lv2_event_queue_t> result;
auto make_expr = [&] { return idm::import<lv2_event_queue_t>([&] { return queue; }); }; auto make_expr = [&]() -> const std::shared_ptr<lv2_event_queue_t>&
{
result = idm::make_ptr<lv2_event_queue_t>(protocol, type, name, ipc_key, size);
return result;
};
if (ipc_key == SYS_EVENT_QUEUE_LOCAL) if (ipc_key == SYS_EVENT_QUEUE_LOCAL)
{ {
// Not an IPC queue // Not an IPC queue
return make_expr(); make_expr();
return result;
} }
// IPC queue // IPC queue
if (ipc_manager<lv2_event_queue_t, u64>::add(ipc_key, make_expr)) if (ipc_manager<lv2_event_queue_t, u64>::add(ipc_key, make_expr))
{ {
return queue; return result;
} }
return nullptr; return nullptr;
@ -48,6 +53,16 @@ std::shared_ptr<lv2_event_queue_t> lv2_event_queue_t::find(u64 ipc_key)
return ipc_manager<lv2_event_queue_t, u64>::get(ipc_key); return ipc_manager<lv2_event_queue_t, u64>::get(ipc_key);
} }
lv2_event_queue_t::lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size)
: protocol(protocol)
, type(type)
, name(name)
, ipc_key(ipc_key)
, size(size)
, id(idm::last_id())
{
}
void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3) void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3)
{ {
verify(HERE), m_sq.empty() || m_events.empty(); verify(HERE), m_sq.empty() || m_events.empty();
@ -61,7 +76,7 @@ void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 d
// notify waiter; protocol is ignored in current implementation // notify waiter; protocol is ignored in current implementation
auto& thread = m_sq.front(); auto& thread = m_sq.front();
if (type == SYS_PPU_QUEUE && thread->id >= ppu_thread::id_min) if (type == SYS_PPU_QUEUE && thread->id_type() == 1)
{ {
// store event data in registers // store event data in registers
auto& ppu = static_cast<ppu_thread&>(*thread); auto& ppu = static_cast<ppu_thread&>(*thread);
@ -71,7 +86,7 @@ void lv2_event_queue_t::push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 d
ppu.gpr[6] = data2; ppu.gpr[6] = data2;
ppu.gpr[7] = data3; ppu.gpr[7] = data3;
} }
else if (type == SYS_SPU_QUEUE && thread->id < ppu_thread::id_min) else if (type == SYS_SPU_QUEUE && thread->id_type() != 1)
{ {
// store event data in In_MBox // store event data in In_MBox
auto& spu = static_cast<SPUThread&>(*thread); auto& spu = static_cast<SPUThread&>(*thread);
@ -162,11 +177,11 @@ s32 sys_event_queue_destroy(u32 equeue_id, s32 mode)
// signal all threads to return CELL_ECANCELED // signal all threads to return CELL_ECANCELED
for (auto& thread : queue->thread_queue(lv2_lock)) for (auto& thread : queue->thread_queue(lv2_lock))
{ {
if (queue->type == SYS_PPU_QUEUE && thread->id >= ppu_thread::id_min) if (queue->type == SYS_PPU_QUEUE && thread->id_type() == 1)
{ {
static_cast<ppu_thread&>(*thread).gpr[3] = 1; static_cast<ppu_thread&>(*thread).gpr[3] = 1;
} }
else if (queue->type == SYS_SPU_QUEUE && thread->id < ppu_thread::id_min) else if (queue->type == SYS_SPU_QUEUE && thread->id_type() != 1)
{ {
static_cast<SPUThread&>(*thread).ch_in_mbox.set_values(1, CELL_ECANCELED); static_cast<SPUThread&>(*thread).ch_in_mbox.set_values(1, CELL_ECANCELED);
} }

View File

@ -73,6 +73,10 @@ class lv2_event_queue_t final
sleep_queue<cpu_thread> m_sq; sleep_queue<cpu_thread> m_sq;
public: public:
static const u32 id_base = 0x8d000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
// Try to make an event queue with specified global key // Try to make an event queue with specified global key
static std::shared_ptr<lv2_event_queue_t> make(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size); static std::shared_ptr<lv2_event_queue_t> make(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size);
@ -84,17 +88,9 @@ public:
const u64 name; const u64 name;
const u64 ipc_key; const u64 ipc_key;
const s32 size; const s32 size;
const u32 id;
const id_value<> id{}; lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size);
lv2_event_queue_t(u32 protocol, s32 type, u64 name, u64 ipc_key, s32 size)
: protocol(protocol)
, type(type)
, name(name)
, ipc_key(ipc_key)
, size(size)
{
}
// Send an event // Send an event
void push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3); void push(lv2_lock_t, u64 source, u64 data1, u64 data2, u64 data3);
@ -120,6 +116,10 @@ public:
struct lv2_event_port_t struct lv2_event_port_t
{ {
static const u32 id_base = 0x0e000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const s32 type; // port type, must be SYS_EVENT_PORT_LOCAL const s32 type; // port type, must be SYS_EVENT_PORT_LOCAL
const u64 name; // passed as event source (generated from id and process id if not set) const u64 name; // passed as event source (generated from id and process id if not set)

View File

@ -31,6 +31,10 @@ struct sys_event_flag_attribute_t
struct lv2_event_flag_t struct lv2_event_flag_t
{ {
static const u32 id_base = 0x98000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 protocol; const u32 protocol;
const s32 type; const s32 type;
const u64 name; const u64 name;

View File

@ -96,19 +96,18 @@ struct lv2_fs_mount_point;
struct lv2_fs_object struct lv2_fs_object
{ {
// ID Manager setups static const u32 id_base = 3;
using id_base = lv2_fs_object; static const u32 id_step = 1;
static const u32 id_count = 255 - id_base;
static constexpr u32 id_min = 3; const u32 id;
static constexpr u32 id_max = 255;
const id_value<> id{};
// Mount Point // Mount Point
const std::add_pointer_t<lv2_fs_mount_point> mp; const std::add_pointer_t<lv2_fs_mount_point> mp;
lv2_fs_object(lv2_fs_mount_point* mp) lv2_fs_object(lv2_fs_mount_point* mp)
: mp(mp) : mp(mp)
, id(idm::last_id())
{ {
} }

View File

@ -10,6 +10,14 @@
logs::channel sys_interrupt("sys_interrupt", logs::level::notice); logs::channel sys_interrupt("sys_interrupt", logs::level::notice);
lv2_int_serv_t::lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2)
: thread(thread)
, arg1(arg1)
, arg2(arg2)
, id(idm::last_id())
{
}
void lv2_int_serv_t::exec() void lv2_int_serv_t::exec()
{ {
thread->cmd_list thread->cmd_list
@ -149,3 +157,8 @@ void sys_interrupt_thread_eoi(ppu_thread& ppu) // Low-level PPU function example
throw cpu_flag::ret; throw cpu_flag::ret;
} }
} }
lv2_int_tag_t::lv2_int_tag_t()
: id(idm::last_id())
{
}

View File

@ -6,26 +6,31 @@ class ppu_thread;
struct lv2_int_tag_t struct lv2_int_tag_t
{ {
const id_value<> id{}; static const u32 id_base = 0x1000a;
static const u32 id_step = 0x10000;
static const u32 id_count = 8192;
const u32 id;
std::shared_ptr<struct lv2_int_serv_t> handler; std::shared_ptr<struct lv2_int_serv_t> handler;
lv2_int_tag_t();
}; };
struct lv2_int_serv_t struct lv2_int_serv_t
{ {
static const u32 id_base = 0x0b000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const std::shared_ptr<ppu_thread> thread; const std::shared_ptr<ppu_thread> thread;
const id_value<> id{}; const u32 id;
const u64 arg1; const u64 arg1;
const u64 arg2; const u64 arg2;
lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2) lv2_int_serv_t(const std::shared_ptr<ppu_thread>& thread, u64 arg1, u64 arg2);
: thread(thread)
, arg1(arg1)
, arg2(arg2)
{
}
void exec(); void exec();
void join(ppu_thread& ppu, lv2_lock_t); void join(ppu_thread& ppu, lv2_lock_t);

View File

@ -19,6 +19,10 @@ struct sys_lwcond_t
struct lv2_lwcond_t struct lv2_lwcond_t
{ {
static const u32 id_base = 0x97000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u64 name; const u64 name;
sleep_queue<cpu_thread> sq; sleep_queue<cpu_thread> sq;

View File

@ -46,6 +46,10 @@ struct sys_lwmutex_t
struct lv2_lwmutex_t struct lv2_lwmutex_t
{ {
static const u32 id_base = 0x95000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 protocol; const u32 protocol;
const u64 name; const u64 name;

View File

@ -46,6 +46,10 @@ struct sys_page_attr_t
struct lv2_memory_container struct lv2_memory_container
{ {
static const u32 id_base = 0x1; // Wrong?
static const u32 id_step = 0x1;
static const u32 id_count = 16;
const u32 size = 0x10000000; // Amount of "physical" memory in this container const u32 size = 0x10000000; // Amount of "physical" memory in this container
atomic_t<u32> used{}; // Amount of "physical" memory currently used atomic_t<u32> used{}; // Amount of "physical" memory currently used

View File

@ -4,6 +4,10 @@
struct lv2_memory struct lv2_memory
{ {
static const u32 id_base = 0x08000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 size; // Memory size const u32 size; // Memory size
const u32 align; // Alignment required const u32 align; // Alignment required
const u64 flags; const u64 flags;

View File

@ -21,6 +21,10 @@ struct sys_mutex_attribute_t
struct lv2_mutex_t struct lv2_mutex_t
{ {
static const u32 id_base = 0x85000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const bool recursive; const bool recursive;
const u32 protocol; const u32 protocol;
const u64 name; const u64 name;

View File

@ -229,3 +229,8 @@ s32 sys_prx_stop()
sys_prx.todo("sys_prx_stop()"); sys_prx.todo("sys_prx_stop()");
return CELL_OK; return CELL_OK;
} }
lv2_prx_t::lv2_prx_t()
: id(idm::last_id())
{
}

View File

@ -76,7 +76,11 @@ struct sys_prx_get_module_list_t
struct lv2_prx_t struct lv2_prx_t
{ {
const id_value<> id{}; static const u32 id_base = 0x23000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 id;
bool is_started = false; bool is_started = false;
@ -86,6 +90,8 @@ struct lv2_prx_t
vm::ptr<s32(int argc, vm::ptr<void> argv)> start = vm::null; vm::ptr<s32(int argc, vm::ptr<void> argv)> start = vm::null;
vm::ptr<s32(int argc, vm::ptr<void> argv)> stop = vm::null; vm::ptr<s32(int argc, vm::ptr<void> argv)> stop = vm::null;
vm::ptr<s32()> exit = vm::null; vm::ptr<s32()> exit = vm::null;
lv2_prx_t();
}; };
// SysCalls // SysCalls

View File

@ -19,6 +19,10 @@ struct sys_rwlock_attribute_t
struct lv2_rwlock_t struct lv2_rwlock_t
{ {
static const u32 id_base = 0x88000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u64 name; const u64 name;
const u32 protocol; const u32 protocol;

View File

@ -19,6 +19,10 @@ struct sys_semaphore_attribute_t
struct lv2_sema_t struct lv2_sema_t
{ {
static const u32 id_base = 0x96000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
const u32 protocol; const u32 protocol;
const s32 max; const s32 max;
const u64 name; const u64 name;

View File

@ -139,6 +139,10 @@ class SPUThread;
struct lv2_spu_group_t struct lv2_spu_group_t
{ {
static const u32 id_base = 1; // Wrong?
static const u32 id_step = 1;
static const u32 id_count = 8192;
const std::string name; const std::string name;
const u32 num; // SPU Number const u32 num; // SPU Number
const s32 type; // SPU Thread Group Type const s32 type; // SPU Thread Group Type

View File

@ -24,11 +24,15 @@ class lv2_timer_t final : public named_thread
void on_task() override; void on_task() override;
public: public:
static const u32 id_base = 0x11000000;
static const u32 id_step = 0x100;
static const u32 id_count = 8192;
std::string get_name() const override; std::string get_name() const override;
void on_stop() override; void on_stop() override;
const id_value<> id{}; const u32 id = idm::last_id();
atomic_t<u32> state{ SYS_TIMER_STATE_RUN }; // Timer state atomic_t<u32> state{ SYS_TIMER_STATE_RUN }; // Timer state

View File

@ -1,12 +1,11 @@
#include "stdafx.h" #include "stdafx.h"
#include "IdManager.h" #include "IdManager.h"
DECLARE(idm::g_map); shared_mutex id_manager::g_mutex;
DECLARE(idm::g_id);
DECLARE(idm::g_mutex);
DECLARE(fxm::g_map); thread_local DECLARE(idm::g_id);
DECLARE(fxm::g_mutex); DECLARE(idm::g_map);
DECLARE(fxm::g_vec);
std::vector<id_manager::typeinfo>& id_manager::typeinfo::access() std::vector<id_manager::typeinfo>& id_manager::typeinfo::access()
{ {
@ -24,20 +23,40 @@ 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 type, u32 min, u32 max) id_manager::id_map::pointer idm::allocate_id(std::pair<u32, u32> types, u32 base, u32 step, u32 count)
{ {
// Check all IDs starting from "next id" auto& map = g_map[types.first];
for (u32 i = 0; i <= max - min; i++)
// Assume next ID
u32 next = base;
if (std::size_t _count = map.size())
{ {
// Fix current ID (wrap around) if (_count >= count)
if (g_id[tag] < min || g_id[tag] > max) g_id[tag] = min;
// Get ID
const auto r = g_map[tag].emplace(id_manager::id_key{g_id[tag]++, type}, nullptr);
if (r.second)
{ {
return &*r.first; return nullptr;
}
const u32 _next = map.rbegin()->first.id() + step;
if (_next > base && _next < base + step * count)
{
next = _next;
}
}
// Check all IDs starting from "next id" (TODO)
for (next; next < base + step * count; next += step)
{
// Get ID
const auto result = map.emplace(id_manager::id_key(next, types.second), nullptr);
if (result.second)
{
// Acknowledge the ID
g_id = next;
return std::addressof(*result.first);
} }
} }
@ -45,47 +64,61 @@ id_manager::id_map::pointer idm::allocate_id(u32 tag, u32 type, u32 min, u32 max
return nullptr; return nullptr;
} }
std::shared_ptr<void> idm::deallocate_id(u32 tag, u32 id) id_manager::id_map::pointer idm::find_id(u32 type, u32 id)
{ {
const auto found = g_map[tag].find(id); auto& map = g_map[type];
if (found == g_map[tag].end()) return nullptr; const auto found = map.find(id);
auto ptr = std::move(found->second); return found == map.end() ? nullptr : std::addressof(*found);
g_map[tag].erase(found);
return ptr;
} }
id_manager::id_map::pointer idm::find_id(u32 type, u32 true_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); auto& map = g_map[type];
if (found == g_map[type].end()) return nullptr; const auto found = map.find(id);
if (true_type != get_type<void>() && found->first.type() != true_type) return nullptr; return found == map.end() || found->first.type() != true_type ? nullptr : std::addressof(*found);
return &*found;
} }
std::shared_ptr<void> idm::delete_id(u32 type, u32 true_type, u32 tag, u32 id) std::shared_ptr<void> idm::delete_id(u32 type, u32 id)
{ {
writer_lock lock(g_mutex); auto& map = g_map[type];
if (!find_id(type, true_type, id)) return nullptr; // ??? const auto found = map.find(id);
auto&& ptr = deallocate_id(tag, id); std::shared_ptr<void> result;
g_map[type].erase(id); if (found != map.end())
{
result = std::move(found->second);
map.erase(found);
}
return ptr; return result;
}
std::shared_ptr<void> idm::delete_id(u32 type, u32 true_type, u32 id)
{
auto& map = g_map[type];
const auto found = map.find(id);
std::shared_ptr<void> result;
if (found != map.end() && found->first.type() == true_type)
{
result = std::move(found->second);
map.erase(found);
}
return result;
} }
void idm::init() void idm::init()
{ {
g_map.resize(id_manager::typeinfo::get().size(), {}); g_map.resize(id_manager::typeinfo::get().size());
g_id.resize(id_manager::typeinfo::get().size(), 0);
} }
void idm::clear() void idm::clear()
@ -101,32 +134,24 @@ void idm::clear()
} }
g_map[i].clear(); g_map[i].clear();
g_id[i] = 0;
} }
} }
std::shared_ptr<void> fxm::remove(u32 type)
{
writer_lock lock(g_mutex);
return std::move(g_map[type]);
}
void fxm::init() void fxm::init()
{ {
g_map.resize(id_manager::typeinfo::get().size(), {}); g_vec.resize(id_manager::typeinfo::get().size(), {});
} }
void fxm::clear() void fxm::clear()
{ {
// Call recorded finalization functions for all IDs // Call recorded finalization functions for all IDs
for (std::size_t i = 0; i < g_map.size(); i++) for (std::size_t i = 0; i < g_vec.size(); i++)
{ {
if (g_map[i]) if (g_vec[i])
{ {
id_manager::typeinfo::get()[i].on_stop(g_map[i].get()); id_manager::typeinfo::get()[i].on_stop(g_vec[i].get());
} }
g_map[i].reset(); g_vec[i].reset();
} }
} }

View File

@ -5,28 +5,35 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <unordered_map> #include <map>
// Mostly helper namespace // idm/fxm: helper namespace
namespace id_manager namespace id_manager
{ {
// Common global mutex
extern shared_mutex g_mutex;
// Optional ID traits // Optional ID traits
template<typename T, typename = void> template<typename T, typename = void>
struct id_traits struct id_traits
{ {
using tag = void; static_assert(sizeof(T) == 0, "ID object must specify: id_base, id_step, id_count");
static constexpr u32 min = 1; static const u32 base = 1; // First ID (N = 0)
static constexpr u32 max = 0x7fffffff; static const u32 step = 1; // Any ID: N * id_step + id_base
static const u32 count = 65535; // Limit: N < id_count
static const u32 invalid = 0;
}; };
template<typename T> template<typename T>
struct id_traits<T, void_t<typename T::id_base, decltype(&T::id_min), decltype(&T::id_max)>> struct id_traits<T, void_t<decltype(&T::id_base), decltype(&T::id_step), decltype(&T::id_count)>>
{ {
using tag = typename T::id_base; static const u32 base = T::id_base;
static const u32 step = T::id_step;
static const u32 count = T::id_count;
static const u32 invalid = base > 0 ? 0 : -1;
static constexpr u32 min = T::id_min; static_assert(u64{step} * count + base < UINT32_MAX, "ID traits: invalid object range");
static constexpr u32 max = T::id_max;
}; };
// Optional object initialization function (called after ID registration) // Optional object initialization function (called after ID registration)
@ -136,69 +143,30 @@ namespace id_manager
return m_type; return m_type;
} }
bool operator ==(const id_key& rhs) const operator u32() const
{ {
return m_value == rhs.m_value; return m_value;
}
bool operator !=(const id_key& rhs) const
{
return m_value != rhs.m_value;
} }
}; };
// Custom hasher for ID values using id_map = std::map<id_key, std::shared_ptr<void>>;
struct id_hash final
{
std::size_t operator ()(const id_key& key) const
{
return key.id();
}
};
using id_map = std::unordered_map<id_key, std::shared_ptr<void>, id_hash>;
} }
// Object manager for emulated process. Multiple objects of specified arbitrary type are given unique IDs. // Object manager for emulated process. Multiple objects of specified arbitrary type are given unique IDs.
class idm class idm
{ {
// Rules for ID allocation: // Last allocated ID for constructors
// 0) Individual ID counter may be specified for each type by defining 'using id_base = ...;' static thread_local u32 g_id;
// 1) If no id_base specified, void is assumed.
// 2) g_id[id_base] indicates next ID allocated in g_map.
// 3) g_map[id_base] contains the additional copy of object pointer.
static shared_mutex g_mutex;
// Type Index -> ID -> Object. Use global since only one process is supported atm. // Type Index -> ID -> Object. Use global since only one process is supported atm.
static std::vector<id_manager::id_map> g_map; static std::vector<id_manager::id_map> g_map;
// Next ID for each category
static std::vector<u32> g_id;
template<typename T> template<typename T>
static inline u32 get_type() static inline u32 get_type()
{ {
return id_manager::typeinfo::get_index<T>(); return id_manager::typeinfo::get_index<T>();
} }
template<typename T>
static inline u32 get_tag()
{
return get_type<typename id_manager::id_traits<T>::tag>();
}
// Update optional ID storage
template<typename T>
static inline auto set_id_value(T* ptr, u32 id) -> decltype(static_cast<void>(std::declval<T&>().id))
{
ptr->id = id;
}
static inline void set_id_value(...)
{
}
// Helper // Helper
template<typename F> template<typename F>
struct function_traits; struct function_traits;
@ -262,35 +230,44 @@ class idm
}; };
// Prepare new ID (returns nullptr if out of resources) // Prepare new ID (returns nullptr if out of resources)
static id_manager::id_map::pointer allocate_id(u32 tag, u32 type, u32 min, u32 max); static id_manager::id_map::pointer allocate_id(std::pair<u32, u32> types, u32 base, u32 step, u32 count);
// Deallocate ID, returns object // Remove ID and return the object
static std::shared_ptr<void> deallocate_id(u32 tag, u32 id); static std::shared_ptr<void> delete_id(u32 type, u32 id);
// Remove ID and return the object (check type)
static std::shared_ptr<void> delete_id(u32 type, u32 true_type, u32 id);
// Get ID
static id_manager::id_map::pointer find_id(u32 type, u32 id);
// Get ID (check type)
static id_manager::id_map::pointer find_id(u32 type, u32 true_type, u32 id);
// Allocate new ID and assign the object from the provider() // Allocate new ID and assign the object from the provider()
template<typename T, typename Set, typename F> template<typename T, typename Type, typename F>
static id_manager::id_map::pointer create_id(F&& provider) static id_manager::id_map::pointer create_id(F&& provider)
{ {
writer_lock lock(id_manager::g_mutex);
// Register destructors
id_manager::typeinfo::update<T>(); id_manager::typeinfo::update<T>();
id_manager::typeinfo::update<typename id_manager::id_traits<T>::tag>();
writer_lock lock(g_mutex); // Type IDs
std::pair<u32, u32> types(get_type<T>(), get_type<Type>());
if (auto place = allocate_id(get_tag<T>(), get_type<Set>(), id_manager::id_traits<T>::min, id_manager::id_traits<T>::max)) // Allocate new id
if (auto* place = allocate_id(types, id_manager::id_traits<T>::base, id_manager::id_traits<T>::step, id_manager::id_traits<T>::count))
{ {
try try
{ {
// Get object, store it // Get object, store it
place->second = provider(); place->second = provider();
return place;
// Update ID value if required
set_id_value(static_cast<T*>(place->second.get()), place->first.id());
return &*g_map[get_type<T>()].emplace(*place).first;
} }
catch (...) catch (...)
{ {
deallocate_id(get_tag<T>(), place->first.id()); delete_id(types.first, place->first.id());
throw; throw;
} }
} }
@ -298,12 +275,6 @@ class idm
return nullptr; return nullptr;
} }
// Get ID (internal)
static id_manager::id_map::pointer find_id(u32 type, u32 true_type, u32 id);
// Remove ID and return the object
static std::shared_ptr<void> delete_id(u32 type, u32 true_type, u32 tag, u32 id);
public: public:
// Initialize object manager // Initialize object manager
static void init(); static void init();
@ -311,6 +282,12 @@ public:
// Remove all objects // Remove all objects
static void clear(); static void clear();
// Get last ID
static inline u32 last_id()
{
return g_id;
}
// 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<Make>> make_ptr(Args&&... args) static inline std::enable_if_t<std::is_constructible<Make, Args...>::value, std::shared_ptr<Make>> make_ptr(Args&&... args)
@ -336,7 +313,7 @@ public:
return pair->first.id(); return pair->first.id();
} }
fmt::throw_exception("Out of IDs ('%s')" HERE, typeid(T).name()); return id_manager::id_traits<T>::invalid;
} }
// Add a new ID for an existing object provided (returns new id) // Add a new ID for an existing object provided (returns new id)
@ -350,7 +327,7 @@ public:
return pair->first.id(); return pair->first.id();
} }
fmt::throw_exception("Out of IDs ('%s')" HERE, typeid(T).name()); return id_manager::id_traits<T>::invalid;
} }
// Add a new ID for an object returned by provider() // Add a new ID for an object returned by provider()
@ -368,21 +345,19 @@ public:
} }
// Check the ID // Check the ID
template<typename T, typename Get = void> template<typename T, typename Get = T>
static inline explicit_bool_t check(u32 id) static inline explicit_bool_t check(u32 id)
{ {
reader_lock lock(g_mutex); reader_lock lock(id_manager::g_mutex);
return find_id(get_type<T>(), get_type<Get>(), id) != nullptr; return find_id(get_type<T>(), get_type<Get>(), id) != nullptr;
} }
// Check the ID, access object under shared lock // Check the ID, access object under shared lock
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>> template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
static inline explicit_bool_t check(u32 id, F&& func, int = 0) static inline explicit_bool_t check(u32 id, F&& func, int = 0)
{ {
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>; reader_lock lock(id_manager::g_mutex);
reader_lock lock(g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -391,17 +366,15 @@ public:
return false; return false;
} }
func(*static_cast<pointer_type*>(found->second.get())); func(*static_cast<Get*>(found->second.get()));
return true; return true;
} }
// Check the ID, access object under reader lock, propagate return value // Check the ID, access object under reader lock, propagate return value
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>> template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline return_pair<bool, FRT> check(u32 id, F&& func) static inline return_pair<bool, FRT> check(u32 id, F&& func)
{ {
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>; reader_lock lock(id_manager::g_mutex);
reader_lock lock(g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -410,14 +383,14 @@ public:
return {false}; return {false};
} }
return {true, func(*static_cast<pointer_type*>(found->second.get()))}; return {true, func(*static_cast<Get*>(found->second.get()))};
} }
// Get the object // Get the object
template<typename T, typename Get = void, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>> template<typename T, typename Get = T, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>>
static inline std::shared_ptr<Made> get(u32 id) static inline std::shared_ptr<Made> get(u32 id)
{ {
reader_lock lock(g_mutex); reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -430,13 +403,12 @@ public:
} }
// Get the object, access object under reader lock // Get the object, access object under reader lock
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>> template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
static inline auto get(u32 id, F&& func, int = 0) static inline auto get(u32 id, F&& func, int = 0)
{ {
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>; using result_type = std::shared_ptr<Get>;
using result_type = std::shared_ptr<pointer_type>;
reader_lock lock(g_mutex); reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -445,7 +417,7 @@ public:
return result_type{nullptr}; return result_type{nullptr};
} }
const auto ptr = static_cast<pointer_type*>(found->second.get()); const auto ptr = static_cast<Get*>(found->second.get());
func(*ptr); func(*ptr);
@ -453,13 +425,12 @@ public:
} }
// Get the object, access object under reader lock, propagate return value // Get the object, access object under reader lock, propagate return value
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>> template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline auto get(u32 id, F&& func) static inline auto get(u32 id, F&& func)
{ {
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>; using result_type = return_pair<Get, FRT>;
using result_type = return_pair<pointer_type, FRT>;
reader_lock lock(g_mutex); reader_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -468,7 +439,7 @@ public:
return result_type{nullptr}; return result_type{nullptr};
} }
const auto ptr = static_cast<pointer_type*>(found->second.get()); const auto ptr = static_cast<Get*>(found->second.get());
return result_type{{found->second, ptr}, func(*ptr)}; return result_type{{found->second, ptr}, func(*ptr)};
} }
@ -477,7 +448,7 @@ public:
template<typename... Types, typename F, typename FT = decltype(&std::decay_t<F>::operator()), typename FRT = typename function_traits<FT>::void_type> template<typename... Types, typename F, typename FT = decltype(&std::decay_t<F>::operator()), typename FRT = typename function_traits<FT>::void_type>
static inline u32 select(F&& func, int = 0) static inline u32 select(F&& func, int = 0)
{ {
reader_lock lock(g_mutex); reader_lock lock(id_manager::g_mutex);
u32 result = 0; u32 result = 0;
@ -500,7 +471,7 @@ public:
using object_type = typename function_traits<FT>::object_type; using object_type = typename function_traits<FT>::object_type;
using result_type = return_pair<object_type, FRT>; using result_type = return_pair<object_type, FRT>;
reader_lock lock(g_mutex); reader_lock lock(id_manager::g_mutex);
for (u32 type : { get_type<Types>()... }) for (u32 type : { get_type<Types>()... })
{ {
@ -517,10 +488,10 @@ public:
} }
// Get count of objects // Get count of objects
template<typename T, typename Get = void> template<typename T, typename Get = T>
static inline u32 get_count() static inline u32 get_count()
{ {
reader_lock lock(g_mutex); reader_lock lock(id_manager::g_mutex);
if (std::is_void<Get>::value) if (std::is_void<Get>::value)
{ {
@ -541,10 +512,10 @@ public:
} }
// Remove the ID // Remove the ID
template<typename T, typename Get = void> template<typename T, typename Get = T>
static inline explicit_bool_t remove(u32 id) static inline explicit_bool_t remove(u32 id)
{ {
auto ptr = delete_id(get_type<T>(), get_type<Get>(), get_tag<T>(), id); auto ptr = delete_id(get_type<T>(), get_type<Get>(), id);
if (LIKELY(ptr)) if (LIKELY(ptr))
{ {
@ -555,29 +526,28 @@ public:
} }
// Remove the ID and return the object // Remove the ID and return the object
template<typename T, typename Get = void, typename Made = std::conditional_t<std::is_void<Get>::value, T, Get>> template<typename T, typename Get = T>
static inline std::shared_ptr<Made> withdraw(u32 id) static inline std::shared_ptr<Get> withdraw(u32 id)
{ {
auto ptr = delete_id(get_type<T>(), get_type<Get>(), get_tag<T>(), id); auto ptr = delete_id(get_type<T>(), get_type<Get>(), 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<Made*>(ptr.get())}; return {ptr, static_cast<Get*>(ptr.get())};
} }
// Remove the ID after accessing the object under writer lock, return the object and propagate return value // Remove the ID after accessing the object under writer lock, return the object and propagate return value
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>> template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<std::is_void<FRT>::value>>
static inline auto withdraw(u32 id, F&& func, int = 0) static inline auto withdraw(u32 id, F&& func, int = 0)
{ {
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>; using result_type = std::shared_ptr<Get>;
using result_type = std::shared_ptr<pointer_type>;
std::shared_ptr<void> ptr; std::shared_ptr<void> ptr;
{ {
writer_lock lock(g_mutex); writer_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -586,29 +556,28 @@ public:
return result_type{nullptr}; return result_type{nullptr};
} }
func(*static_cast<pointer_type*>(found->second.get())); func(*static_cast<Get*>(found->second.get()));
ptr = deallocate_id(get_tag<T>(), id); ptr = delete_id(get_type<T>(), id);
g_map[get_type<T>()].erase(id); g_map[get_type<T>()].erase(id);
} }
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get())); id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
return result_type{ptr, static_cast<pointer_type*>(ptr.get())}; return result_type{ptr, static_cast<Get*>(ptr.get())};
} }
// Conditionally remove the ID (if return value evaluates to false) after accessing the object under writer lock, return the object and propagate return value // Conditionally remove the ID (if return value evaluates to false) after accessing the object under writer lock, return the object and propagate return value
template<typename T, typename Get = void, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>> template<typename T, typename Get = T, typename F, typename FRT = std::result_of_t<F(T&)>, typename = std::enable_if_t<!std::is_void<FRT>::value>>
static inline auto withdraw(u32 id, F&& func) static inline auto withdraw(u32 id, F&& func)
{ {
using pointer_type = std::conditional_t<std::is_void<Get>::value, T, Get>; using result_type = return_pair<Get, FRT>;
using result_type = return_pair<pointer_type, FRT>;
std::shared_ptr<void> ptr; std::shared_ptr<void> ptr;
FRT ret; FRT ret;
{ {
writer_lock lock(g_mutex); writer_lock lock(id_manager::g_mutex);
const auto found = find_id(get_type<T>(), get_type<Get>(), id); const auto found = find_id(get_type<T>(), get_type<Get>(), id);
@ -617,7 +586,7 @@ public:
return result_type{nullptr}; return result_type{nullptr};
} }
const auto _ptr = static_cast<pointer_type*>(found->second.get()); const auto _ptr = static_cast<Get*>(found->second.get());
ret = func(*_ptr); ret = func(*_ptr);
@ -626,14 +595,14 @@ public:
return result_type{{found->second, _ptr}, std::move(ret)}; return result_type{{found->second, _ptr}, std::move(ret)};
} }
ptr = deallocate_id(get_tag<T>(), id); ptr = delete_id(get_type<T>(), id);
g_map[get_type<T>()].erase(id); g_map[get_type<T>()].erase(id);
} }
id_manager::on_stop<T>::func(static_cast<T*>(ptr.get())); id_manager::on_stop<T>::func(static_cast<T*>(ptr.get()));
return result_type{{ptr, static_cast<pointer_type*>(ptr.get())}, std::move(ret)}; return result_type{{ptr, static_cast<Get*>(ptr.get())}, std::move(ret)};
} }
}; };
@ -641,9 +610,7 @@ public:
class fxm class fxm
{ {
// Type Index -> Object. Use global since only one process is supported atm. // Type Index -> Object. Use global since only one process is supported atm.
static std::vector<std::shared_ptr<void>> g_map; static std::vector<std::shared_ptr<void>> g_vec;
static shared_mutex g_mutex;
template<typename T> template<typename T>
static inline u32 get_type() static inline u32 get_type()
@ -651,8 +618,6 @@ class fxm
return id_manager::typeinfo::get_index<T>(); return id_manager::typeinfo::get_index<T>();
} }
static std::shared_ptr<void> remove(u32 type);
public: public:
// Initialize object manager // Initialize object manager
static void init(); static void init();
@ -668,13 +633,13 @@ public:
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
{ {
writer_lock lock(g_mutex); writer_lock lock(id_manager::g_mutex);
if (!g_map[get_type<T>()]) if (!g_vec[get_type<T>()])
{ {
ptr = std::make_shared<Make>(std::forward<Args>(args)...); ptr = std::make_shared<Make>(std::forward<Args>(args)...);
g_map[get_type<T>()] = ptr; g_vec[get_type<T>()] = ptr;
} }
} }
@ -696,12 +661,12 @@ public:
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
std::shared_ptr<void> old; std::shared_ptr<void> old;
{ {
writer_lock lock(g_mutex); writer_lock lock(id_manager::g_mutex);
old = std::move(g_map[get_type<T>()]); old = std::move(g_vec[get_type<T>()]);
ptr = std::make_shared<Make>(std::forward<Args>(args)...); ptr = std::make_shared<Make>(std::forward<Args>(args)...);
g_map[get_type<T>()] = ptr; g_vec[get_type<T>()] = ptr;
} }
if (old) if (old)
@ -721,13 +686,13 @@ public:
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
{ {
writer_lock lock(g_mutex); writer_lock lock(id_manager::g_mutex);
if (!g_map[get_type<T>()]) if (!g_vec[get_type<T>()])
{ {
ptr = provider(); ptr = provider();
g_map[get_type<T>()] = ptr; g_vec[get_type<T>()] = ptr;
} }
} }
@ -749,12 +714,12 @@ public:
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
std::shared_ptr<void> old; std::shared_ptr<void> old;
{ {
writer_lock lock(g_mutex); writer_lock lock(id_manager::g_mutex);
old = std::move(g_map[get_type<T>()]); old = std::move(g_vec[get_type<T>()]);
ptr = provider(); ptr = provider();
g_map[get_type<T>()] = ptr; g_vec[get_type<T>()] = ptr;
} }
if (old) if (old)
@ -774,9 +739,9 @@ public:
std::shared_ptr<T> ptr; std::shared_ptr<T> ptr;
{ {
writer_lock lock(g_mutex); writer_lock lock(id_manager::g_mutex);
if (auto& value = g_map[get_type<T>()]) if (auto& value = g_vec[get_type<T>()])
{ {
return{ value, static_cast<T*>(value.get()) }; return{ value, static_cast<T*>(value.get()) };
} }
@ -784,7 +749,7 @@ public:
{ {
ptr = std::make_shared<Make>(std::forward<Args>(args)...); ptr = std::make_shared<Make>(std::forward<Args>(args)...);
g_map[get_type<T>()] = ptr; g_vec[get_type<T>()] = ptr;
} }
} }
@ -797,18 +762,18 @@ public:
template<typename T> template<typename T>
static inline explicit_bool_t check() static inline explicit_bool_t check()
{ {
reader_lock lock(g_mutex); reader_lock lock(id_manager::g_mutex);
return g_map[get_type<T>()].operator bool(); return g_vec[get_type<T>()].operator bool();
} }
// Get the object (returns nullptr if it doesn't exist) // Get the object (returns nullptr if it doesn't exist)
template<typename T> template<typename T>
static inline std::shared_ptr<T> get() static inline std::shared_ptr<T> get()
{ {
reader_lock lock(g_mutex); reader_lock lock(id_manager::g_mutex);
auto& ptr = g_map[get_type<T>()]; auto& ptr = g_vec[get_type<T>()];
return{ ptr, static_cast<T*>(ptr.get()) }; return{ ptr, static_cast<T*>(ptr.get()) };
} }
@ -817,7 +782,11 @@ public:
template<typename T> template<typename T>
static inline explicit_bool_t remove() static inline explicit_bool_t remove()
{ {
auto ptr = remove(get_type<T>()); std::shared_ptr<void> ptr;
{
writer_lock lock(id_manager::g_mutex);
ptr = std::move(g_vec[get_type<T>()]);
}
if (ptr) if (ptr)
{ {
@ -831,7 +800,11 @@ public:
template<typename T> template<typename T>
static inline std::shared_ptr<T> withdraw() static inline std::shared_ptr<T> withdraw()
{ {
auto ptr = remove(get_type<T>()); std::shared_ptr<void> ptr;
{
writer_lock lock(id_manager::g_mutex);
ptr = std::move(g_vec[get_type<T>()]);
}
if (ptr) if (ptr)
{ {

View File

@ -1,5 +1,6 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/IdManager.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "ARMv7Thread.h" #include "ARMv7Thread.h"
@ -94,7 +95,7 @@ ARMv7Thread::~ARMv7Thread()
} }
ARMv7Thread::ARMv7Thread(const std::string& name, u32 prio, u32 stack) ARMv7Thread::ARMv7Thread(const std::string& name, u32 prio, u32 stack)
: cpu_thread() : cpu_thread(idm::last_id())
, m_name(name) , m_name(name)
, prio(prio) , prio(prio)
, stack_addr(vm::alloc(stack, vm::main)) , stack_addr(vm::alloc(stack, vm::main))

View File

@ -14,6 +14,10 @@ enum ARMv7InstructionSet
class ARMv7Thread final : public cpu_thread class ARMv7Thread final : public cpu_thread
{ {
public: public:
static const u32 id_base = 1;
static const u32 id_step = 2;
static const u32 id_count = 32767;
virtual std::string get_name() const override; virtual std::string get_name() const override;
virtual std::string dump() const override; virtual std::string dump() const override;
virtual void cpu_task() override; virtual void cpu_task() override;

View File

@ -808,6 +808,10 @@ s32 sceKernelWaitMultipleEventsCB(vm::ptr<SceKernelWaitEvent> pWaitEventList, s3
struct psp2_event_flag final struct psp2_event_flag final
{ {
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
struct alignas(8) ctrl_t struct alignas(8) ctrl_t
{ {
u32 waiters; u32 waiters;

View File

@ -496,6 +496,10 @@ struct SceKernelSemaInfo
struct psp2_semaphore struct psp2_semaphore
{ {
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const std::string name; // IPC Name const std::string name; // IPC Name
atomic_t<u32> ref{}; // IPC Ref Counter atomic_t<u32> ref{}; // IPC Ref Counter
@ -536,6 +540,10 @@ struct SceKernelMutexInfo
struct psp2_mutex struct psp2_mutex
{ {
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const std::string name; // IPC Name const std::string name; // IPC Name
atomic_t<u32> ref{}; // IPC Ref Counter atomic_t<u32> ref{}; // IPC Ref Counter
@ -596,6 +604,10 @@ struct SceKernelCondInfo
struct psp2_cond struct psp2_cond
{ {
static const u32 id_base = 1;
static const u32 id_step = 1;
static const u32 id_count = 32767;
const std::string name; // IPC Name const std::string name; // IPC Name
atomic_t<u32> ref{}; // IPC Ref Counter atomic_t<u32> ref{}; // IPC Ref Counter

View File

@ -481,7 +481,7 @@ s32 error_code::error_report(const fmt_type_info* sup, u64 arg)
if (auto thread = get_current_cpu_thread()) if (auto thread = get_current_cpu_thread())
{ {
if (g_system == system_type::ps3 && thread->id >= ppu_thread::id_min) if (g_system == system_type::ps3 && thread->id_type() == 1)
{ {
if (auto func = static_cast<ppu_thread*>(thread)->last_function) if (auto func = static_cast<ppu_thread*>(thread)->last_function)
{ {

View File

@ -61,7 +61,7 @@ InstructionEditorDialog::InstructionEditorDialog(wxPanel *parent, u32 _pc, cpu_t
s_panel_margin_x->Add(s_panel_margin_y); s_panel_margin_x->Add(s_panel_margin_y);
s_panel_margin_x->AddSpacer(12); s_panel_margin_x->AddSpacer(12);
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id < ppu_thread::id_min ? static_cast<SPUThread&>(*cpu).offset : 0; const u32 cpu_offset = g_system == system_type::ps3 && cpu->id_type() != 1 ? static_cast<SPUThread&>(*cpu).offset : 0;
this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview)); this->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(InstructionEditorDialog::updatePreview));
t2_instr->SetValue(wxString::Format("%08x", vm::ps3::read32(cpu_offset + pc).value())); t2_instr->SetValue(wxString::Format("%08x", vm::ps3::read32(cpu_offset + pc).value()));

View File

@ -25,7 +25,7 @@ u32 InterpreterDisAsmFrame::GetPc() const
{ {
switch (g_system) switch (g_system)
{ {
case system_type::ps3: return cpu->id >= ppu_thread::id_min ? static_cast<ppu_thread*>(cpu)->cia : static_cast<SPUThread*>(cpu)->pc; case system_type::ps3: return cpu->id_type() == 1 ? static_cast<ppu_thread*>(cpu)->cia : static_cast<SPUThread*>(cpu)->pc;
case system_type::psv: return static_cast<ARMv7Thread*>(cpu)->PC; case system_type::psv: return static_cast<ARMv7Thread*>(cpu)->PC;
} }
@ -140,7 +140,7 @@ void InterpreterDisAsmFrame::OnSelectUnit(wxCommandEvent& event)
{ {
case system_type::ps3: case system_type::ps3:
{ {
if (cpu->id >= ppu_thread::id_min) if (cpu->id_type() == 1)
{ {
m_disasm = std::make_unique<PPUDisAsm>(CPUDisAsm_InterpreterMode); m_disasm = std::make_unique<PPUDisAsm>(CPUDisAsm_InterpreterMode);
} }
@ -250,7 +250,7 @@ void InterpreterDisAsmFrame::ShowAddr(u32 addr)
} }
else else
{ {
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id < ppu_thread::id_min ? static_cast<SPUThread&>(*cpu).offset : 0; const u32 cpu_offset = g_system == system_type::ps3 && cpu->id_type() != 1 ? static_cast<SPUThread&>(*cpu).offset : 0;
m_disasm->offset = (u8*)vm::base(cpu_offset); m_disasm->offset = (u8*)vm::base(cpu_offset);
for (uint i = 0, count = 4; i<m_item_count; ++i, m_pc += count) for (uint i = 0, count = 4; i<m_item_count; ++i, m_pc += count)
{ {

View File

@ -58,7 +58,7 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
{ {
case system_type::ps3: case system_type::ps3:
{ {
if (_cpu->id >= ppu_thread::id_min) if (_cpu->id_type() == 1)
{ {
for (int i = 0; i < 32; i++) t1_register->Append(wxString::Format("GPR[%d]", i)); for (int i = 0; i < 32; i++) t1_register->Append(wxString::Format("GPR[%d]", i));
for (int i = 0; i < 32; i++) t1_register->Append(wxString::Format("FPR[%d]", i)); for (int i = 0; i < 32; i++) t1_register->Append(wxString::Format("FPR[%d]", i));
@ -89,7 +89,7 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
std::string reg = fmt::ToUTF8(t1_register->GetStringSelection()); std::string reg = fmt::ToUTF8(t1_register->GetStringSelection());
std::string value = fmt::ToUTF8(t2_value->GetValue()); std::string value = fmt::ToUTF8(t2_value->GetValue());
if (g_system == system_type::ps3 && cpu->id >= ppu_thread::id_min) if (g_system == system_type::ps3 && cpu->id_type() == 1)
{ {
auto& ppu = *static_cast<ppu_thread*>(cpu); auto& ppu = *static_cast<ppu_thread*>(cpu);
@ -134,7 +134,7 @@ RegisterEditorDialog::RegisterEditorDialog(wxPanel *parent, u32 _pc, cpu_thread*
{ {
} }
} }
else if (g_system == system_type::ps3 && cpu->id < ppu_thread::id_min) else if (g_system == system_type::ps3 && cpu->id_type() != 1)
{ {
auto& spu = *static_cast<SPUThread*>(cpu); auto& spu = *static_cast<SPUThread*>(cpu);
@ -169,7 +169,7 @@ void RegisterEditorDialog::updateRegister(wxCommandEvent& event)
std::string reg = fmt::ToUTF8(t1_register->GetStringSelection()); std::string reg = fmt::ToUTF8(t1_register->GetStringSelection());
std::string str; std::string str;
if (g_system == system_type::ps3 && cpu->id >= ppu_thread::id_min) if (g_system == system_type::ps3 && cpu->id_type() == 1)
{ {
auto& ppu = *static_cast<ppu_thread*>(cpu); auto& ppu = *static_cast<ppu_thread*>(cpu);
@ -185,7 +185,7 @@ void RegisterEditorDialog::updateRegister(wxCommandEvent& event)
if (reg == "LR") str = fmt::format("%016llx", ppu.lr); if (reg == "LR") str = fmt::format("%016llx", ppu.lr);
if (reg == "CTR") str = fmt::format("%016llx", ppu.ctr); if (reg == "CTR") str = fmt::format("%016llx", ppu.ctr);
} }
else if (g_system == system_type::ps3 && cpu->id < ppu_thread::id_min) else if (g_system == system_type::ps3 && cpu->id_type() != 1)
{ {
auto& spu = *static_cast<SPUThread*>(cpu); auto& spu = *static_cast<SPUThread*>(cpu);