From 6b987cf78d817defaa355f21f5d68d37b19fa60e Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Sun, 10 Aug 2025 11:46:43 +0200 Subject: [PATCH] fix Signal --- include/td/misc/Signal.h | 63 ++++++++++++++++++++++++++++++++++++- include/td/misc/SlotGuard.h | 15 ++++----- 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/include/td/misc/Signal.h b/include/td/misc/Signal.h index 126e675..66afe35 100644 --- a/include/td/misc/Signal.h +++ b/include/td/misc/Signal.h @@ -8,8 +8,11 @@ namespace td { namespace utils { +/** + * \brief Signal class + */ template -class Signal : private NonCopyable { +class SignalRaw : private NonCopyable { public: using FnType = void(Args...); using CallBack = std::function; @@ -35,5 +38,63 @@ class Signal : private NonCopyable { } }; +/** + * \brief Memory managed Signal class + */ +template +class Signal { + public: + using SignalBase = SignalRaw; + using CallBack = typename SignalBase::CallBack; + using SignalPtr = std::shared_ptr; + class ConnectionGuard; + + private: + SignalPtr m_Signal; + + public: + Signal() : m_Signal(std::make_shared()) {} + Signal(const Signal&) = default; + + void Connect(const CallBack& a_Callback) { + m_Signal->Connect(a_Callback); + } + + [[nodiscard]] std::unique_ptr ConnectSafe(const CallBack& a_Callback) { + Connect(a_Callback); + return std::make_unique(*this, a_Callback); + } + + void Disconnect(const CallBack& a_Callback) { + m_Signal->Disconnect(a_Callback); + } + + void operator()(Args... args) const { + m_Signal->operator()(args...); + } +}; + +class Connection { + public: + virtual ~Connection() {} +}; + +template +class Signal::ConnectionGuard : public Connection { + private: + using CallBack = typename Signal::CallBack; + + std::weak_ptr> m_Signal; + CallBack m_Callback; + + public: + ConnectionGuard(const Signal& a_Signal, const CallBack& a_Callback) : m_Signal(a_Signal.m_Signal), m_Callback(a_Callback) {} + + ~ConnectionGuard() { + if (!m_Signal.expired()) + m_Signal.lock()->Disconnect(m_Callback); + } +}; + } // namespace utils } // namespace td diff --git a/include/td/misc/SlotGuard.h b/include/td/misc/SlotGuard.h index ba06a32..21e3eb8 100644 --- a/include/td/misc/SlotGuard.h +++ b/include/td/misc/SlotGuard.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace td { namespace utils { @@ -12,22 +12,19 @@ namespace utils { */ class SlotGuard { private: - std::vector> m_Deleters; + std::vector> m_Connections; public: /** * \brief Connect a signal to a function (with the same signature) */ template - void Connect(Signal& a_Signal, const typename Signal::CallBack& a_Callback) { - a_Signal.Connect(a_Callback); - m_Deleters.push_back([&a_Signal, &a_Callback]() { a_Signal.Disconnect(a_Callback); }); + void Connect(Signal a_Signal, const typename Signal::CallBack& a_Callback) { + m_Connections.push_back(a_Signal.ConnectSafe(a_Callback)); } - ~SlotGuard() { - for (auto& deleter : m_Deleters) { - deleter(); - } + void Disconnect() { + m_Connections.clear(); } };