AK: Make IntrusiveList work with NonnullRefPtr's

This commit is contained in:
Ali Mohammad Pur 2021-04-20 13:01:27 +04:30 committed by Linus Groh
parent 3857148028
commit 88b97f5367
Notes: sideshowbarker 2024-07-18 19:15:23 +09:00

View file

@ -33,15 +33,32 @@
namespace AK { namespace AK {
namespace Detail {
template<typename T, typename Container = RawPtr<T>> template<typename T, typename Container = RawPtr<T>>
class IntrusiveListNode; class IntrusiveListNode;
template<typename T, typename Container>
struct SubstituteIntrusiveListNodeContainerType {
using Type = Container;
};
template<typename T>
struct SubstituteIntrusiveListNodeContainerType<T, NonnullRefPtr<T>> {
using Type = RefPtr<T>;
};
}
template<typename T, typename Container = RawPtr<T>>
using IntrusiveListNode = Detail::IntrusiveListNode<T, typename Detail::SubstituteIntrusiveListNodeContainerType<T, Container>::Type>;
template<typename T, typename Container> template<typename T, typename Container>
class IntrusiveListStorage { class IntrusiveListStorage {
private: private:
friend class IntrusiveListNode<T, Container>; friend class Detail::IntrusiveListNode<T, Container>;
template<class T_, typename Container_, IntrusiveListNode<T_, Container_> T_::*member> template<class T_, typename Container_, IntrusiveListNode<T_, Container_> T_::*member>
friend class IntrusiveList; friend class IntrusiveList;
IntrusiveListNode<T, Container>* m_first { nullptr }; IntrusiveListNode<T, Container>* m_first { nullptr };
IntrusiveListNode<T, Container>* m_last { nullptr }; IntrusiveListNode<T, Container>* m_last { nullptr };
}; };
@ -132,6 +149,8 @@ template<typename Contained>
struct SelfReferenceIfNeeded<Contained, true> { struct SelfReferenceIfNeeded<Contained, true> {
}; };
namespace Detail {
template<typename T, typename Container> template<typename T, typename Container>
class IntrusiveListNode { class IntrusiveListNode {
public: public:
@ -141,15 +160,22 @@ public:
static constexpr bool IsRaw = IsPointer<Container>; static constexpr bool IsRaw = IsPointer<Container>;
// Note: For some reason, clang does not consider `member` as declared here, and as declared above (`IntrusiveListNode<T, Container> T::*`)
// to be of equal types. so for now, just make the members public on clang.
#ifndef __clang__
private: private:
template<class T_, typename Container_, IntrusiveListNode<T_, Container_> T_::*member> template<class T_, typename Container_, IntrusiveListNode<T_, Container_> T_::*member>
friend class IntrusiveList; friend class ::AK::IntrusiveList;
#endif
IntrusiveListStorage<T, Container>* m_storage = nullptr; IntrusiveListStorage<T, Container>* m_storage = nullptr;
IntrusiveListNode<T, Container>* m_next = nullptr; IntrusiveListNode<T, Container>* m_next = nullptr;
IntrusiveListNode<T, Container>* m_prev = nullptr; IntrusiveListNode<T, Container>* m_prev = nullptr;
SelfReferenceIfNeeded<Container, IsRaw> m_self; SelfReferenceIfNeeded<Container, IsRaw> m_self;
}; };
}
template<class T, typename Container, IntrusiveListNode<T, Container> T::*member> template<class T, typename Container, IntrusiveListNode<T, Container> T::*member>
inline typename IntrusiveList<T, Container, member>::Iterator& IntrusiveList<T, Container, member>::Iterator::erase() inline typename IntrusiveList<T, Container, member>::Iterator& IntrusiveList<T, Container, member>::Iterator::erase()
{ {
@ -309,6 +335,8 @@ inline T* IntrusiveList<T, Container, member>::node_to_value(IntrusiveListNode<T
return bit_cast<T*>(bit_cast<unsigned char*>(&node) - bit_cast<unsigned char*>(member)); return bit_cast<T*>(bit_cast<unsigned char*>(&node) - bit_cast<unsigned char*>(member));
} }
namespace Detail {
template<typename T, typename Container> template<typename T, typename Container>
inline IntrusiveListNode<T, Container>::~IntrusiveListNode() inline IntrusiveListNode<T, Container>::~IntrusiveListNode()
{ {
@ -341,12 +369,11 @@ inline bool IntrusiveListNode<T, Container>::is_in_list() const
return m_storage != nullptr; 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 // By default, intrusive lists cannot contain null entries anyway, so switch to RefPtr
// and just make the user-facing functions deref the pointers. // and just make the user-facing functions deref the pointers.
template<typename T>
struct IntrusiveListNode<T, NonnullRefPtr<T>> : public IntrusiveListNode<T, RefPtr<T>> {
};
template<class T, IntrusiveListNode<T, NonnullRefPtr<T>> T::*member> template<class T, IntrusiveListNode<T, NonnullRefPtr<T>> T::*member>
class IntrusiveList<T, NonnullRefPtr<T>, member> : public IntrusiveList<T, RefPtr<T>, member> { class IntrusiveList<T, NonnullRefPtr<T>, member> : public IntrusiveList<T, RefPtr<T>, member> {