helpers: Add new C++ Signal and Listener classes

A memory-safe alternative to wl_signal
This commit is contained in:
Vaxry 2024-04-21 01:47:24 +01:00
parent a10a6fff55
commit a141bbbea5
4 changed files with 78 additions and 0 deletions

View file

@ -0,0 +1,13 @@
#include "Listener.hpp"
#include "Signal.hpp"
CSignalListener::CSignalListener(std::function<void(std::any)> handler) : m_fHandler(handler) {
;
}
void CSignalListener::emit(std::any data) {
if (!m_fHandler)
return;
m_fHandler(data);
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <any>
#include <memory>
#include <functional>
class CSignal;
class CSignalListener {
public:
CSignalListener(std::function<void(std::any)> handler);
CSignalListener(CSignalListener&&) = delete;
CSignalListener(CSignalListener&) = delete;
CSignalListener(const CSignalListener&) = delete;
CSignalListener(const CSignalListener&&) = delete;
void emit(std::any data);
private:
std::function<void(std::any)> m_fHandler;
};
typedef std::shared_ptr<CSignalListener> CHyprSignalListener;

View file

@ -0,0 +1,22 @@
#include "Signal.hpp"
#include <algorithm>
void CSignal::emit(std::any data) {
bool dirty = false;
for (auto& l : m_vListeners) {
if (const CHyprSignalListener L = l.lock())
L->emit(data);
else
dirty = true;
}
if (dirty)
std::erase_if(m_vListeners, [](const auto& other) { return !other.lock(); });
}
CHyprSignalListener CSignal::registerListener(std::function<void(std::any)> handler) {
CHyprSignalListener listener = std::make_shared<CSignalListener>(handler);
m_vListeners.emplace_back(std::weak_ptr<CSignalListener>(listener));
return listener;
}

View file

@ -0,0 +1,19 @@
#pragma once
#include <functional>
#include <any>
#include <vector>
#include <memory>
#include "Listener.hpp"
class CSignal {
public:
void emit(std::any data);
//
[[nodiscard("Listener is unregistered when the ptr is lost")]] CHyprSignalListener registerListener(std::function<void(std::any)> handler);
private:
std::vector<std::weak_ptr<CSignalListener>> m_vListeners;
};