mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 10:42:36 +01:00
121 lines
1.6 KiB
C++
121 lines
1.6 KiB
C++
#include "stdafx.h"
|
|
#include "Utilities/Semaphore.h"
|
|
|
|
bool semaphore_t::try_wait()
|
|
{
|
|
// check m_value without interlocked op
|
|
if (m_var.load().value == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// try to decrement m_value atomically
|
|
const auto old = m_var.fetch_op([](sync_var_t& var)
|
|
{
|
|
if (var.value)
|
|
{
|
|
var.value--;
|
|
}
|
|
});
|
|
|
|
// recheck atomic result
|
|
if (old.value == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool semaphore_t::try_post()
|
|
{
|
|
// check m_value without interlocked op
|
|
if (m_var.load().value >= max_value)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// try to increment m_value atomically
|
|
const auto old = m_var.fetch_op([&](sync_var_t& var)
|
|
{
|
|
if (var.value < max_value)
|
|
{
|
|
var.value++;
|
|
}
|
|
});
|
|
|
|
// recheck atomic result
|
|
if (old.value >= max_value)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (old.waiters)
|
|
{
|
|
// notify waiting thread
|
|
std::lock_guard<std::mutex> lock(m_mutex);
|
|
|
|
m_cv.notify_one();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void semaphore_t::wait()
|
|
{
|
|
if (m_var.atomic_op([](sync_var_t& var) -> bool
|
|
{
|
|
if (var.value)
|
|
{
|
|
var.value--;
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
//var.waiters++;
|
|
|
|
return false;
|
|
}
|
|
}))
|
|
{
|
|
return;
|
|
}
|
|
|
|
std::unique_lock<std::mutex> lock(m_mutex);
|
|
|
|
m_var.atomic_op([](sync_var_t& var)
|
|
{
|
|
var.waiters++;
|
|
});
|
|
|
|
while (!m_var.atomic_op([](sync_var_t& var) -> bool
|
|
{
|
|
if (var.value)
|
|
{
|
|
var.value--;
|
|
var.waiters--;
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}))
|
|
{
|
|
m_cv.wait(lock);
|
|
}
|
|
}
|
|
|
|
bool semaphore_t::post_and_wait()
|
|
{
|
|
// TODO: merge these functions? Probably has a race condition.
|
|
if (try_wait()) return false;
|
|
|
|
try_post();
|
|
wait();
|
|
|
|
return true;
|
|
}
|