diff --git a/rpcs3/Emu/Cell/lv2/sys_cond.cpp b/rpcs3/Emu/Cell/lv2/sys_cond.cpp index 4e10ddc6ff..f014cdd9a6 100644 --- a/rpcs3/Emu/Cell/lv2/sys_cond.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_cond.cpp @@ -9,8 +9,6 @@ LOG_CHANNEL(sys_cond); -template<> DECLARE(ipc_manager::g_ipc) {}; - error_code sys_cond_create(ppu_thread& ppu, vm::ptr cond_id, u32 mutex_id, vm::ptr attr) { ppu.state += cpu_flag::wait; @@ -58,7 +56,8 @@ error_code sys_cond_destroy(ppu_thread& ppu, u32 cond_id) return CELL_EBUSY; } - cond.mutex->obj_count.atomic_op([](lv2_mutex::count_info& info){ info.cond_count--; }); + cond.mutex->cond_count--; + lv2_obj::on_id_destroy(cond, cond.shared, cond.key); return {}; }); diff --git a/rpcs3/Emu/Cell/lv2/sys_cond.h b/rpcs3/Emu/Cell/lv2/sys_cond.h index 281694c512..db54536e36 100644 --- a/rpcs3/Emu/Cell/lv2/sys_cond.h +++ b/rpcs3/Emu/Cell/lv2/sys_cond.h @@ -40,20 +40,17 @@ struct lv2_cond final : lv2_obj { } - CellError on_id_create() const + CellError on_id_create() { - if (!mutex->obj_count.fetch_op([](lv2_mutex::count_info& info) + if (mutex->exists) { - if (info.mutex_count) - return info.cond_count++, true; - return false; - }).second) - { - // Mutex has been destroyed, cannot create conditional variable - return CELL_ESRCH; + mutex->cond_count++; + exists++; + return {}; } - return {}; + // Mutex has been destroyed, cannot create conditional variable + return CELL_ESRCH; } }; diff --git a/rpcs3/Emu/Cell/lv2/sys_event.cpp b/rpcs3/Emu/Cell/lv2/sys_event.cpp index 3de75991c4..79fbf15d21 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event.cpp @@ -11,8 +11,6 @@ LOG_CHANNEL(sys_event); -template<> DECLARE(ipc_manager::g_ipc) {}; - std::shared_ptr lv2_event_queue::find(u64 ipc_key) { if (ipc_key == SYS_EVENT_QUEUE_LOCAL) @@ -21,14 +19,7 @@ std::shared_ptr lv2_event_queue::find(u64 ipc_key) return {}; } - auto queue = ipc_manager::get(ipc_key); - - if (queue && !queue->exists) - { - queue.reset(); - } - - return queue; + return g_fxo->get>().get(ipc_key); } bool lv2_event_queue::check(const std::weak_ptr& wkptr) @@ -93,11 +84,11 @@ CellError lv2_event_queue::send(lv2_event event) return {}; } -error_code sys_event_queue_create(cpu_thread& cpu, vm::ptr equeue_id, vm::ptr attr, u64 event_queue_key, s32 size) +error_code sys_event_queue_create(cpu_thread& cpu, vm::ptr equeue_id, vm::ptr attr, u64 ipc_key, s32 size) { cpu.state += cpu_flag::wait; - sys_event.warning("sys_event_queue_create(equeue_id=*0x%x, attr=*0x%x, event_queue_key=0x%llx, size=%d)", equeue_id, attr, event_queue_key, size); + sys_event.warning("sys_event_queue_create(equeue_id=*0x%x, attr=*0x%x, ipc_key=0x%llx, size=%d)", equeue_id, attr, ipc_key, size); if (size <= 0 || size > 127) { @@ -120,42 +111,19 @@ error_code sys_event_queue_create(cpu_thread& cpu, vm::ptr equeue_id, vm::p return CELL_EINVAL; } - auto queue = std::make_shared(protocol, type, attr->name_u64, event_queue_key, size); + const u32 pshared = ipc_key == SYS_EVENT_QUEUE_LOCAL ? SYS_SYNC_NOT_PROCESS_SHARED : SYS_SYNC_NOT_PROCESS_SHARED; + constexpr u32 flags = SYS_SYNC_NEWLY_CREATED; // NOTE: This is inaccurate for multi-process + const u64 name = attr->name_u64; - CellError error = CELL_EAGAIN; - - if (event_queue_key == SYS_EVENT_QUEUE_LOCAL) + if (const auto error = lv2_obj::create(pshared, ipc_key, flags, [&]() { - // Not an IPC queue - if (const u32 _id = idm::import([&]() { if ((error = queue->on_id_create())) queue.reset(); return std::move(queue); } )) - { - *equeue_id = _id; - return CELL_OK; - } - - return error; - } - - // Create IPC queue - if (!ipc_manager::add(event_queue_key, [&]() -> std::shared_ptr - { - if (const u32 _id = idm::import([&]() { if ((error = queue->on_id_create())) return decltype(queue){}; return queue; } )) - { - *equeue_id = _id; - return std::move(queue); - } - - return nullptr; + return std::make_shared(protocol, type, name, ipc_key, size); })) - { - return CELL_EEXIST; - } - - if (queue) { return error; } + *equeue_id = idm::last_id(); return CELL_OK; } @@ -179,7 +147,7 @@ error_code sys_event_queue_destroy(ppu_thread& ppu, u32 equeue_id, s32 mode) return CELL_EBUSY; } - queue.exists--; + lv2_obj::on_id_destroy(queue, queue.key == SYS_EVENT_QUEUE_LOCAL ? SYS_SYNC_NOT_PROCESS_SHARED : SYS_SYNC_PROCESS_SHARED, queue.key); return {}; }); @@ -521,11 +489,11 @@ error_code sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3) const auto port = idm::get(eport_id, [&](lv2_event_port& port) -> CellError { - if (const auto queue = port.queue.lock(); lv2_event_queue::check(queue)) + if (lv2_event_queue::check(port.queue)) { const u64 source = port.name ? port.name : (s64{process_getpid()} << 32) | u64{eport_id}; - return queue->send(source, data1, data2, data3); + return port.queue->send(source, data1, data2, data3); } return CELL_ENOTCONN; diff --git a/rpcs3/Emu/Cell/lv2/sys_event.h b/rpcs3/Emu/Cell/lv2/sys_event.h index 31746a0e6f..0977079813 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event.h +++ b/rpcs3/Emu/Cell/lv2/sys_event.h @@ -86,7 +86,6 @@ struct lv2_event_queue final : public lv2_obj const u64 key; const s32 size; - atomic_t exists = 0; // Existence validation (workaround for shared-ptr ref-counting) shared_mutex mutex; std::deque events; std::deque sq; @@ -113,12 +112,6 @@ struct lv2_event_queue final : public lv2_obj // Check queue ptr validity (use 'exists' member) static bool check(const std::weak_ptr&); static bool check(const std::shared_ptr&); - - CellError on_id_create() - { - exists++; - return {}; - } }; struct lv2_event_port final : lv2_obj @@ -129,7 +122,7 @@ struct lv2_event_port final : lv2_obj const u64 name; // Event source (generated from id and process id if not set) u32 queue_id = 0; // Event queue ID (if IPC is used this value is meaningless) - std::weak_ptr queue; // Event queue this port is connected to + std::shared_ptr queue; // Event queue this port is connected to lv2_event_port(s32 type, u64 name) : type(type) diff --git a/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp b/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp index 3a216af861..fe46b684fe 100644 --- a/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_event_flag.cpp @@ -11,8 +11,6 @@ LOG_CHANNEL(sys_event_flag); -template<> DECLARE(ipc_manager::g_ipc) {}; - error_code sys_event_flag_create(ppu_thread& ppu, vm::ptr id, vm::ptr attr, u64 init) { ppu.state += cpu_flag::wait; @@ -73,6 +71,7 @@ error_code sys_event_flag_destroy(ppu_thread& ppu, u32 id) return CELL_EBUSY; } + lv2_obj::on_id_destroy(flag, flag.shared, flag.key); return {}; }); diff --git a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp index 5564d66615..94044f0802 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp @@ -12,10 +12,12 @@ LOG_CHANNEL(sys_mmapper); -lv2_memory::lv2_memory(u32 size, u32 align, u64 flags, lv2_memory_container* ct) +lv2_memory::lv2_memory(u32 size, u32 align, u64 flags, u64 key, u32 pshared, lv2_memory_container* ct) : size(size) , align(align) , flags(flags) + , key(key) + , pshared(pshared) , ct(ct) , shm(std::make_shared(size, 1 /* shareable flag */)) { @@ -25,17 +27,18 @@ lv2_memory::lv2_memory(u32 size, u32 align, u64 flags, lv2_memory_container* ct) #endif } -template<> DECLARE(ipc_manager::g_ipc) {}; - template error_code create_lv2_shm(bool pshared, u64 ipc_key, u64 size, u32 align, u64 flags, lv2_memory_container* ct) { - if (auto error = lv2_obj::create(pshared ? SYS_SYNC_PROCESS_SHARED : SYS_SYNC_NOT_PROCESS_SHARED, ipc_key, exclusive ? SYS_SYNC_NEWLY_CREATED : SYS_SYNC_NOT_CARE, [&]() + const u32 _pshared = pshared ? SYS_SYNC_PROCESS_SHARED : SYS_SYNC_NOT_PROCESS_SHARED; + if (auto error = lv2_obj::create(_pshared, ipc_key, exclusive ? SYS_SYNC_NEWLY_CREATED : SYS_SYNC_NOT_CARE, [&]() { return std::make_shared( static_cast(size), align, flags, + ipc_key, + _pshared, ct); }, false)) { @@ -525,6 +528,7 @@ error_code sys_mmapper_free_shared_memory(ppu_thread& ppu, u32 mem_id) return CELL_EBUSY; } + lv2_obj::on_id_destroy(mem, mem.pshared, mem.key); return {}; }); diff --git a/rpcs3/Emu/Cell/lv2/sys_mmapper.h b/rpcs3/Emu/Cell/lv2/sys_mmapper.h index 44ac477144..6829bc5645 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mmapper.h +++ b/rpcs3/Emu/Cell/lv2/sys_mmapper.h @@ -21,12 +21,14 @@ struct lv2_memory : lv2_obj const u32 size; // Memory size const u32 align; // Alignment required const u64 flags; + const u64 key; // IPC key + const u32 pshared; lv2_memory_container* const ct; // Associated memory container const std::shared_ptr shm; atomic_t counter{0}; - lv2_memory(u32 size, u32 align, u64 flags, lv2_memory_container* ct); + lv2_memory(u32 size, u32 align, u64 flags, u64 key, u32 pshared, lv2_memory_container* ct); }; enum : u64 diff --git a/rpcs3/Emu/Cell/lv2/sys_mutex.cpp b/rpcs3/Emu/Cell/lv2/sys_mutex.cpp index fb9a56776d..88459f2fde 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mutex.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mutex.cpp @@ -9,8 +9,6 @@ LOG_CHANNEL(sys_mutex); -template<> DECLARE(ipc_manager::g_ipc) {}; - error_code sys_mutex_create(ppu_thread& ppu, vm::ptr mutex_id, vm::ptr attr) { ppu.state += cpu_flag::wait; @@ -87,21 +85,12 @@ error_code sys_mutex_destroy(ppu_thread& ppu, u32 mutex_id) return CELL_EBUSY; } - if (!mutex.obj_count.fetch_op([](lv2_mutex::count_info& info) - { - if (info.cond_count) - { - return false; - } - - // Decrement mutex copies count - info.mutex_count--; - return true; - }).second) + if (mutex.cond_count) { return CELL_EPERM; } + lv2_obj::on_id_destroy(mutex, mutex.shared, mutex.key); return {}; }); diff --git a/rpcs3/Emu/Cell/lv2/sys_mutex.h b/rpcs3/Emu/Cell/lv2/sys_mutex.h index cb3b460ff6..580792fa1d 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mutex.h +++ b/rpcs3/Emu/Cell/lv2/sys_mutex.h @@ -32,16 +32,10 @@ struct lv2_mutex final : lv2_obj const u64 key; const u64 name; - struct alignas(8) count_info - { - u32 mutex_count; // Mutex copies count (0 means doesn't exist anymore) - u32 cond_count; // Condition Variables - }; - + u32 cond_count = 0; // Condition Variables shared_mutex mutex; atomic_t owner{0}; atomic_t lock_count{0}; // Recursive Locks - atomic_t obj_count{}; std::deque sq; lv2_mutex(u32 protocol, u32 recursive, u32 shared, u32 adaptive, u64 key, u64 name) @@ -54,12 +48,6 @@ struct lv2_mutex final : lv2_obj { } - CellError on_id_create() - { - obj_count.atomic_op([](count_info& info){ info.mutex_count++; }); - return {}; - } - CellError try_lock(u32 id) { const u32 value = owner; diff --git a/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp b/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp index 7140e73fe2..2356c507e4 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rwlock.cpp @@ -9,8 +9,6 @@ LOG_CHANNEL(sys_rwlock); -template<> DECLARE(ipc_manager::g_ipc) {}; - error_code sys_rwlock_create(ppu_thread& ppu, vm::ptr rw_lock_id, vm::ptr attr) { ppu.state += cpu_flag::wait; @@ -57,6 +55,7 @@ error_code sys_rwlock_destroy(ppu_thread& ppu, u32 rw_lock_id) return CELL_EBUSY; } + lv2_obj::on_id_destroy(rw, rw.shared, rw.key); return {}; }); diff --git a/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp b/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp index f21613687e..0e67708450 100644 --- a/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_semaphore.cpp @@ -9,8 +9,6 @@ LOG_CHANNEL(sys_semaphore); -template<> DECLARE(ipc_manager::g_ipc) {}; - error_code sys_semaphore_create(ppu_thread& ppu, vm::ptr sem_id, vm::ptr attr, s32 initial_val, s32 max_val) { ppu.state += cpu_flag::wait; @@ -68,6 +66,7 @@ error_code sys_semaphore_destroy(ppu_thread& ppu, u32 sem_id) return CELL_EBUSY; } + lv2_obj::on_id_destroy(sema, sema.shared, sema.key); return {}; }); diff --git a/rpcs3/Emu/Cell/lv2/sys_sync.h b/rpcs3/Emu/Cell/lv2/sys_sync.h index e1c82927e5..7a6cdb3653 100644 --- a/rpcs3/Emu/Cell/lv2/sys_sync.h +++ b/rpcs3/Emu/Cell/lv2/sys_sync.h @@ -77,13 +77,17 @@ private: }; // Function executed under IDM mutex, error will make the object creation fail and the error will be returned - static CellError on_id_create() + CellError on_id_create() { + exists++; return {}; } public: + // Existence validation (workaround for shared-ptr ref-counting) + atomic_t exists = 0; + static std::string name64(u64 name_u64) { const auto ptr = reinterpret_cast(&name_u64); @@ -198,95 +202,95 @@ public: { case SYS_SYNC_NEWLY_CREATED: case SYS_SYNC_NOT_CARE: - { - std::shared_ptr result = make(); - - CellError error{}; - - if (!ipc_manager::add(ipc_key, [&]() - { - if (!idm::import([&]() - { - if (result && (error = result->on_id_create())) - result.reset(); - return result; - })) - { - result.reset(); - } - - return result; - }, &result)) - { - if (error) - { - return error; - } - - if (flags == SYS_SYNC_NEWLY_CREATED) - { - return CELL_EEXIST; - } - - error = CELL_EAGAIN; - - if (!idm::import([&]() { if (result && (error = result->on_id_create())) result.reset(); return std::move(result); })) - { - return error; - } - - return CELL_OK; - } - else if (!result) - { - return error ? CELL_EAGAIN : error; - } - else - { - return CELL_OK; - } - } case SYS_SYNC_NOT_CREATE: { - auto result = ipc_manager::get(ipc_key); - - if (!result) - { - return CELL_ESRCH; - } - - CellError error = CELL_EAGAIN; - - if (!idm::import([&]() { if (result && (error = result->on_id_create())) result.reset(); return std::move(result); })) - { - return error; - } - - return CELL_OK; - } - default: - { - return CELL_EINVAL; + break; } + default: return CELL_EINVAL; } + + break; } case SYS_SYNC_NOT_PROCESS_SHARED: { - std::shared_ptr result = make(); + break; + } + default: return CELL_EINVAL; + } - CellError error = CELL_EAGAIN; + std::shared_ptr result = make(); - if (!idm::import([&]() { if (result && (error = result->on_id_create())) result.reset(); return std::move(result); })) + // EAGAIN for IDM IDs shortage + CellError error = CELL_EAGAIN; + + if (!idm::import([&]() -> std::shared_ptr + { + auto finalize_construct = [&]() -> std::shared_ptr { - return error; + if ((error = result->on_id_create())) + { + result.reset(); + } + + return std::move(result); + }; + + if (flags != SYS_SYNC_PROCESS_SHARED) + { + // Creation of unique (non-shared) object handle + return finalize_construct(); } - return CELL_OK; - } - default: + auto& ipc_container = g_fxo->get>(); + + if (flags == SYS_SYNC_NOT_CREATE) + { + result = ipc_container.get(ipc_key); + + if (!result) + { + error = CELL_ESRCH; + return result; + } + + // Run on_id_create() on existing object + return finalize_construct(); + } + + bool added = false; + std::tie(added, result) = ipc_container.add(ipc_key, finalize_construct, flags != SYS_SYNC_NEWLY_CREATED); + + if (!added) + { + if (flags == SYS_SYNC_NEWLY_CREATED) + { + // Object already exists but flags does not allow it + error = CELL_EEXIST; + + // We specified we do not want to peek pointer's value, result must be empty + AUDIT(!result); + return result; + } + + // Run on_id_create() on existing object + return finalize_construct(); + } + + return std::move(result); + })) { - return CELL_EINVAL; + return error; } + + return CELL_OK; + } + + template + static void on_id_destroy(T& obj, u32 pshared, u64 ipc_key) + { + if (obj.exists-- == 1u && pshared == SYS_SYNC_PROCESS_SHARED) + { + g_fxo->get>().remove(ipc_key); } } diff --git a/rpcs3/Emu/IPC.h b/rpcs3/Emu/IPC.h index d6bd9d3954..9df802c7bb 100644 --- a/rpcs3/Emu/IPC.h +++ b/rpcs3/Emu/IPC.h @@ -6,99 +6,65 @@ #include "Utilities/mutex.h" // IPC manager for objects of type T and IPC keys of type K. -// External declaration of g_ipc is required. template class ipc_manager final { - std::unordered_map> m_map; + std::unordered_map> m_map; - shared_mutex m_mutex; - - static ipc_manager g_ipc; + mutable shared_mutex m_mutex; public: // Add new object if specified ipc_key is not used + // .first: added new object?, .second: what's at m_map[key] after this function if (peek_ptr || added new object) is true template - static bool add(const K& ipc_key, F&& provider, std::shared_ptr* out = nullptr) + std::pair> add(const K& ipc_key, F&& provider, bool peek_ptr = true) { - std::lock_guard lock(g_ipc.m_mutex); + std::lock_guard lock(m_mutex); // Get object location - std::weak_ptr& wptr = g_ipc.m_map[ipc_key]; + std::shared_ptr& ptr = m_map[ipc_key]; + const bool existed = ptr.operator bool(); - std::shared_ptr old; - - if ((out && !(old = wptr.lock())) || wptr.expired()) + if (!existed) { // Call a function which must return the object - if (out) - { - *out = provider(); - wptr = *out; - } - else - { - wptr = provider(); - } - - return true; + ptr = provider(); } - if (out) - { - *out = std::move(old); - } - - return false; + const bool added = !existed && ptr; + return {added, (peek_ptr || added) ? ptr : nullptr}; } // Unregister specified ipc_key, may return true even if the object doesn't exist anymore - static bool remove(const K& ipc_key) + bool remove(const K& ipc_key) { - std::lock_guard lock(g_ipc.m_mutex); + std::lock_guard lock(m_mutex); - return g_ipc.m_map.erase(ipc_key) != 0; - } - - // Unregister specified ipc_key, return the object - static std::shared_ptr withdraw(const K& ipc_key) - { - std::lock_guard lock(g_ipc.m_mutex); - - const auto found = g_ipc.m_map.find(ipc_key); - - if (found != g_ipc.m_map.end()) - { - auto ptr = found->second.lock(); - g_ipc.m_map.erase(found); - return ptr; - } - - return nullptr; + return m_map.erase(ipc_key) != 0; } // Get object with specified ipc_key - static std::shared_ptr get(const K& ipc_key) + std::shared_ptr get(const K& ipc_key) const { - reader_lock lock(g_ipc.m_mutex); + reader_lock lock(m_mutex); - const auto found = g_ipc.m_map.find(ipc_key); + const auto found = m_map.find(ipc_key); - if (found != g_ipc.m_map.end()) + if (found != m_map.end()) { - return found->second.lock(); + return found->second; } return nullptr; } // Check whether the object actually exists - static bool check(const K& ipc_key) + bool check(const K& ipc_key) const { - reader_lock lock(g_ipc.m_mutex); + reader_lock lock(m_mutex); - const auto found = g_ipc.m_map.find(ipc_key); + const auto found = m_map.find(ipc_key); - return found != g_ipc.m_map.end() && !found->second.expired(); + return found != m_map.end(); } }; diff --git a/rpcs3/rpcs3qt/kernel_explorer.cpp b/rpcs3/rpcs3qt/kernel_explorer.cpp index a2bebca410..26d3b84bf5 100644 --- a/rpcs3/rpcs3qt/kernel_explorer.cpp +++ b/rpcs3/rpcs3qt/kernel_explorer.cpp @@ -321,7 +321,7 @@ void kernel_explorer::Update() { auto& mutex = static_cast(obj); add_leaf(node, qstr(fmt::format(u8"Mutex 0x%08x: ā€œ%sā€, %s,%s Owner: %#x, Locks: %u, Key: %#llx, Conds: %u, Wq: %zu", id, lv2_obj::name64(mutex.name), mutex.protocol, - mutex.recursive == SYS_SYNC_RECURSIVE ? " Recursive," : "", mutex.owner >> 1, +mutex.lock_count, mutex.key, mutex.obj_count.load().cond_count, mutex.sq.size()))); + mutex.recursive == SYS_SYNC_RECURSIVE ? " Recursive," : "", mutex.owner >> 1, +mutex.lock_count, mutex.key, mutex.cond_count, mutex.sq.size()))); break; } case SYS_COND_OBJECT: @@ -360,19 +360,18 @@ void kernel_explorer::Update() case SYS_EVENT_PORT_OBJECT: { auto& ep = static_cast(obj); - const auto queue = ep.queue.lock(); const auto type = ep.type == SYS_EVENT_PORT_LOCAL ? "LOCAL"sv : "IPC"sv; - if (lv2_event_queue::check(queue)) + if (const auto queue = ep.queue.get(); queue && queue->exists) { - if (queue.get() == idm::check_unlocked(ep.queue_id)) + if (queue == idm::check_unlocked(ep.queue_id)) { // Type must be LOCAL here, but refer to the note below for why it is showed add_leaf(node, qstr(fmt::format("Event Port 0x%08x: %s, Name: %#llx, Event Queue (ID): 0x%08x", id, type, ep.name, ep.queue_id))); break; } - if (queue == lv2_event_queue::find(queue->key)) + if (queue == lv2_event_queue::find(queue->key).get()) { // There are cases in which the attached queue by ID also has an IPC // And the ID was destroyed but another was created for that same IPC