diff --git a/kernel/src/thread/Spinlock.cpp b/kernel/src/thread/Spinlock.cpp index 8184a029..45cde161 100644 --- a/kernel/src/thread/Spinlock.cpp +++ b/kernel/src/thread/Spinlock.cpp @@ -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; diff --git a/kernel/src/thread/Spinlock.h b/kernel/src/thread/Spinlock.h index 3553752c..28cd0e57 100644 --- a/kernel/src/thread/Spinlock.h +++ b/kernel/src/thread/Spinlock.h @@ -1,5 +1,6 @@ #pragma once #include +#include 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 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 class LockedValue } private: - LockedValue& m_value_ref; + LockedValue* m_value_ref; }; public: @@ -68,6 +79,12 @@ template class LockedValue return {*this}; } + Option try_lock() + { + if (m_lock.try_lock()) { return {*this}; } + return {}; + } + private: T m_value; Spinlock m_lock;