aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorVaxry <[email protected]>2024-04-21 01:47:24 +0100
committerVaxry <[email protected]>2024-04-21 01:47:45 +0100
commita141bbbea503ae7b320eba614a80ca2f4e5c1cba (patch)
treef5d2c7f05c835da95dc6a225c65ec4d84809ca88
parenta10a6fff5530136a9ea024fa5f98c5ba5671bd2d (diff)
downloadHyprland-a141bbbea503ae7b320eba614a80ca2f4e5c1cba.tar.gz
Hyprland-a141bbbea503ae7b320eba614a80ca2f4e5c1cba.zip
helpers: Add new C++ Signal and Listener classes
A memory-safe alternative to wl_signal
-rw-r--r--src/helpers/signal/Listener.cpp13
-rw-r--r--src/helpers/signal/Listener.hpp24
-rw-r--r--src/helpers/signal/Signal.cpp22
-rw-r--r--src/helpers/signal/Signal.hpp19
4 files changed, 78 insertions, 0 deletions
diff --git a/src/helpers/signal/Listener.cpp b/src/helpers/signal/Listener.cpp
new file mode 100644
index 00000000..ae506343
--- /dev/null
+++ b/src/helpers/signal/Listener.cpp
@@ -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);
+}
diff --git a/src/helpers/signal/Listener.hpp b/src/helpers/signal/Listener.hpp
new file mode 100644
index 00000000..d2edb253
--- /dev/null
+++ b/src/helpers/signal/Listener.hpp
@@ -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;
diff --git a/src/helpers/signal/Signal.cpp b/src/helpers/signal/Signal.cpp
new file mode 100644
index 00000000..a8adc275
--- /dev/null
+++ b/src/helpers/signal/Signal.cpp
@@ -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;
+}
diff --git a/src/helpers/signal/Signal.hpp b/src/helpers/signal/Signal.hpp
new file mode 100644
index 00000000..38f9ea0c
--- /dev/null
+++ b/src/helpers/signal/Signal.hpp
@@ -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;
+};