Skip to content

Commit

Permalink
Kernel: Make self-contained locking smart pointers their own classes
Browse files Browse the repository at this point in the history
Until now, our kernel has reimplemented a number of AK classes to
provide automatic internal locking:

- RefPtr
- NonnullRefPtr
- WeakPtr
- Weakable

This patch renames the Kernel classes so that they can coexist with
the original AK classes:

- RefPtr => LockRefPtr
- NonnullRefPtr => NonnullLockRefPtr
- WeakPtr => LockWeakPtr
- Weakable => LockWeakable

The goal here is to eventually get rid of the Lock* classes in favor of
using external locking.
  • Loading branch information
awesomekling committed Aug 20, 2022
1 parent e475263 commit 11eee67
Show file tree
Hide file tree
Showing 360 changed files with 1,704 additions and 1,673 deletions.
29 changes: 21 additions & 8 deletions AK/Forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct Array;
template<typename Container, typename ValueType>
class SimpleIterator;

using ReadonlyBytes = Span<const u8>;
using ReadonlyBytes = Span<u8 const>;
using Bytes = Span<u8>;

template<typename T, AK::MemoryOrder DefaultMemoryOrder>
Expand Down Expand Up @@ -107,25 +107,31 @@ template<typename T>
class NonnullOwnPtr;

template<typename T, size_t inline_capacity = 0>
class NonnullRefPtrVector;
class NonnullOwnPtrVector;

template<typename T, size_t inline_capacity = 0>
class NonnullOwnPtrVector;
class NonnullRefPtrVector;

template<typename T>
class Optional;

#ifdef KERNEL
template<typename T>
struct RefPtrTraits;
class NonnullLockRefPtr;

template<typename T, size_t inline_capacity = 0>
class NonnullLockRefPtrVector;

template<typename T, typename PtrTraits = RefPtrTraits<T>>
class RefPtr;
#else
template<typename T>
class RefPtr;
struct LockRefPtrTraits;

template<typename T, typename PtrTraits = LockRefPtrTraits<T>>
class LockRefPtr;
#endif

template<typename T>
class RefPtr;

template<typename T>
class OwnPtr;

Expand Down Expand Up @@ -192,3 +198,10 @@ using AK::Utf32View;
using AK::Utf8CodePointIterator;
using AK::Utf8View;
using AK::Vector;

#ifdef KERNEL
using AK::LockRefPtr;
using AK::LockRefPtrTraits;
using AK::NonnullLockRefPtr;
using AK::NonnullLockRefPtrVector;
#endif
10 changes: 10 additions & 0 deletions AK/IntrusiveDetails.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

#include <AK/NonnullRefPtr.h>

