1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-28 10:17:34 +00:00

AK+Kernel: Make automatically locking RefPtr & co a kernel-only thing

Some time ago, automatic locking was added to the AK smart pointers to
paper over various race conditions in the kernel. Until we've actually
solved the issues in the kernel, we're stuck with the locking.

However, we don't need to punish single-threaded userspace programs with
the high cost of locking. This patch moves the thread-safe variants of
RefPtr, NonnullRefPtr, WeakPtr and RefCounted into Kernel/Library/.
This commit is contained in:
Andreas Kling 2021-10-07 19:12:37 +02:00
parent ca060d8566
commit 5b1f697460
8 changed files with 1418 additions and 470 deletions

View file

@ -6,12 +6,15 @@
#pragma once
#include <AK/Assertions.h>
#include <AK/Atomic.h>
#include <AK/Checked.h>
#include <AK/Noncopyable.h>
#include <AK/Platform.h>
#include <AK/StdLibExtras.h>
#ifdef KERNEL
# include <Kernel/Library/ThreadSafeRefCounted.h>
#else
# include <AK/Assertions.h>
# include <AK/Checked.h>
# include <AK/Noncopyable.h>
# include <AK/Platform.h>
# include <AK/StdLibExtras.h>
namespace AK {
@ -49,43 +52,32 @@ public:
void ref() const
{
auto old_ref_count = m_ref_count.fetch_add(1, AK::MemoryOrder::memory_order_relaxed);
VERIFY(old_ref_count > 0);
VERIFY(!Checked<RefCountType>::addition_would_overflow(old_ref_count, 1));
VERIFY(m_ref_count > 0);
VERIFY(!Checked<RefCountType>::addition_would_overflow(m_ref_count, 1));
++m_ref_count;
}
[[nodiscard]] bool try_ref() const
{
RefCountType expected = m_ref_count.load(AK::MemoryOrder::memory_order_relaxed);
for (;;) {
if (expected == 0)
return false;
VERIFY(!Checked<RefCountType>::addition_would_overflow(expected, 1));
if (m_ref_count.compare_exchange_strong(expected, expected + 1, AK::MemoryOrder::memory_order_acquire))
return true;
}
if (m_ref_count == 0)
return false;
ref();
return true;
}
[[nodiscard]] RefCountType ref_count() const
{
return m_ref_count.load(AK::MemoryOrder::memory_order_relaxed);
}
[[nodiscard]] RefCountType ref_count() const { return m_ref_count; }
protected:
RefCountedBase() = default;
~RefCountedBase()
{
VERIFY(m_ref_count.load(AK::MemoryOrder::memory_order_relaxed) == 0);
}
~RefCountedBase() { VERIFY(!m_ref_count); }
RefCountType deref_base() const
{
auto old_ref_count = m_ref_count.fetch_sub(1, AK::MemoryOrder::memory_order_acq_rel);
VERIFY(old_ref_count > 0);
return old_ref_count - 1;
VERIFY(m_ref_count);
return --m_ref_count;
}
mutable Atomic<RefCountType> m_ref_count { 1 };
RefCountType mutable m_ref_count { 1 };
};
template<typename T>
@ -109,3 +101,5 @@ public:
using AK::RefCounted;
using AK::RefCountedBase;
#endif