86 lines
1.3 KiB
C
86 lines
1.3 KiB
C
|
#pragma once
|
||
|
#include <luna/Atomic.h>
|
||
|
|
||
|
class Spinlock
|
||
|
{
|
||
|
public:
|
||
|
void lock();
|
||
|
void unlock();
|
||
|
|
||
|
bool is_locked() const
|
||
|
{
|
||
|
return m_lock.load() != -1;
|
||
|
}
|
||
|
|
||
|
// Call this before use if the Spinlock is a global variable.
|
||
|
void init()
|
||
|
{
|
||
|
m_lock = -1;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
Atomic<int> m_lock{-1};
|
||
|
};
|
||
|
|
||
|
template <typename T> class LockedValue
|
||
|
{
|
||
|
struct LockedValueGuard
|
||
|
{
|
||
|
LockedValueGuard(LockedValue& value_ref) : m_value_ref(value_ref)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
~LockedValueGuard()
|
||
|
{
|
||
|
m_value_ref.m_lock.unlock();
|
||
|
}
|
||
|
|
||
|
T& ref()
|
||
|
{
|
||
|
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)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// Call this before use if the LockedValue is a global variable.
|
||
|
void init()
|
||
|
{
|
||
|
m_lock.init();
|
||
|
}
|
||
|
|
||
|
LockedValueGuard lock()
|
||
|
{
|
||
|
m_lock.lock();
|
||
|
return {*this};
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
T m_value;
|
||
|
Spinlock m_lock;
|
||
|
};
|