#pragma once #include #include #include #include #include #include #include "ScopedConnection.h" /** * Signal 类,用于事件通知 * 线程安全,支持 RAII 连接管理 */ template class Signal { public: using Listener = std::function; using Token = size_t; Signal() : m_impl(std::make_shared()) {} // 允许移动 Signal(Signal&&) = default; Signal& operator=(Signal&&) = default; // 禁止拷贝(因为底层是 shared_ptr,拷贝会导致两个 Signal 共享同一个监听器列表,通常不符合预期) Signal(const Signal&) = delete; Signal& operator=(const Signal&) = delete; /** * @brief 添加监听器 */ Token Connect(Listener listener) { std::lock_guard lock(m_impl->mutex); Token token = ++m_impl->tokenCounter; m_impl->listeners.emplace(token, std::move(listener)); return token; } /** * @brief 移除指定令牌的监听器 */ bool Disconnect(Token token) { std::lock_guard lock(m_impl->mutex); return m_impl->listeners.erase(token) > 0; // 修正了拼写和返回值 } /** * @brief RAII 版本的连接函数 */ [[nodiscard]] ScopedConnection ConnectScoped(Listener listener) { Token token = Connect(std::move(listener)); // 使用 weak_ptr 打破循环引用,并防止野指针访问 std::weak_ptr weakImpl = m_impl; return ScopedConnection([weakImpl, token]() { // 尝试锁定 weak_ptr,如果 Signal 已经被销毁,lock 会返回空指针 if (auto impl = weakImpl.lock()) { impl->Remove(token); } }); } /** * @brief 通知所有监听器 */ void Emit(Args... args) { std::vector listenersSnapshot; { std::lock_guard lock(m_impl->mutex); if (m_impl->listeners.empty()) { return; } // 创建快照:将回调拷贝出来,在锁外执行 // 避免死锁(回调中调用 Connect/Disconnect)和迭代器失效 listenersSnapshot.reserve(m_impl->listeners.size()); for (const auto& [token, listener] : m_impl->listeners) { listenersSnapshot.push_back(listener); } } for (const auto& listener : listenersSnapshot) { listener(args...); } } /** * @brief 清空所有监听器 */ void Clear() { std::lock_guard lock(m_impl->mutex); m_impl->listeners.clear(); } private: // 内部实现类,由 shared_ptr 管理生命周期 struct Impl { std::mutex mutex; std::unordered_map listeners; std::atomic_size_t tokenCounter{ 0 }; void Remove(Token token) { std::lock_guard lock(mutex); listeners.erase(token); } }; std::shared_ptr m_impl; };