All checks were successful
continuous-integration/drone/push Build is passing
This method looks for the first bit with a value, optionally from a starting index, and returns its index. This should be (haven't benchmarked) way faster than the manual way, AKA what MM and KernelVM were doing. This is due to this method using bit and byte manipulation tricks instead of just calling get() until getting the desired result :)
108 lines
1.9 KiB
C++
108 lines
1.9 KiB
C++
#pragma once
|
|
#include "Log.h"
|
|
#include "arch/CPU.h"
|
|
#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:
|
|
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)
|
|
{
|
|
}
|
|
|
|
#ifndef LOCKED_VALUE_DEBUG
|
|
LockedValueGuard lock()
|
|
{
|
|
m_lock.lock();
|
|
return { *this };
|
|
}
|
|
#else
|
|
LockedValueGuard lock()
|
|
{
|
|
if (m_lock.try_lock()) { return { *this }; }
|
|
|
|
kwarnln("Spinning on a locked LockedValue. This might lead to a deadlock...");
|
|
|
|
CPU::print_stack_trace();
|
|
|
|
m_lock.lock();
|
|
return { *this };
|
|
}
|
|
#endif
|
|
|
|
Option<LockedValueGuard> try_lock()
|
|
{
|
|
if (m_lock.try_lock()) { return { *this }; }
|
|
return {};
|
|
}
|
|
|
|
private:
|
|
T m_value;
|
|
Spinlock m_lock;
|
|
};
|