rpcsx/rpcs3/Emu/Memory/wait_engine.h

50 lines
1,018 B
C
Raw Normal View History

#pragma once
2016-05-13 16:01:48 +02:00
#include "Utilities/types.h"
2016-05-13 16:01:48 +02:00
class thread_ctrl;
namespace vm
{
2016-05-13 16:01:48 +02:00
struct waiter_base
{
u32 addr;
u32 mask;
2016-05-13 16:01:48 +02:00
thread_ctrl* thread{};
2016-05-13 16:01:48 +02:00
void initialize(u32 addr, u32 size);
bool try_notify();
2016-05-13 16:01:48 +02:00
protected:
virtual bool test() = 0;
};
2016-05-13 16:01:48 +02:00
// Wait until pred() returns true, addr must be aligned to size which must be a power of 2.
// It's possible for pred() to be called from any thread once the waiter is registered.
template<typename F>
auto wait_op(u32 addr, u32 size, F&& pred) -> decltype(static_cast<void>(pred()))
{
2016-05-13 16:01:48 +02:00
if (LIKELY(pred())) return;
2016-05-13 16:01:48 +02:00
struct waiter : waiter_base
{
2016-05-13 16:01:48 +02:00
std::conditional_t<sizeof(F) <= sizeof(void*), std::remove_reference_t<F>, F&&> func;
2016-05-13 16:01:48 +02:00
waiter(F&& func)
: func(std::forward<F>(func))
{
}
2016-05-13 16:01:48 +02:00
bool test() override
{
return func();
}
};
2016-05-13 16:01:48 +02:00
waiter(std::forward<F>(pred)).initialize(addr, size);
}
// Notify waiters on specific addr, addr must be aligned to size which must be a power of 2
void notify_at(u32 addr, u32 size);
}