#pragma once #include #include #include #include #include #include #include #include #include namespace XCEngine { namespace Editor { class EventTypeRegistry { public: static uint32_t NextId() { return s_nextId.fetch_add(1, std::memory_order_relaxed); } private: inline static std::atomic s_nextId{0}; }; template struct EventTypeId { static uint32_t Get() { static const uint32_t id = EventTypeRegistry::NextId(); return id; } }; class EventBus { public: using EventHandler = std::function; template uint64_t Subscribe(std::function handler) { static_assert(sizeof(T) > 0, "Event type must be defined"); uint32_t typeId = EventTypeId::Get(); uint64_t handlerId = 0; { std::lock_guard lock(m_mutex); handlerId = m_nextHandlerId++; auto it = m_handlers.find(typeId); if (it == m_handlers.end()) { m_handlers[typeId] = std::vector(); } HandlerEntry entry; entry.id = handlerId; entry.handler = [handler](const void* data) { handler(*static_cast(data)); }; m_handlers[typeId].push_back(entry); } return handlerId; } template void Unsubscribe(uint64_t handlerId) { static_assert(sizeof(T) > 0, "Event type must be defined"); uint32_t typeId = EventTypeId::Get(); std::lock_guard lock(m_mutex); auto it = m_handlers.find(typeId); if (it != m_handlers.end()) { auto& handlers = it->second; handlers.erase( std::remove_if(handlers.begin(), handlers.end(), [handlerId](const HandlerEntry& entry) { return entry.id == handlerId; }), handlers.end() ); } } template void Publish(const T& event) { static_assert(sizeof(T) > 0, "Event type must be defined"); uint32_t typeId = EventTypeId::Get(); std::shared_lock lock(m_mutex); auto it = m_handlers.find(typeId); if (it != m_handlers.end()) { for (const auto& entry : it->second) { entry.handler(&event); } } } void Clear() { std::lock_guard lock(m_mutex); m_handlers.clear(); } private: struct HandlerEntry { uint64_t id; std::function handler; }; std::unordered_map> m_handlers; uint64_t m_nextHandlerId = 0; std::shared_mutex m_mutex; }; } }