Spinlock+LockedValue: Add try_lock() methods
All checks were successful
continuous-integration/drone/push Build is passing

For when you want to lock a resource if possible but not get blocked if it is locked by another thread.
This commit is contained in:
apio 2022-12-18 20:37:26 +01:00
parent 283e641ece
commit 0bdbffe0ca
Signed by: apio
GPG Key ID: B8A7D06E42258954
2 changed files with 27 additions and 4 deletions

View File

@ -12,6 +12,12 @@ void Spinlock::lock()
}
}
bool Spinlock::try_lock()
{
int expected = 0;
return m_lock.compare_exchange_strong(expected, 1);
}
void Spinlock::unlock()
{
int expected = 1;

View File

@ -1,5 +1,6 @@
#pragma once
#include <luna/Atomic.h>
#include <luna/Option.h>
class Spinlock
{
@ -7,6 +8,8 @@ class Spinlock
void lock();
void unlock();
bool try_lock();
bool is_locked() const
{
return m_lock.load() != 0;
@ -20,18 +23,26 @@ template <typename T> class LockedValue
{
struct LockedValueGuard
{
LockedValueGuard(LockedValue& value_ref) : m_value_ref(value_ref)
LockedValueGuard(LockedValue& value_ref) : m_value_ref(&value_ref)
{
}
LockedValueGuard(const LockedValueGuard& other) = delete;
LockedValueGuard(LockedValueGuard&& other)
{
m_value_ref = other.m_value_ref;
other.m_value_ref = nullptr;
}
~LockedValueGuard()
{
m_value_ref.m_lock.unlock();
if (m_value_ref) m_value_ref->m_lock.unlock();
}
T& ref()
{
return m_value_ref.m_value;
expect(m_value_ref, "LockedValueGuard::ref() called on a moved LockedValueGuard");
return m_value_ref->m_value;
}
void set(const T& other)
@ -50,7 +61,7 @@ template <typename T> class LockedValue
}
private:
LockedValue& m_value_ref;
LockedValue* m_value_ref;
};
public:
@ -68,6 +79,12 @@ template <typename T> class LockedValue
return {*this};
}
Option<LockedValueGuard> try_lock()
{
if (m_lock.try_lock()) { return {*this}; }
return {};
}
private:
T m_value;
Spinlock m_lock;