hyprutils/src/signal/Signal.cpp

61 lines
1.8 KiB
C++
Raw Normal View History

#include "hyprutils/memory/SharedPtr.hpp"
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::CSignalBase::emitInternal(void* args) {
2024-06-08 19:37:15 +02:00
std::vector<SP<CSignalListener>> listeners;
listeners.reserve(m_vListeners.size());
2024-06-08 19:37:15 +02:00
for (auto& l : m_vListeners) {
if (l.expired())
2024-06-08 19:37:15 +02:00
continue;
listeners.emplace_back(l.lock());
}
auto statics = m_vStaticListeners;
2024-06-08 19:37:15 +02:00
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
if (l.strongRef() == 1)
2024-06-08 19:37:15 +02:00
continue;
l->emitInternal(args);
2024-06-08 19:37:15 +02:00
}
for (auto& l : statics) {
l->emitInternal(args);
2024-06-08 19:37:15 +02:00
}
// release SPs
listeners.clear();
// we cannot release any expired refs here as one of the listeners could've removed this object and
// as such we'd be doing a UAF
2024-06-08 19:37:15 +02:00
}
CHyprSignalListener Hyprutils::Signal::CSignalBase::registerListenerInternal(std::function<void(void*)> handler) {
CHyprSignalListener listener = SP<CSignalListener>(new CSignalListener(handler));
2024-06-08 19:37:15 +02:00
m_vListeners.emplace_back(listener);
// housekeeping: remove any stale listeners
std::erase_if(m_vListeners, [](const auto& other) { return other.expired(); });
2024-06-08 19:37:15 +02:00
return listener;
}
void Hyprutils::Signal::CSignalBase::registerStaticListenerInternal(std::function<void(void*)> handler) {
m_vStaticListeners.emplace_back(SP<CSignalListener>(new CSignalListener(handler)));
}
void Hyprutils::Signal::CSignal::emit(std::any data) {
CSignalT::emit(data);
}