mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-10 21:40:43 +00:00
init_mutex: implement init_always()
This commit is contained in:
parent
db7042b986
commit
2446bb5d40
@ -21,13 +21,31 @@ namespace stx
|
|||||||
init_mutex* _this;
|
init_mutex* _this;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit init_lock(init_mutex& mtx) noexcept
|
template <typename... FAndArgs>
|
||||||
|
explicit init_lock(init_mutex& mtx, FAndArgs&&... args) noexcept
|
||||||
: _this(&mtx)
|
: _this(&mtx)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
// Expect initial (zero) state, don't optimize for least expected cases
|
auto [val, ok] = _this->m_state.fetch_op([](u32& value)
|
||||||
const u32 val = _this->m_state.compare_and_swap(0, 1);
|
{
|
||||||
|
if (val == 0)
|
||||||
|
{
|
||||||
|
val = 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if constexpr (sizeof...(FAndArgs))
|
||||||
|
{
|
||||||
|
if (val & c_init_bit)
|
||||||
|
{
|
||||||
|
val -= c_init_bit - 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
if (val == 0)
|
if (val == 0)
|
||||||
{
|
{
|
||||||
@ -37,12 +55,28 @@ namespace stx
|
|||||||
|
|
||||||
if (val & c_init_bit)
|
if (val & c_init_bit)
|
||||||
{
|
{
|
||||||
|
if constexpr (sizeof...(FAndArgs))
|
||||||
|
{
|
||||||
|
// Forced reset
|
||||||
|
val -= c_init_bit - 1;
|
||||||
|
|
||||||
|
while (val != 1)
|
||||||
|
{
|
||||||
|
// Wait for other users to finish their work
|
||||||
|
_this->m_state.wait(val);
|
||||||
|
val = _this->m_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call specified reset function
|
||||||
|
std::invoke(std::forward<FAndArgs>(args)...);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Failure
|
// Failure
|
||||||
_this = nullptr;
|
_this = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until the state becomes certain
|
|
||||||
_this->m_state.wait(val);
|
_this->m_state.wait(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,6 +120,13 @@ namespace stx
|
|||||||
return init_lock(*this);
|
return init_lock(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same as init, but never fails, and executes provided `on_reset` function if already initialized.
|
||||||
|
template <typename F, typename... Args>
|
||||||
|
[[nodiscard]] init_lock init_always(F on_reset, Args&&... args) noexcept
|
||||||
|
{
|
||||||
|
return init_lock(*this, std::move(on_reset), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
class reset_lock final
|
class reset_lock final
|
||||||
{
|
{
|
||||||
init_mutex* _this;
|
init_mutex* _this;
|
||||||
@ -141,6 +182,16 @@ namespace stx
|
|||||||
}
|
}
|
||||||
|
|
||||||
explicit operator bool() && = delete;
|
explicit operator bool() && = delete;
|
||||||
|
|
||||||
|
void set_init() & noexcept
|
||||||
|
{
|
||||||
|
if (_this)
|
||||||
|
{
|
||||||
|
// Set initialized state (TODO?)
|
||||||
|
_this->m_state |= c_init_bit;
|
||||||
|
_this->m_state.notify_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Obtain exclusive lock to finalize protected resource. Waits for ongoing use. Fails if not initialized.
|
// Obtain exclusive lock to finalize protected resource. Waits for ongoing use. Fails if not initialized.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user