2024-06-08 19:37:15 +02:00
|
|
|
#include <hyprutils/signal/Signal.hpp>
|
|
|
|
|
#include <hyprutils/memory/WeakPtr.hpp>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
|
|
using namespace Hyprutils::Signal;
|
|
|
|
|
using namespace Hyprutils::Memory;
|
|
|
|
|
|
|
|
|
|
#define SP CSharedPointer
|
|
|
|
|
#define WP CWeakPointer
|
|
|
|
|
|
|
|
|
|
void Hyprutils::Signal::CSignal::emit(std::any data) {
|
|
|
|
|
std::vector<SP<CSignalListener>> listeners;
|
|
|
|
|
for (auto& l : m_vListeners) {
|
2024-07-08 23:06:28 +02:00
|
|
|
if (l.expired())
|
2024-06-08 19:37:15 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
listeners.emplace_back(l.lock());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<CStaticSignalListener*> statics;
|
2025-02-03 00:36:28 +05:00
|
|
|
statics.reserve(m_vStaticListeners.size());
|
2024-06-08 19:37:15 +02:00
|
|
|
for (auto& l : m_vStaticListeners) {
|
|
|
|
|
statics.emplace_back(l.get());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& l : listeners) {
|
|
|
|
|
// if there is only one lock, it means the event is only held by the listeners
|
|
|
|
|
// vector and was removed during our iteration
|
2024-07-08 23:06:28 +02:00
|
|
|
if (l.strongRef() == 1)
|
2024-06-08 19:37:15 +02:00
|
|
|
continue;
|
2024-12-25 14:10:14 -05:00
|
|
|
|
2024-06-08 19:37:15 +02:00
|
|
|
l->emit(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& l : statics) {
|
|
|
|
|
l->emit(data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// release SPs
|
|
|
|
|
listeners.clear();
|
|
|
|
|
|
2024-12-25 14:10:14 -05:00
|
|
|
// we cannot release any expired refs here as one of the listeners could've removed this object and
|
2024-07-08 23:06:28 +02:00
|
|
|
// as such we'd be doing a UAF
|
2024-06-08 19:37:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CHyprSignalListener Hyprutils::Signal::CSignal::registerListener(std::function<void(std::any)> handler) {
|
|
|
|
|
CHyprSignalListener listener = makeShared<CSignalListener>(handler);
|
|
|
|
|
m_vListeners.emplace_back(listener);
|
2024-07-08 23:06:28 +02:00
|
|
|
|
|
|
|
|
// housekeeping: remove any stale listeners
|
|
|
|
|
std::erase_if(m_vListeners, [](const auto& other) { return other.expired(); });
|
2024-12-25 14:10:14 -05:00
|
|
|
|
2024-06-08 19:37:15 +02:00
|
|
|
return listener;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Hyprutils::Signal::CSignal::registerStaticListener(std::function<void(void*, std::any)> handler, void* owner) {
|
|
|
|
|
m_vStaticListeners.emplace_back(std::make_unique<CStaticSignalListener>(handler, owner));
|
2025-02-03 00:36:28 +05:00
|
|
|
}
|