shadPS4/src/core/libraries/kernel/event_queue.cpp

95 lines
2.3 KiB
C++
Raw Normal View History

2024-02-23 22:32:32 +01:00
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/assert.h"
2024-04-13 23:35:48 +02:00
#include "core/libraries/kernel/event_queue.h"
2023-11-06 00:11:54 +01:00
2024-04-13 23:35:48 +02:00
namespace Libraries::Kernel {
2023-11-06 00:11:54 +01:00
EqueueInternal::~EqueueInternal() = default;
2024-07-09 12:12:15 +02:00
bool EqueueInternal::AddEvent(EqueueEvent& event) {
std::scoped_lock lock{m_mutex};
2024-07-09 12:12:15 +02:00
event.time_added = std::chrono::high_resolution_clock::now();
2024-07-09 12:12:15 +02:00
const auto& it = std::ranges::find(m_events, event);
if (it != m_events.cend()) {
*it = event;
} else {
m_events.emplace_back(event);
}
return true;
}
2024-07-09 12:12:15 +02:00
bool EqueueInternal::RemoveEvent(u64 id) {
bool has_found = false;
2024-05-17 23:32:15 +02:00
std::scoped_lock lock{m_mutex};
2024-07-09 12:12:15 +02:00
const auto& it =
2024-05-10 23:51:24 +02:00
std::ranges::find_if(m_events, [id](auto& ev) { return ev.event.ident == id; });
2024-07-09 12:12:15 +02:00
if (it != m_events.cend()) {
m_events.erase(it);
has_found = true;
}
return has_found;
}
2024-07-09 12:12:15 +02:00
int EqueueInternal::WaitForEvents(SceKernelEvent* ev, int num, u32 micros) {
std::unique_lock lock{m_mutex};
int ret = 0;
const auto predicate = [&] {
2024-07-09 12:12:15 +02:00
ret = GetTriggeredEvents(ev, num);
return ret > 0;
};
if (micros == 0) {
m_cond.wait(lock, predicate);
} else {
m_cond.wait_for(lock, std::chrono::microseconds(micros), predicate);
}
return ret;
}
2024-07-09 12:12:15 +02:00
bool EqueueInternal::TriggerEvent(u64 ident, s16 filter, void* trigger_data) {
bool has_found = false;
2024-05-17 23:32:15 +02:00
{
std::scoped_lock lock{m_mutex};
for (auto& event : m_events) {
2024-07-09 12:12:15 +02:00
ASSERT_MSG(event.event.filter == filter,
"Event to trigger doesn't match to queue events");
if (event.event.ident == ident) {
event.Trigger(trigger_data);
has_found = true;
2024-05-17 23:32:15 +02:00
}
}
}
m_cond.notify_one();
2024-07-09 12:12:15 +02:00
return has_found;
2023-09-11 12:14:13 +02:00
}
2024-07-09 12:12:15 +02:00
int EqueueInternal::GetTriggeredEvents(SceKernelEvent* ev, int num) {
int ret = 0;
2024-05-17 23:32:15 +02:00
for (auto& event : m_events) {
2024-07-09 12:12:15 +02:00
if (event.IsTriggered()) {
if (ev->flags & SceKernelEvent::Flags::Clear) {
event.Reset();
}
2024-05-17 23:32:15 +02:00
ev[ret++] = event.event;
2024-07-09 12:12:15 +02:00
if (ret == num) {
break;
}
2024-05-17 23:32:15 +02:00
}
}
return ret;
}
2024-04-13 23:35:48 +02:00
} // namespace Libraries::Kernel