mirror of
https://github.com/hyprwm/Hyprland
synced 2025-02-17 02:42:08 +01:00
helpers: Add new C++ Signal and Listener classes
A memory-safe alternative to wl_signal
This commit is contained in:
parent
a10a6fff55
commit
a141bbbea5
4 changed files with 78 additions and 0 deletions
13
src/helpers/signal/Listener.cpp
Normal file
13
src/helpers/signal/Listener.cpp
Normal 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);
|
||||||
|
}
|
24
src/helpers/signal/Listener.hpp
Normal file
24
src/helpers/signal/Listener.hpp
Normal 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;
|
22
src/helpers/signal/Signal.cpp
Normal file
22
src/helpers/signal/Signal.cpp
Normal 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;
|
||||||
|
}
|
19
src/helpers/signal/Signal.hpp
Normal file
19
src/helpers/signal/Signal.hpp
Normal 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;
|
||||||
|
};
|
Loading…
Add table
Reference in a new issue