fix Signal

This commit is contained in:
2025-08-10 11:46:43 +02:00
parent cba790f804
commit 6b987cf78d
2 changed files with 68 additions and 10 deletions

View File

@@ -8,8 +8,11 @@
namespace td {
namespace utils {
/**
* \brief Signal class
*/
template <typename... Args>
class Signal : private NonCopyable {
class SignalRaw : private NonCopyable {
public:
using FnType = void(Args...);
using CallBack = std::function<FnType>;
@@ -35,5 +38,63 @@ class Signal : private NonCopyable {
}
};
/**
* \brief Memory managed Signal class
*/
template <typename... Args>
class Signal {
public:
using SignalBase = SignalRaw<Args...>;
using CallBack = typename SignalBase::CallBack;
using SignalPtr = std::shared_ptr<SignalBase>;
class ConnectionGuard;
private:
SignalPtr m_Signal;
public:
Signal() : m_Signal(std::make_shared<SignalBase>()) {}
Signal(const Signal&) = default;
void Connect(const CallBack& a_Callback) {
m_Signal->Connect(a_Callback);
}
[[nodiscard]] std::unique_ptr<ConnectionGuard> ConnectSafe(const CallBack& a_Callback) {
Connect(a_Callback);
return std::make_unique<ConnectionGuard>(*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 <typename... Args>
class Signal<Args...>::ConnectionGuard : public Connection {
private:
using CallBack = typename Signal<Args...>::CallBack;
std::weak_ptr<SignalRaw<Args...>> m_Signal;
CallBack m_Callback;
public:
ConnectionGuard(const Signal<Args...>& 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

View File

@@ -1,6 +1,6 @@
#pragma once
#include <td/misc/SlotGuard.h>
#include <td/misc/Signal.h>
namespace td {
namespace utils {
@@ -12,22 +12,19 @@ namespace utils {
*/
class SlotGuard {
private:
std::vector<std::function<void()>> m_Deleters;
std::vector<std::unique_ptr<Connection>> m_Connections;
public:
/**
* \brief Connect a signal to a function (with the same signature)
*/
template <typename... Args>
void Connect(Signal<Args...>& a_Signal, const typename Signal<Args...>::CallBack& a_Callback) {
a_Signal.Connect(a_Callback);
m_Deleters.push_back([&a_Signal, &a_Callback]() { a_Signal.Disconnect(a_Callback); });
void Connect(Signal<Args...> a_Signal, const typename Signal<Args...>::CallBack& a_Callback) {
m_Connections.push_back(a_Signal.ConnectSafe(a_Callback));
}
~SlotGuard() {
for (auto& deleter : m_Deleters) {
deleter();
}
void Disconnect() {
m_Connections.clear();
}
};