#ifdef KERNEL
# include <Kernel/Library/LockRefPtr.h>
#endif
namespace AK::Detail {

template<typename T, typename Container>
Expand All @@ -20,6 +23,13 @@ struct SubstituteIntrusiveContainerType<T, NonnullRefPtr<T>> {
using Type = RefPtr<T>;
};

#ifdef KERNEL
template<typename T>
struct SubstituteIntrusiveContainerType<T, NonnullLockRefPtr<T>> {
using Type = LockRefPtr<T>;
};
#endif

template<typename Container, bool _IsRaw>
struct SelfReferenceIfNeeded {
Container reference = nullptr;
Expand Down
46 changes: 33 additions & 13 deletions AK/IntrusiveList.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include <AK/Noncopyable.h>
#include <AK/StdLibExtras.h>

#ifdef KERNEL
# include <Kernel/Library/LockRefPtr.h>
#endif

namespace AK::Detail {

template<typename T, typename Container = RawPtr<T>>
Expand Down Expand Up @@ -56,7 +60,7 @@ class IntrusiveList {
void prepend(T& n);
void insert_before(T&, T&);
void remove(T& n);
[[nodiscard]] bool contains(const T&) const;
[[nodiscard]] bool contains(T const&) const;
[[nodiscard]] Container first() const;
[[nodiscard]] Container last() const;

Expand All @@ -71,7 +75,7 @@ class IntrusiveList {
{
}

const T& operator*() const { return *m_value; }
T const& operator*() const { return *m_value; }
auto operator->() const { return m_value; }
T& operator*() { return *m_value; }
auto operator->() { return m_value; }
Expand Down Expand Up @@ -99,7 +103,7 @@ class IntrusiveList {
{
}

const T& operator*() const { return *m_value; }
T const& operator*() const { return *m_value; }
auto operator->() const { return m_value; }
T& operator*() { return *m_value; }
auto operator->() { return m_value; }
Expand All @@ -122,12 +126,12 @@ class IntrusiveList {
class ConstIterator {
public:
ConstIterator() = default;
ConstIterator(const T* value)
ConstIterator(T const* value)
: m_value(value)
{
}

const T& operator*() const { return *m_value; }
T const& operator*() const { return *m_value; }
auto operator->() const { return m_value; }
bool operator==(ConstIterator const& other) const { return other.m_value == m_value; }
bool operator!=(ConstIterator const& other) const { return !(*this == other); }
Expand All @@ -138,7 +142,7 @@ class IntrusiveList {
}

private:
const T* m_value { nullptr };
T const* m_value { nullptr };
};

ConstIterator begin() const;
Expand All @@ -147,8 +151,8 @@ class IntrusiveList {
private:
static T* next(T* current);
static T* prev(T* current);
static const T* next(const T* current);
static const T* prev(const T* current);
static T const* next(T const* current);
static T const* prev(T const* current);
static T* node_to_value(SubstitutedIntrusiveListNode<T, Container>& node);
IntrusiveListStorage<T, Container> m_storage;
};
Expand Down Expand Up @@ -284,7 +288,7 @@ inline void IntrusiveList<T, Container, member>::remove(T& n)
}

template<class T, typename Container, SubstitutedIntrusiveListNode<T, Container> T::*member>
inline bool IntrusiveList<T, Container, member>::contains(const T& n) const
inline bool IntrusiveList<T, Container, member>::contains(T const& n) const
{
auto& nnode = n.*member;
return nnode.m_storage == &m_storage;
Expand Down Expand Up @@ -323,18 +327,18 @@ inline Container IntrusiveList<T, Container, member>::last() const
}

template<class T, typename Container, SubstitutedIntrusiveListNode<T, Container> T::*member>
inline const T* IntrusiveList<T, Container, member>::next(const T* current)
inline T const* IntrusiveList<T, Container, member>::next(T const* current)
{
auto& nextnode = (current->*member).m_next;
const T* nextstruct = nextnode ? node_to_value(*nextnode) : nullptr;
T const* nextstruct = nextnode ? node_to_value(*nextnode) : nullptr;
return nextstruct;
}

template<class T, typename Container, SubstitutedIntrusiveListNode<T, Container> T::*member>
inline const T* IntrusiveList<T, Container, member>::prev(const T* current)
inline T const* IntrusiveList<T, Container, member>::prev(T const* current)
{
auto& prevnode = (current->*member).m_prev;
const T* prevstruct = prevnode ? node_to_value(*prevnode) : nullptr;
T const* prevstruct = prevnode ? node_to_value(*prevnode) : nullptr;
return prevstruct;
}

Expand Down Expand Up @@ -429,6 +433,22 @@ class IntrusiveList<T, NonnullRefPtr<T>, member> : public IntrusiveList<T, RefPt
[[nodiscard]] NonnullRefPtr<T> take_last() { return *IntrusiveList<T, RefPtr<T>, member>::take_last(); }
};

#ifdef KERNEL
// Specialise IntrusiveList for NonnullLockRefPtr
// By default, intrusive lists cannot contain null entries anyway, so switch to LockRefPtr
// and just make the user-facing functions deref the pointers.

template<class T, SubstitutedIntrusiveListNode<T, NonnullLockRefPtr<T>> T::*member>
class IntrusiveList<T, NonnullLockRefPtr<T>, member> : public IntrusiveList<T, LockRefPtr<T>, member> {
public:
[[nodiscard]] NonnullLockRefPtr<T> first() const { return *IntrusiveList<T, LockRefPtr<T>, member>::first(); }
[[nodiscard]] NonnullLockRefPtr<T> last() const { return *IntrusiveList<T, LockRefPtr<T>, member>::last(); }

[[nodiscard]] NonnullLockRefPtr<T> take_first() { return *IntrusiveList<T, LockRefPtr<T>, member>::take_first(); }
[[nodiscard]] NonnullLockRefPtr<T> take_last() { return *IntrusiveList<T, LockRefPtr<T>, member>::take_last(); }
};
#endif

}

namespace AK {
Expand Down
35 changes: 15 additions & 20 deletions AK/NonnullRefPtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@

#define NONNULLREFPTR_SCRUB_BYTE 0xe1

#ifdef KERNEL
# include <Kernel/Library/ThreadSafeNonnullRefPtr.h>
#else
# include <AK/Assertions.h>
# include <AK/Atomic.h>
# include <AK/Format.h>
# include <AK/Traits.h>
# include <AK/Types.h>
#include <AK/Assertions.h>
#include <AK/Atomic.h>
#include <AK/Format.h>
#include <AK/Traits.h>
#include <AK/Types.h>

namespace AK {

Expand Down Expand Up @@ -98,9 +95,9 @@ class [[nodiscard]] NonnullRefPtr {
{
unref_if_not_null(m_ptr);
m_ptr = nullptr;
# ifdef SANITIZE_PTRS
#ifdef SANITIZE_PTRS
m_ptr = reinterpret_cast<T*>(explode_byte(NONNULLREFPTR_SCRUB_BYTE));
# endif
#endif
}

template<typename U>
Expand Down Expand Up @@ -163,7 +160,7 @@ class [[nodiscard]] NonnullRefPtr {
{
return as_nonnull_ptr();
}
ALWAYS_INLINE RETURNS_NONNULL const T* ptr() const
ALWAYS_INLINE RETURNS_NONNULL T const* ptr() const
{
return as_nonnull_ptr();
}
Expand All @@ -172,7 +169,7 @@ class [[nodiscard]] NonnullRefPtr {
{
return as_nonnull_ptr();
}
ALWAYS_INLINE RETURNS_NONNULL const T* operator->() const
ALWAYS_INLINE RETURNS_NONNULL T const* operator->() const
{
return as_nonnull_ptr();
}
Expand All @@ -181,7 +178,7 @@ class [[nodiscard]] NonnullRefPtr {
{
return *as_nonnull_ptr();
}
ALWAYS_INLINE const T& operator*() const
ALWAYS_INLINE T const& operator*() const
{
return *as_nonnull_ptr();
}
Expand All @@ -190,7 +187,7 @@ class [[nodiscard]] NonnullRefPtr {
{
return as_nonnull_ptr();
}
ALWAYS_INLINE RETURNS_NONNULL operator const T*() const
ALWAYS_INLINE RETURNS_NONNULL operator T const*() const
{
return as_nonnull_ptr();
}
Expand All @@ -199,7 +196,7 @@ class [[nodiscard]] NonnullRefPtr {
{
return *as_nonnull_ptr();
}
ALWAYS_INLINE operator const T&() const
ALWAYS_INLINE operator T const&() const
{
return *as_nonnull_ptr();
}
Expand Down Expand Up @@ -245,10 +242,10 @@ inline NonnullRefPtr<T> adopt_ref(T& object)
}

template<typename T>
struct Formatter<NonnullRefPtr<T>> : Formatter<const T*> {
struct Formatter<NonnullRefPtr<T>> : Formatter<T const*> {
ErrorOr<void> format(FormatBuilder& builder, NonnullRefPtr<T> const& value)
{
return Formatter<const T*>::format(builder, value.ptr());
return Formatter<T const*>::format(builder, value.ptr());
}
};

Expand All @@ -275,13 +272,11 @@ inline NonnullRefPtr<T> make_ref_counted(Args&&... args)
template<typename T>
struct Traits<NonnullRefPtr<T>> : public GenericTraits<NonnullRefPtr<T>> {
using PeekType = T*;
using ConstPeekType = const T*;
using ConstPeekType = T const*;
static unsigned hash(NonnullRefPtr<T> const& p) { return ptr_hash(p.ptr()); }
static bool equals(NonnullRefPtr<T> const& a, NonnullRefPtr<T> const& b) { return a.ptr() == b.ptr(); }
};

using AK::adopt_ref;
using AK::make_ref_counted;
using AK::NonnullRefPtr;

#endif
Loading

0 comments on commit 11eee67

Please sign in to comment.