mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-12-16 13:36:59 +00:00
171 lines
No EOL
2.6 KiB
C++
171 lines
No EOL
2.6 KiB
C++
#pragma once
|
|
|
|
#include <mutex>
|
|
#include <condition_variable>
|
|
|
|
class Semaphore
|
|
{
|
|
public:
|
|
void notify()
|
|
{
|
|
std::lock_guard lock(m_mutex);
|
|
++m_count;
|
|
m_condition.notify_one();
|
|
}
|
|
|
|
void wait()
|
|
{
|
|
std::unique_lock lock(m_mutex);
|
|
while (m_count == 0)
|
|
{
|
|
m_condition.wait(lock);
|
|
}
|
|
|
|
--m_count;
|
|
}
|
|
|
|
bool try_wait()
|
|
{
|
|
std::lock_guard lock(m_mutex);
|
|
if (m_count == 0)
|
|
return false;
|
|
|
|
--m_count;
|
|
return true;
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
std::lock_guard lock(m_mutex);
|
|
m_count = 0;
|
|
}
|
|
|
|
private:
|
|
std::mutex m_mutex;
|
|
std::condition_variable m_condition;
|
|
uint64 m_count = 0;
|
|
};
|
|
|
|
class CounterSemaphore
|
|
{
|
|
public:
|
|
void reset()
|
|
{
|
|
std::lock_guard lock(m_mutex);
|
|
m_count = 0;
|
|
}
|
|
|
|
void increment()
|
|
{
|
|
std::lock_guard lock(m_mutex);
|
|
++m_count;
|
|
if (m_count == 1)
|
|
m_condition.notify_all();
|
|
}
|
|
|
|
void decrement()
|
|
{
|
|
std::lock_guard lock(m_mutex);
|
|
--m_count;
|
|
cemu_assert_debug(m_count >= 0);
|
|
if (m_count == 0)
|
|
m_condition.notify_all();
|
|
}
|
|
|
|
// decrement only if non-zero
|
|
// otherwise wait
|
|
void decrementWithWait()
|
|
{
|
|
std::unique_lock lock(m_mutex);
|
|
while (m_count == 0)
|
|
m_condition.wait(lock);
|
|
m_count--;
|
|
}
|
|
|
|
// decrement only if non-zero
|
|
// otherwise wait
|
|
// may wake up spuriously
|
|
bool decrementWithWaitAndTimeout(uint32 ms)
|
|
{
|
|
std::unique_lock lock(m_mutex);
|
|
if (m_count == 0)
|
|
{
|
|
m_condition.wait_for(lock, std::chrono::milliseconds(ms));
|
|
}
|
|
if (m_count == 0)
|
|
return false;
|
|
m_count--;
|
|
return true;
|
|
}
|
|
|
|
void waitUntilZero()
|
|
{
|
|
std::unique_lock lock(m_mutex);
|
|
while (m_count != 0)
|
|
m_condition.wait(lock);
|
|
}
|
|
|
|
void waitUntilNonZero()
|
|
{
|
|
std::unique_lock lock(m_mutex);
|
|
while (m_count == 0)
|
|
m_condition.wait(lock);
|
|
}
|
|
|
|
bool isZero() const
|
|
{
|
|
return m_count == 0;
|
|
}
|
|
|
|
private:
|
|
std::mutex m_mutex;
|
|
std::condition_variable m_condition;
|
|
sint64 m_count = 0;
|
|
};
|
|
|
|
template<typename T>
|
|
class StateSemaphore
|
|
{
|
|
public:
|
|
StateSemaphore(T initialState) : m_state(initialState) {};
|
|
|
|
T getValue()
|
|
{
|
|
std::unique_lock lock(m_mutex);
|
|
return m_state;
|
|
}
|
|
|
|
bool hasState(T state)
|
|
{
|
|
std::unique_lock lock(m_mutex);
|
|
return m_state == state;
|
|
}
|
|
|
|
void setValue(T newState)
|
|
{
|
|
std::unique_lock lock(m_mutex);
|
|
m_state = newState;
|
|
m_condition.notify_all();
|
|
}
|
|
|
|
void setValue(T newState, T expectedValue)
|
|
{
|
|
std::unique_lock lock(m_mutex);
|
|
while (m_state != expectedValue)
|
|
m_condition.wait(lock);
|
|
m_state = newState;
|
|
m_condition.notify_all();
|
|
}
|
|
|
|
void waitUntilValue(T state)
|
|
{
|
|
std::unique_lock lock(m_mutex);
|
|
while (m_state != state)
|
|
m_condition.wait(lock);
|
|
}
|
|
|
|
private:
|
|
std::mutex m_mutex;
|
|
std::condition_variable m_condition;
|
|
T m_state;
|
|
}; |