mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 09:17:35 +00:00
AK+Kernel: Add AK::AtomicRefCounted and use everywhere in the kernel
Instead of having two separate implementations of AK::RefCounted, one for userspace and one for kernelspace, there is now RefCounted and AtomicRefCounted.
This commit is contained in:
parent
4889eb019a
commit
e475263113
45 changed files with 81 additions and 94 deletions
|
@ -6,7 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/RefCounted.h>
|
||||
#include <AK/AtomicRefCounted.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
|
@ -21,7 +21,7 @@ enum class LockType {
|
|||
};
|
||||
|
||||
template<typename T, LockType Lock>
|
||||
class ListedRefCounted : public RefCountedBase {
|
||||
class ListedRefCounted : public AtomicRefCountedBase {
|
||||
public:
|
||||
bool unref() const
|
||||
{
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
namespace AK {
|
||||
|
||||
class RefCountedBase {
|
||||
AK_MAKE_NONCOPYABLE(RefCountedBase);
|
||||
AK_MAKE_NONMOVABLE(RefCountedBase);
|
||||
|
||||
public:
|
||||
using RefCountType = unsigned int;
|
||||
using AllowOwnPtr = FalseType;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
[[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;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] RefCountType ref_count() const
|
||||
{
|
||||
return m_ref_count.load(AK::MemoryOrder::memory_order_relaxed);
|
||||
}
|
||||
|
||||
protected:
|
||||
RefCountedBase() = default;
|
||||
~RefCountedBase()
|
||||
{
|
||||
VERIFY(m_ref_count.load(AK::MemoryOrder::memory_order_relaxed) == 0);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
mutable Atomic<RefCountType> m_ref_count { 1 };
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class RefCounted : public RefCountedBase {
|
||||
public:
|
||||
bool unref() const
|
||||
{
|
||||
auto* that = const_cast<T*>(static_cast<T const*>(this));
|
||||
auto new_ref_count = deref_base();
|
||||
if (new_ref_count == 0) {
|
||||
if constexpr (requires { that->will_be_destroyed(); })
|
||||
that->will_be_destroyed();
|
||||
delete that;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using AK::RefCounted;
|
||||
using AK::RefCountedBase;
|
|
@ -168,7 +168,7 @@ template<typename T>
|
|||
template<typename U>
|
||||
inline ErrorOr<WeakPtr<U>> Weakable<T>::try_make_weak_ptr() const
|
||||
{
|
||||
if constexpr (IsBaseOf<RefCountedBase, T>) {
|
||||
if constexpr (IsBaseOf<AtomicRefCountedBase, T>) {
|
||||
// Checking m_being_destroyed isn't sufficient when dealing with
|
||||
// a RefCounted type.The reference count will drop to 0 before the
|
||||
// destructor is invoked and revoke_weak_ptrs is called. So, try
|
||||
|
@ -192,7 +192,7 @@ inline ErrorOr<WeakPtr<U>> Weakable<T>::try_make_weak_ptr() const
|
|||
|
||||
WeakPtr<U> weak_ptr(m_link);
|
||||
|
||||
if constexpr (IsBaseOf<RefCountedBase, T>) {
|
||||
if constexpr (IsBaseOf<AtomicRefCountedBase, T>) {
|
||||
// Now drop the reference we temporarily added
|
||||
if (static_cast<const T*>(this)->unref()) {
|
||||
// We just dropped the last reference, which should have called
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/Atomic.h>
|
||||
#include <AK/RefCounted.h>
|
||||
#include <AK/AtomicRefCounted.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/StdLibExtras.h>
|
||||
#include <Kernel/Arch/Processor.h>
|
||||
|
@ -21,7 +21,7 @@ class Weakable;
|
|||
template<typename T>
|
||||
class WeakPtr;
|
||||
|
||||
class WeakLink : public RefCounted<WeakLink> {
|
||||
class WeakLink final : public AtomicRefCounted<WeakLink> {
|
||||
template<typename T>
|
||||
friend class Weakable;
|
||||
template<typename T>
|
||||
|
@ -30,7 +30,7 @@ class WeakLink : public RefCounted<WeakLink> {
|
|||
public:
|
||||
template<typename T, typename PtrTraits = RefPtrTraits<T>>
|
||||
RefPtr<T, PtrTraits> strong_ref() const
|
||||
requires(IsBaseOf<RefCountedBase, T>)
|
||||
requires(IsBaseOf<AtomicRefCountedBase, T>)
|
||||
{
|
||||
RefPtr<T, PtrTraits> ref;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue