Luna/kernel/src/thread/Spinlock.h

92 lines
1.6 KiB
C
Raw Normal View History

#pragma once
#include <luna/Atomic.h>
#include <luna/Option.h>
class Spinlock
{
public:
void lock();
void unlock();
bool try_lock();
bool is_locked() const
{
return m_lock.load() != 0;
}
private:
2022-12-21 19:22:44 +00:00
Atomic<int> m_lock { 0 };
};
template <typename T> class LockedValue
{
struct LockedValueGuard
{
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()
{
if (m_value_ref) m_value_ref->m_lock.unlock();
}
T& ref()
{
expect(m_value_ref, "LockedValueGuard::ref() called on a moved LockedValueGuard");
return m_value_ref->m_value;
}
void set(const T& other)
{
ref() = other;
}
T* operator->()
{
return &ref();
}
T& operator*()
{
return ref();
}
private:
LockedValue* m_value_ref;
};
public:
LockedValue() : m_value()
{
}
LockedValue(T value) : m_value(value)
{
}
LockedValueGuard lock()
{
m_lock.lock();
2022-12-21 19:22:44 +00:00
return { *this };
}
Option<LockedValueGuard> try_lock()
{
2022-12-21 19:22:44 +00:00
if (m_lock.try_lock()) { return { *this }; }
return {};
}
private:
T m_value;
Spinlock m_lock;
2023-01-02 12:07:29 +00:00
};