From 88b97f5367693dc6d83b35b2761a6069f1a4b720 Mon Sep 17 00:00:00 2001 From: Ali Mohammad Pur Date: Tue, 20 Apr 2021 13:01:27 +0430 Subject: [PATCH] AK: Make IntrusiveList work with NonnullRefPtr's --- AK/IntrusiveList.h | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/AK/IntrusiveList.h b/AK/IntrusiveList.h index 082a93ac3b..0282f5fad2 100644 --- a/AK/IntrusiveList.h +++ b/AK/IntrusiveList.h @@ -33,15 +33,32 @@ namespace AK { +namespace Detail { template> class IntrusiveListNode; +template +struct SubstituteIntrusiveListNodeContainerType { + using Type = Container; +}; + +template +struct SubstituteIntrusiveListNodeContainerType> { + using Type = RefPtr; +}; +} + +template> +using IntrusiveListNode = Detail::IntrusiveListNode::Type>; + template class IntrusiveListStorage { private: - friend class IntrusiveListNode; + friend class Detail::IntrusiveListNode; + template T_::*member> friend class IntrusiveList; + IntrusiveListNode* m_first { nullptr }; IntrusiveListNode* m_last { nullptr }; }; @@ -132,6 +149,8 @@ template struct SelfReferenceIfNeeded { }; +namespace Detail { + template class IntrusiveListNode { public: @@ -141,15 +160,22 @@ public: static constexpr bool IsRaw = IsPointer; + // Note: For some reason, clang does not consider `member` as declared here, and as declared above (`IntrusiveListNode T::*`) + // to be of equal types. so for now, just make the members public on clang. +#ifndef __clang__ private: template T_::*member> - friend class IntrusiveList; + friend class ::AK::IntrusiveList; +#endif + IntrusiveListStorage* m_storage = nullptr; IntrusiveListNode* m_next = nullptr; IntrusiveListNode* m_prev = nullptr; SelfReferenceIfNeeded m_self; }; +} + template T::*member> inline typename IntrusiveList::Iterator& IntrusiveList::Iterator::erase() { @@ -309,6 +335,8 @@ inline T* IntrusiveList::node_to_value(IntrusiveListNode(bit_cast(&node) - bit_cast(member)); } +namespace Detail { + template inline IntrusiveListNode::~IntrusiveListNode() { @@ -341,12 +369,11 @@ inline bool IntrusiveListNode::is_in_list() const return m_storage != nullptr; } -// Specialise IntrusiveList(Node) for NonnullRefPtr +} + +// Specialise IntrusiveList for NonnullRefPtr // By default, intrusive lists cannot contain null entries anyway, so switch to RefPtr // and just make the user-facing functions deref the pointers. -template -struct IntrusiveListNode> : public IntrusiveListNode> { -}; template> T::*member> class IntrusiveList, member> : public IntrusiveList, member> {