signals: use tuple reference and check if listeners is empty

use forward_as_tuple as ít creates a temporary tuple reference instead
of copying/moving each argument. also if guard the emitInternal to only
create locals if there is actually any listeners.
This commit is contained in:
Tom Englund 2025-12-20 01:56:59 +01:00
parent 5ac060bfcf
commit 8ca26cee4d
2 changed files with 27 additions and 22 deletions

View file

@ -36,7 +36,7 @@ namespace Hyprutils {
if constexpr (sizeof...(Args) == 0)
emitInternal(nullptr);
else {
auto argsTuple = std::tuple<RefArg<Args>...>(args...);
auto argsTuple = std::forward_as_tuple(args...);
if constexpr (sizeof...(Args) == 1)
// NOLINTNEXTLINE: const is reapplied by handler invocation if required

View file

@ -10,33 +10,38 @@ using namespace Hyprutils::Memory;
#define WP CWeakPointer
void Hyprutils::Signal::CSignalBase::emitInternal(void* args) {
std::vector<SP<CSignalListener>> listeners;
listeners.reserve(m_vListeners.size());
for (auto& l : m_vListeners) {
if (l.expired())
continue;
if (!m_vListeners.empty()) {
std::vector<SP<CSignalListener>> listeners;
listeners.reserve(m_vListeners.size());
listeners.emplace_back(l.lock());
for (const auto& l : m_vListeners) {
if (l.expired())
continue;
listeners.emplace_back(l.lock());
}
for (const 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)
continue;
l->emitInternal(args);
}
// release SPs
listeners.clear();
}
auto statics = m_vStaticListeners;
if (!m_vStaticListeners.empty()) {
const auto statics = m_vStaticListeners;
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)
continue;
l->emitInternal(args);
for (const auto& l : statics) {
l->emitInternal(args);
}
}
for (auto& l : statics) {
l->emitInternal(args);
}
// 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
}